打印
[经验分享]

string.h库函数

[复制链接]
3116|42
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1988020566|  楼主 | 2024-8-13 20:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <REG51.h>    //包含头文件REG51.h,使能51内部寄存器;

//#include <intrins.h>  //包含头文件intrins.h,要放在stdio.h的头文件之前;

//使能函数: _nop_();  相当于汇编的NOP指令;

//使能函数: bit  _testbit_( bit bit_value ); 对bit_value进行测试,若bit_value=1,返回1,

//否则返回0;

//使能函数: unsigned char _cror_( unsigned char x, unsigned char n ); 将字节型变量x的值,向

//右循环移动n位,相当于汇编的RR A命令;

//使能函数: unsigned int  _iror_( unsigned int x,  unsigned char n ); 将双字节型变量x的值,

//向右循环移动n位,相当于汇编的RR A命令;

//使能函数: unsigned long _lror_( unsigned long x, unsigned char n ); 将4字节型变量x的值,

//向右循环移动n位,相当于汇编的RR A命令;

//使能函数: unsigned char _crol_( unsigned char x, unsigned char n ); 将字节型变量x的值,向

//左循环移动n位,相当于汇编的RL A命令;

//使能函数: unsigned int  _irol_( unsigned int x,  unsigned char n ); 将双字节型变量x的值,向左循环移动n位,相当于汇编的RL A命令;

//使能函数: unsigned long _lrol_( unsigned long x, unsigned char n ); 将4字节型变量x的值,

//向左循环移动n位,相当于汇编的RL A命令;

//以上的循环左移和循环右移,同C语言的左移和右移是不同的,使用时要小心;

#include <string.h>

//void *memchr(void *s,char val,int n);

//在字符串数组s[]中,搜索前n个字符,查找是否具有val的值,若有,则返回指向val的指针,否则返回

//NULL;

//char memcmp (void *s1, void *s2, int n);

//比较字符串数组s1[]和字符串数组s2[]的前n个字符是否相等,若相等,则返回0;

//若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;

//char strncmp (char *s1, char *s2, int n);

//比较字符串数组s1[]和字符串数组s2[]的前n个字符是否相等,若相等,则返回0;

//若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;

//char strcmp (char *s1, char *s2);

//比较字符串数组s1[]和字符串数组s2[],若s1=s2则返回0,表示这两个字符串是相同的;

//若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;

//char *strcpy (char *s1, char *s2);

//将字符串数组s2[]的字符(包括结束符)拷贝到数组s1[]中,并将数组s1[]的首地址返回;

//char *strncpy (char *s1, char *s2, int n);

//将字符串数组s2[]的前n个字符拷贝到数组s1[]中,若s2的长度小于n,则用0补齐到长度

//n,拷贝到s1中,并将数组s1[]的首地址返回;

//void *memcpy (void *s1, void *s2, int n);

//将字符串数组s2[]的前n个字符拷贝到数组s1[]中,并将数组s1[]的首地址返回;

//注意:s1[]和s2[]是互相独立,没有重叠;

//void *memccpy (void *s1, void *s2, char val, int n);

//将字符串数组s2[]的前n个字符拷贝到数组s1[]中,若拷贝了n个字符,没有遇到val的值,

//则返回NULL;

//在拷贝过程中,若遇到val的值,则在拷贝完该字符后,将指向s1[]的下一个元素的指针返回;

//void *memmove (void *s1, void *s2, int n);

//将字符串数组s2[]的前n个字符拷贝到数组s1[]中,并将数组s1[]的首地址返回;

//注意:s2[]可以是s1[]的一部分,即有重叠部分;

//void *memset  (void *s, char val, int n);

//将s[]的前n个元素设置为val的值;

//char *strcat (char *s1, char *s2);

//将字符串数组s2[]拷贝到字符串数组s1[]的尾部,并将s1[]的首字符指针返回;

//注意:s1[]要可以接受s2的字符串;

//char *strncat (char *s1, char *s2, int n);

//将字符串数组s2[]的前n个字符拷贝到字符串数组s1[]的尾部,并将s1[]的首字符指针返回;

//若字串数组s2[]的元素个数小于n,则只拷贝到s2的结束符,就停止拷贝;

//int strlen (char *s1); //返回字符串s1[]中的字符个数,包括结束符'\0';

//char *strchr (const char *s, char c);

//在s[]中搜索c的值并将第1次出现c值的指针返回,若没有搜索到,则返回NULL;

//int strpos (const char *s, char c);

