字符,字符串函数和内存 *** 作函数

字符,字符串函数和内存 *** 作函数,第1张

字符,字符串函数和内存 *** 作函数
  • 求字符串长度
    • strlen
  • 长度不受限制的字符串函数
    • strcpy
    • strcat
    • strcmp
  • 长度受限制的字符串函数介绍
    • strncpy
    • strncat
    • strncmp
  • 字符串查找
    • strstr
    • strtok
  • 错误信息报告
    • strerror
  • 字符 *** 作
  • 内存 *** 作函数
    • memcpy
    • memmove
    • memset
    • memcmp

求字符串长度 strlen

strlen
strlen 计算字符串’\0’之前的个数,只适用于字符串。

  1. 字符串已 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包
    含 ‘\0’ )。
  2. 参数指向的字符串必须要以 ‘
  3. 注意函数的返回值为size_t,是无符号的( 易错 )
  4. ’ 结束。#

size_t是无符号整型(unsigned int)在C语言库中的重定义

练习

includeint 
main ()const
{
 char *=str1 "abcdef" ;const
 char *=str2 "bbb" ;if
 (strlen()str2-strlen()str10>)printf
 {
 ()"str2>str1\n";}
 else 
 printf
 {
 ()"srt1>str2\n";}
 return
 0 ;} size_t

解释一下
输出结果:str2>str1,因为strlen的返回类型是size_t,无符号数减无符号数还是无符号数,所以大于0.
模拟实现strlen
循环实现

my_strlen (constchar *) strassert
{
	(!=str NULL );size_t
	= i 0 ;while

	( *++str)++
	{
		i;}
	return

	; i}
size_t

递归实现
不能创建临时变量计数器

my_strlen (constchar *) strif
{
	( *==str ')' return0
		; return(

	1 +my_strlen ( +1str ) );}
  • 源字符串必须以 ‘
  • 会将源字符串中的 ‘
  • 目标空间必须足够大,以确保能存放源字符串。
  • ’ 拷贝到目标空间。’ 结束。
  • 目标空间必须可变。
  • 长度不受限制的字符串函数 strcpy

    strcpy
    strcpy字符串拷贝,只适用于字符串。

    destination:目的地
    source:源

      char*my_strcpy(

    证明\0会被拷贝

    模拟实现

    char* ,constchar* destination) assert (!= sourceNULL
    {
    	);destination assert (!=NULL
    	);source char *=;
    
    	while( p * destination++
    
    	= *++destination)//当*source=';'赋给*destination时,这时*destination='//空语句',为假,循环终止,所以这种写法很妙。 }sourcereturn;}
    	{
    		
  • 源字符串必须以 ‘
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • ’ 结束。
  • 目标空间必须可修改。
  • char * pmy_strcat (
    strcat

    strcat:
    strcat:字符串追加,只适用于字符串。

      char*,

    strcat函数不能自己给自己追加。
    模拟实现

    constchar *)assert( destination!= NULL ); sourceassert
    {
    	(!=destination NULL );char
    	*=source ; while(*
    
    	)++ p ; destination}
    
    	while (*destination++
    	{
    		destination=*
    	++
    	) ;}destinationreturn ; }source
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • {
  • 第一个字符串小于第二个字符串,则返回小于0的数字
  • int my_strcmp p( const
    strcmp

    strcmp
    strcmp:字符串比较函数,只适用于字符串。

    C语言标准规定:

      char*,

    字符串是如何比较那

    模拟实现
    两种方法都符合C语言规定。
    方法1

    const char*) assert( str1!= NULL ); str2assert
    {
    	(!=str1 NULL );while
    	(*str2 ++ ==*++
    
    	) if(str1* == '&&'str2*==
    	{
    		')' return0str1 ; } } ifstr2 (**
    		{
    			) return1
    		;
    	}
    	else return-str1 > 1str2;
    	{
    		} }int
    	my_strcmp
    	(
    	{
    		const char*,
    	const
    char
    

    方法2

    * )assert( !=NULL str1) ; assert( str2!=
    {
    	NULL)str1 ; while(*
    	++==str2 * ++)if
    
    	( *==str1'&&' * ==str2')'return
    	{
    		0 ;}str1 } return ( (str2 *)-
    		{
    			( *)
    		)
    	;
    	
    	} 
  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个.
  • charstr1* my_strncpy (charstr2*,const char
    长度受限制的字符串函数介绍 strncpy

    strncpy
    strncpy:拷贝num个字符从源字符串到目标空间,注意strncpy与strcpy不一样,只适用于字符串。

      *,


    模拟实现

    size_t) assert(!=NULL destination) ; assert( source!=NULL num)
    {
    	;chardestination * =;while
    	(--source ) if(*
    
    	)* p ++ destination=
    
    	* ++num;}
    	{
    		else *++source=
    		{
    			';'destination} } returnsource;}
    		
  • 将源的前 num 个字符追加到目标,外加一个终止空字符。
  • 如果源中 C 字符串的长度小于 num,则仅复制到终止空字符之前的内容。
  • { chardestination* my_strncat (char * , const pchar *
    strncat

    strncat
    strncat:追加指定字符个数,只适用于字符串。

      ,size_t

    模拟实现

    )assert (!=NULL) destination; assert (!= sourceNULL ) num;
    {
    	char*destination = ;while(
    	*)source //找到destination的'++'的位置 ;}while
    
    	(-- p ) destinationif
    
    	(*)destination//判断*source是否为'*',为'++'就不在进去。=
    	{
    		destination*++
    	;
    	} }num*=
    	{
    		';' return;source}
  • 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
  • { intdestinationmy_strncmp ( constsourcechar* , const chardestination * ,size_t ) passert (
    strncmp

    strncmp
    strncmp:比较指定个数的字符串大小,只适用于字符串


      !=

    模拟实现

    NULL );assert (!= str1NULL ) ;while str2( -- num)
    {
    	if(str1 * !=*)
    	if(str2 * *)return
    
    	1 ;numelsereturn
    	{
    		- 1;str1 } ifstr2(
    		{
    			* !='||'str1 > *str2!=
    				')' //如果两个字符相等但是输入超过两个字符串的个数,使字符一直保持相等。++
    			;
    				++ ;}}
    		return
    		0 ;}str1 char * my_strstr (str2 const char*,
    		{
    			str1constchar
    			str2*)
    		assert
    	(
    
    	!= NULL)
    ;
    
    字符串查找 strstr

    strstr
    strstr:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL,只适用于字符串。

    实现原理
    图1

    图2

    图3

    模拟实现

    assert( !=NULL) ;/* char* p1 = str1;
    	char* p2 = str2;*/ str1//一般我们把一个类型限制严格的变量,赋给一个类型限制不怎么严格变量时,编译器会报警告。 const char* str2=
    {
    	;conststr1 char *=;
    	if(str2 * ==')'return
    
       ;
    	while
    
    	( *) p1 = str1;
    	while (* p2 != str2'&&'
    
    	* !='&&'str1 ( *==
    		* str1)
    	) //一直找到*p2与*p1不相等++str1;
    	{
    		p1++ str1;
    
    		} if(p1 * == ')' //如果p2='return'证明找完了p2 ; //找到了 } ++;p1 = ;p2}returnNULL
    		{
    			p1;//找不到子串
    			p2}
  • sep参数是个字符串,定义了用作分隔符的字符集合
  • # include #includep2 int main() { char str1[] = str1"- This, a sample string."; p2 char str2* ; printf ("Splitting string \"%s\" into tokens:\n", )
    strtok

      ;
    1. 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标
      记。
    2. strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
      strtok函数会改变被 *** 作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
      并且可修改。)
    3. strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
      中的位置。
    4. strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
      记。
    5. 如果字符串中不存在更多的标记,则返回 NULL 指针。
      使用演示
    =strtok 
    (, 
    " ,.-" ) ;while
    {
      ( str!=NULL )printf(
      "%s\n" , pch)
      ; =strtok(strNULL,
      pch " ,.-" ) ;str}return0;
      } #pch include intmain
     {
        ( )char*pch="zhangsan@bitedu.tech"
        pch ; const char*= ".@";char
     [
      30 ]; char
    
    *= 
    NULL ;strcpy(
    {
       , )p ; //将数据拷贝一份,处理arr数组的内容for
     ( =strtok sep ( ,)
     ; arr!=NULL;=
     strtok (str NULL ,)
     )printfarr( p"%s\n",)
     ;}str}#includearr# sepinclude# str include //必须包含的头文件int strmain()*; sep=fopen
     {
     ("unexist.ent","r" str);
     if
    (
    
    错误信息报告 strerror

    strerror:返回错误码,所对应的错误信息。

    使用演示

    ==NULL 
    )printf 
    ("Error opening file unexist.ent: %s\n" ,
    strerror ())
    {
    	FILE; pFile//errno: Last error number
    	pFile return 0;}# include#include
    	int mainpFile ( )int
    		=0;char []errno="Test String.\n";
    	char
    	; while(
    [
    
    字符 *** 作

    字符分类函数:

    使用演示

    ]) 
    =[ 
    ] ;if(
    {
    	isupper i ( ))
    	= strtolower( ) ;putchar
    	( c)
    	; ++str;i}return
    	{
    		c 0 str;i}
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 ‘
  • 如果source和destination有任何的重叠,复制的结果都是未定义的
  • ’ 的时候并不会停下来。 void*my_memcpyc(void c * ,constcvoid* ,size_tc)assert i(!= NULL ) ;assert (
    内存 *** 作函数 memcpy

    memcpy
    memcpy:从源source所指的内存地址的起始位置开始拷贝num个字节到目标destination所指的内存地址的起始位置中。注意:(内存 *** 作函数)

    注意: 根据类型的大小确定num的大小。

      !=NULL)

    模拟实现

    ;void *=;while destination( -- )* source( char num*
    {
    	)=destination * (char*
    	);source = (char*
    
    	)+ p 1 destination;
    
    	= (numchar*
    	{
    		)+1;}destination return ;}
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
  • voidsource* destination my_memmove (void*,destination const void* source , size_t)assert(source != NULL) ; assert p( !=

    注意: C语言规定memcpy只能拷贝,起始地址不一的两个空间,但是VS中实现的可以拷贝起始地址一样的空间。
    C语言中要拷贝两个一样的起始地址,用的函数是memmove.因此我们在使用函数时要考虑函数的跨平台性。

    memmove

      NULL)

    函数实现原理

    ;void *=;if destination( < )//前向前 sourcewhile ( num--
    {
    	)*destination ( char*)
    	=*source ( char*)
    
    	;= p ( destinationchar
    
    	* )destination + source1;
    	{
    		= (numchar*
    		{
    			)+1;}destination } else//后向后while(--source)
    			destination * ((char*destination ) +)
    			source = *((charsource * )+
    		)
    	;
    	}}
    	{
    		return ;num}int
    		{
    			main()char[]destination=num"abcdefj" ; memset(,'*',3source)num;printf
    		(
    	"%s"
    
    	, p)
    ;
    
    memset

    memset
    memset:将 ptr 所指向的内存块的前 num 个字节设置为指定的值(解释为无符号字符)。

    使用演示

    int []=
    {
    	10 arr,2 , 3,
    	4,arr5 ,6 ,7,
    	8,9} arr;memset
    	( arr1,1 , { 8);return0;}
  • 比较从ptr1和ptr2指针开始的num个字节
  • #include#includeintmain()char [] ="DWgaOtP12df0"arr1; char[ ]="DWGAOTP12DF0" ; int; =
    memcmp
      memcmp
    1. 返回值如下

      使用演示
    (, 
    ,sizeof 
    ( ) );
    {
      if buffer1(0 ) printf(
      "'%s' is greater than '%s'.\n" buffer2,, ) ;else
      if n(
      n<0 ) buffer1printf buffer2( "'%s' is less than '%s'.\n",buffer1, );
      else printfn>("'%s' is the same as '%s'.\n" , ,);buffer1returnbuffer20;
      }  n  buffer1buffer2
        buffer1buffer2
        
    

    欢迎分享,转载请注明来源:内存溢出

    原文地址: http://outofmemory.cn/langs/2991216.html

    (0)
    打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
    上一篇 2022-09-23
    下一篇 2022-09-23

    发表评论

    登录后才能评论

    评论列表(0条)

    保存