//在s[]中搜索c的值并将第1次出现c值的位置值返回,若没有搜索到,则返回-1;

//char *strrchr (const char *s, char c);

//在s[]中搜索c的值并将最后1个出现c值的指针返回,若没有搜索到,则返回NULL;

//int strrpos (const char *s, char c);

//在s[]中搜索c的值并将最后1个出现c值的位置值返回,若没有搜索到,则返回-1;

//char *strstr  (char *s, char *sub);

//在s[]中搜索字符串数组sub[]的字符串,并将第1次出现"sub[]的字符串"的指针返回,若没有

//搜索到,则返回NULL;

#include <stdio.h>  //包含头文件stdio.h

       //_getkey();从串口读入一个字符;

   //putchar();向串口发送一个字节;

   //printf();向串口发送一串字节;

//函数功能:测试memchr()函数;

void test_memchr(void)

{ char s[15]="It is test!";

  void *ptr;

  ptr=memchr( s,'!',sizeof(s) ); //在字符串s[]中,搜索所有字符,查找是否具有!的值,若有,

//则返回指向!的指针,否则返回NULL;

  if( ptr==NULL) printf( "! was not found in s[10].\n");

  else printf( "Found ! in s[10].\n" );

}

//函数功能:测试memcmp()函数;

void test_memcmp()

{ char s1[16]="0123456789ABCDEF";

  char s2[16]="0123456789abcdef";

  char i;

  i=memcmp(s1,s2,16);

       //比较字符串数组s1[]和字符串数组s2[]的前n个字符是否相等,若相等,则返回0,

       //若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;

  if(i==0) printf("s1[16]==s2[16],return value = 0.\n");

  else if(i>0) printf("s1[16>]=s2[16],return value is > 0.\n");

  else printf("s1[16]<s2[16],return value < 0.\n");

}

//函数功能:测试memcpy()函数;

void test_memcpy()

{ char s2[]="12345678";

  char s1[11]="aaaaaaaaaa";

  char *ptr;

  ptr=memcpy( s1,s2,sizeof(s1) );

    //将字符串数组s2[]的前9个字符拷贝到数组s1[]中,并将数组s1[]的首地址返回;

  printf( "s1[%bu]=%s\n",sizeof(s2),ptr ); //s1[9]=12345678

}

//函数功能:测试memccpy()函数;

void test_memccpy()

{ unsigned char i=0;

  char s2[10]="123456789";

  char s1[11]="aaaaabcde";

  void *ptr;

  unsigned char * p;

  ptr=memccpy( s1,s2,'5',sizeof(s1) );

       //将字符串数组s2[]的前n个字符拷贝到数组s1[]中,若拷贝了n个字符,

//没有遇到val的值,则返回NULL;

       //在拷贝过程中,若遇到val的值,则在拷贝完该字符后,将指向s1[]的下一个元素的

//指针返回;

  if(ptr==NULL) printf( "5 was not in s2[10];\n" );

  else{ printf( "5 is in s2[10];\n" ); //串口发送,"5 is in s2[10];\n";

        while(s1!='5') i++;

i++;

printf( "s1[%bu]=",i ); //串口发送,"S[5]=";

p=*(&ptr); //将ptr所指向的指针送给p;

i=*p;      //将p所指的内容保存到i中;

printf("%c;\n",i); //串口发送,"b\n";

printf("s[11]=%s;\n",s1); //串口发送:"s[11]=12345bcde;"

      }

}

//函数功能:测试memmove()函数;

void test_memmove()

{ unsigned char s2[]="123"

                    "456"

                    "789";

  unsigned char s1[10]="123";

  printf( "s2[]=%s\n",s2 ); //串口发送:"s2[]=123456789"

  memmove( s2,&s2[2],5 );   //将s2[2]~s2[7]的5个元素拷贝到s2[]数组中;

  printf( "s2[]=%s\n",s2 ); //串口发送:"s2[]=345676789"

  memmove( s1,s2,5 );        //将s2[]的前5个元素拷贝到s1[]中;

  printf( "s1[]=%s\n",s1 );  //串口发送:"s1[]=34567"

  printf( "s2[]=%s\n",s2 );  //串口发送:"s2[]=345676789"

}

//函数功能:测试memset()函数;

void test_memset()

{ char s[10]="123456789";

  memset( s,'*',9 );

  s[9]='\0';               //添加字符串结束符,为printf()打印做准备;

  printf( "s[]=%s\n",s );  //串口发送:"s[]=*********"

}

//函数功能:测试strcat()函数;

void test_strcat()

{ char s2[]="456";

  char s1[10]="123";

  void *ptr;

  ptr=strcat( s1,s2 ); //将字符串数组s2[]拷贝到字符串数组s1[]的尾部,并将s1[]的

//首字符指针返回;

  printf( "s1[]=%s\n",s1 );  //串口发送:"s[]=123456"

  printf( "s1[]=%s\n",ptr );  //串口发送:"s[]=123456"

}

//函数功能:测试strncat()函数;

void test_strncat()

{ char s2[]="DEF";

  char s1[10]="ABC";

  void *ptr;

  ptr=strncat( s1,s2,2 ); //将s2[]的前2个字符拷贝到字符串数组s1[]的尾部,并将s1[]的首字符

//指针返回;

  printf( "s1[]=%s\n",s1 );  //串口发送:"s[]=ABCDE"

  printf( "s1[]=%s\n",ptr );  //串口发送:"s[]=ABCDE"

}

//函数功能:测试strcmp()函数;

void test_strcmp()

{ char s1[]="123";

  char s2[]="321";

  char i;

  i=strcmp(s1,s2);

       //比较字符串数组s1[]和字符串数组s2[]的字符串是否相等,若相等,则返回0,

       //若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;

  if(i==0) printf("s1[]==s2[],return value = 0.\n");

  else if(i>0) printf("s1[>]=s2[],return value is > 0.\n");

  else printf("s1[]<s2[],return value < 0.\n");

}

//函数功能:测试strncmp()函数;

void test_strncmp()

{ char s1[16]="0123456789ABCDEF";

  char s2[16]="0123456789abcdef";

  char i;

  i=strncmp(s1,s2,16);

       //比较字符串数组s1[]和字符串数组s2[]的前16个字符是否相等,若相等,则返回0,

       //若s1>s2,则返回一个正数,若s1<s2,则返回一个负数;

  if(i==0) printf("s1[16]==s2[16],return value = 0.\n");

  else if(i>0) printf("s1[16>]=s2[16],return value is > 0.\n");

  else printf("s1[16]<s2[16],return value < 0.\n");

}

//函数功能:测试strcpy()函数;

void test_strcpy()

{ char s2[]="12345678";

  char s1[11];

  char *ptr;

  ptr=strcpy( s1,s2 );

    //将字符串数组s2[]的字符(包括结束符)拷贝到数组s1[]中,并将数组s1[]的首地址返回;

  printf( "s1[11]=%s\n",ptr ); //s1[11]=12345678

  printf( "s1[11]=%s\n",s1 );  //s1[11]=12345678

}

//函数功能:测试strncpy()函数;

void test_strncpy()

{ char s2[]="abcd";

  char s1[11]="1234567890";

  char *ptr,*p;

  unsigned char i,temp;

  ptr=strncpy( s1,s2,8 );

//将字符串数组s2[]的前8个字符拷贝到数组s1[]中,若s2的长度小于8,则用0补齐到长

//度8,拷贝到s1中,

    //并将数组s1[]的首地址返回;

  printf( "s1[11]=%s\n",ptr ); //s1[11]=abcd

  printf( "s1[11]=%s\n",s1 );  //s1[11]=abcd

  printf( "s1[11]=" );          //s1[11]=

  p=*(&ptr); //将ptr所指向的指针送给p;

  for( i=0;i<4;i++ )

     { temp=*p++; //将p所指的内容保存到temp中;

    printf("%c",temp); //打印字符串:abcd

}

  for( i=4;i<8;i++ )

     { temp=*p++; //将p所指的内容保存到temp中;

    printf("%bd",temp);  //打印补齐的数据:0000

}

  for( i=8;i<sizeof(s1)-1;i++ )

     { temp=*p++; //将p所指的内容保存到temp中;

    printf("%c",temp);  //打印字符串:90

}

  temp=*p; //将p所指的内容保存到temp中;

  printf("%bd",temp);  //打印字符串结束符:\0

  printf( "\n" );

}

//函数功能:测试strlen()函数;

void test_strlen()

{ char s1[11]="1234567890";

  int return_value;

  return_value=strlen(s1);  //返回字符串s1[]中的字符个数,包括结束符'\0';

  printf("s1 length is %d\n",return_value);  //打印:s1 length is 10

  printf( "s1 length is %bd\n",sizeof(s1) );  //打印:s1 length is 11

}

//函数功能:测试strchr()函数;

void test_strchr()

{ char * ptr,*p;

  char s[]="cbcd";

  unsigned char temp;

  int return_value;

  ptr=strchr( s,'c' ); //在s[]中搜索'c'的值并将第1次出现'c'值的指针返回,若没有搜索到,

//则返回NULL;

  return_value= strpos(s,'c'); //在s[]中搜索c的值并将第1次出现c值的位置值返回,若没

//有搜索到,则返回-1;

  p=*(&ptr);   //将ptr所指向的指针送给p;

  temp=*p;  //将p所指的内容保存到temp中;

  if(ptr!=NULL) printf("%c is in s[%d];\n",temp,return_value); //"c is in s[0];"

}

//函数功能:测试strpos()函数;

void test_strpos()

{ char s[]="01234";

  int return_value;

  return_value= strpos(s,'3');

  //在s[]中搜索c的值并将第1次出现c值的位置值返回,若没有搜索到,则返回-1;

  if(return_value!=-1) printf("s[%d]=3\n",return_value); //"s[3]=3"

}

//函数功能:测试strrchr()函数;

void test_strrchr()

{ char * ptr,*p;

  char s[]="cbcd";

  unsigned char temp;

  int return_value;

  ptr=strrchr( s,'c' ); //在s[]中搜索c的值并将最后1个出现c值的指针返回,若没有搜索到,

//则返回NULL;

  return_value= strrpos(s,'c'); //在s[]中搜索c的值并将最后1个出现c值的位置值返回,

//若没有搜索到,则返回-1;

  p=*(&ptr);  //将ptr所指向的指针送给p;

  temp=*p;  //将p所指的内容保存到temp中;

  if(ptr!=NULL) printf("%c is in s[%d];\n",temp,return_value);   //"c is in s[2]"

}

//函数功能:测试strrpos()函数;

void test_strrpos()

{ char s[]="33234";

  int return_value;

  return_value=strrpos(s,'3');

//在s[]中搜索c的值并将最后1个出现c值的位置值返回,若没有搜索到,则返回-1;

  if(return_value!=-1) printf("s[%d]=3\n",return_value);  //"s[3]=3"

}

//函数功能:测试strstr()函数;

void test_strstr()

{ char * ptr,*p;

  char s[]="1234aabcd5678abcd";

  char sub[]="abcd";

  unsigned char temp,i;

  ptr=strstr( s,sub );

  //在s[]中搜索字符串数组sub[]的字符串,并将第1次出现"sub[]的字符串"的指针返回,

//若没有搜索到,则返回NULL;

  p=*(&ptr);    //将ptr所指向的指针送给p;

  if(ptr!=NULL)

    { printf("s[]=1234a");

  for(i=0;i<12;i++)

    { temp=*p++;        //将p所指的内容保存到temp中;

  printf("%c",temp);  //"abcd5678abcd"

}

  printf("\n");

}

}

//函数功能:初始化串口,设置波特率为1200bps@16MHz,使能接收,使用8位UART;

void Serial_Port_Initialization()

{ SCON  = 0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI

                //SM1:SM0=01,选择方式1,SM2=0,表示非多机通讯,8-bit UART;

//REN=1,使能接收;

  TMOD |= 0x20; //定时器方式控制寄存器:GATE1,C/T1,M11,M10,GATE0,C/T0,M01,M00

                //GATE=0,TR置1便可以启动Timer;GATE=1,TR置1,且INT脚输入

//高电平,才可以启动Timer;

//M11:M10=10,选择方式2,8位自动重装载;

  TH1   = 221;  //TH1:  reload value for 1200 baud @ 16MHz

  TR1   = 1;    //启动Timer1;

  TI    = 1;    //发送UART的第一个字节,为下次发送做准备;

}

void main(void)

{

  Serial_Port_Initialization(); //初始化串口,设置波特率为1200bps@16MHz,使能接收,使用8位UART;

  for(;;)

     { test_memchr();   //测试memchr()函数;

    test_memcmp();  //测试memcmp()函数;

test_memcpy();   //测试memcpy()函数;

test_memccpy(); //测试memccpy()函数;

test_memmove();  //测试memmove()函数;

test_memset();    //测试memset()函数;

test_strcat();     //测试strcat()函数;

test_strncat();    //测试strncat()函数;

test_strcmp();    //测试strcmp()函数;

test_strncmp(); //测试strncmp()函数;

test_strcpy();     //测试strcpy()函数;

test_strncpy();    //测试strncpy()函数;

test_strlen();     //测试strlen()函数;

test_strchr();    //测试strchr()函数;

test_strpos();     //测试strpos()函数;

test_strrchr();    //测试strrchr()函数;

test_strrpos();    //测试strrpos()函数;

test_strstr();    //测试strstr()函数;

}


使用特权

评论回复
沙发
macpherson| | 2024-10-11 08:58 | 只看该作者
单片机通常具有有限的内存资源,特别是在资源受限的微控制器上。使用string.h中的函数时,要确保目标字符串有足够的内存空间。

使用特权

评论回复
板凳
mikewalpole| | 2024-10-11 10:11 | 只看该作者
避免使用未初始化或已经释放的指针。

使用特权

评论回复
地板
geraldbetty| | 2024-10-11 19:24 | 只看该作者
当函数的输入参数不合法或者操作过程中发生错误时,函数的行为可能是未定义的。

使用特权

评论回复
5
mattlincoln| | 2024-10-14 14:18 | 只看该作者
在单片机中,内存资源通常是有限的。定义字符串数组时,要根据实际需要合理分配空间,确保数组的大小足够容纳字符串及其结束符。

使用特权

评论回复
6
backlugin| | 2024-10-14 14:56 | 只看该作者
并非所有的单片机开发环境都支持完整的string.h库。在使用前,应检查所使用的编译器和库是否提供了所需的字符串函数。

使用特权

评论回复
7
uytyu| | 2024-10-15 11:38 | 只看该作者
strcpy、strcat等函数不会自动检查目标缓冲区的大小,可能导致缓冲区溢出。可以使用strncpy、strncat等带有长度参数的函数来避免这个问题。

使用特权

评论回复
8
hearstnorman323| | 2024-10-15 17:32 | 只看该作者
在使用string.h库函数时,要特别注意内存管理、边界检查、性能优化和错误处理

使用特权

评论回复
9
uytyu| | 2024-10-16 09:40 | 只看该作者
单片机的处理能力有限,一些字符串操作可能较为耗时,特别是在处理较长字符串时。因此,应尽量优化字符串操作,减少不必要的复制和移动。

使用特权

评论回复
10
cemaj| | 2024-10-16 12:18 | 只看该作者
递归调用或大量局部变量的使用可能导致堆栈溢出。

使用特权

评论回复
11
hudi008| | 2024-10-16 12:56 | 只看该作者
单片机的处理能力有限,因此在处理大型字符串时,要考虑函数的性能。尽量优化代码,减少不必要的字符串操作。

使用特权

评论回复
12
sheflynn| | 2024-10-16 13:46 | 只看该作者
在使用 strcpy, strcat 等函数时,确保目标缓冲区足够大,以容纳所有的字符加上结束的 null 字符。缓冲区溢出可能导致程序崩溃或安全漏洞。

使用特权

评论回复
13
1988020566|  楼主 | 2024-10-16 14:38 | 只看该作者
如果需要动态分配内存来存储字符串,要确保及时释放内存,避免内存泄漏。

使用特权

评论回复
14
maudlu| | 2024-10-16 16:01 | 只看该作者
在使用 strlen 函数时,确保字符串确实以 null 字符结尾,否则 strlen 可能进入无限循环或返回错误的长度。

使用特权

评论回复
15
loutin| | 2024-10-16 17:09 | 只看该作者
单片机资源有限,避免使用大量的字符串操作,因为这可能会消耗大量的栈空间或堆空间。

使用特权

评论回复
16
mickit| | 2024-10-16 19:01 | 只看该作者
大多数 string.h 库函数都假设字符串是以 null 字符(\0)结尾的。

使用特权

评论回复
17
updownq| | 2024-10-16 19:45 | 只看该作者
一些 string.h 函数(如 strcpy_s, strncpy_s)提供了更安全的版本,这些版本可以避免缓冲区溢出的问题。在可能的情况下,优先使用这些安全函数。

使用特权

评论回复
18
mikewalpole| | 2024-10-16 20:31 | 只看该作者
大多数string.h函数都会返回一个值,表示操作是否成功。务必检查这些返回值并进行适当的错误处理。

使用特权

评论回复
19
cemaj| | 2024-10-17 10:31 | 只看该作者
在使用strstr、strchr等搜索函数时,要考虑边界条件,如空字符串或搜索字符串不存在的情况。

使用特权

评论回复
20
hudi008| | 2024-10-17 11:07 | 只看该作者
某些 string.h 库函数可能对特定的字符集有特殊的处理方式或者限制。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

402

主题

10662

帖子

6

粉丝