字符串处理
- 测字符串长度函数
- 字符串拷贝函数
- 格式化字符串操作函数
const
关键字
对字符串的处理,在嵌入式编程、应用编程、网络编程中会有大量的使用
字符串的拷贝、连接、比较、切割、变换…
要求熟练使用常见字符串处理函数,并且会自己编写典型的字符串操作函数
字符串操作函数
1 2 3 4 5
| 头文件:#include<string.h> 1、strlen 2、strcpy/strncpy 3、strcat/strncat 4、strcmp/strncmp
|
注意:只要是 str 开头的函数,都是遇到 '\0'
结束
strlen 函数
- 函数原型:
unsigned int strlen(const char *str);
- 函数功能:测量字符串的长度,不包含
'\0'
- 函数参数:存放字符串的内存空间的
首地址
- 注意:遇到
'\0'
结束测量
案例 1:请说出下面代码的运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include<stdio.h> #include<string.h> int main(int argc,char *argv[]){ char str1[128]="hello"; char str2[]="hello"; char str3[]="hel\0lo"; char str4[]="hel\123\\lo"; char str5[]="hel\x2flo"; char str6[]="\0he\0llo";
printf("%d\n",sizeof(str1)); printf("%d\n",strlen(str1));
printf("%d\n",sizeof(str2)); printf("%d\n",strlen(str2));
printf("%d\n",sizeof(str3)); printf("%d\n",strlen(str3));
printf("%d\n",sizeof(str4)); printf("%d\n",strlen(str4)); printf("%s\n",str4);
printf("%d\n",sizeof(str5)); printf("%d\n",strlen(str5)); printf("%s\n",str5);
printf("%d\n",sizeof(str6)); printf("%d\n",strlen(str6)); return 0; }
|
运行结果:
分析:
第 9、10 行,因为定义的数组元素个数为 128,为 char 类型,所以占的字节数为 128,但是 str1 中的字符串为hello
只有 5 个字符,所以打印的分别是 128、5;
第 12、13 行,因为数组的长度没有定义,数组的长度有初始化的元素个数决定,然而字符串hello
实际上最后面系统会自动添加一个'\0'
,所以共有 6 个元素,而字符串的长度为 5,因此打印分别为 6、5;
第 15、16 行,数组长度没有定义,有初始化元素个数决定,而"hel\0lo"
系统在末尾会添加一个'\0'
,所以数组总元素个数为 7,而hel
后面有个\0
,strlen 函数遇到\0
就会结束,所以测量出的长度为 3;
第 18,19 行,'\123'
代表一个字符,'\\'
为一个'\'
作业:自定义一个 my_strlen 函数测量字符串的长度
1
| int my_strlen(const char *s);
|
字符串拷贝函数 strcpy/strncpy
strcpy 函数
- 函数原型:
char *strcpy(char *dest,const char *src);
- 函数功能:把 src 所指向的字符串复制到 dest 所指向的空间中
- 返回值:返回 dest 字符串的首地址
- 注意:遇到
\0
会结束拷贝,但是\0
也会被拷贝过去
案例 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include<stdio.h> #include<string.h> int main(int argc,char *argv[]){ char src1[] = "hello world"; char dest1[128]=""; char src2[] = "hello\0 wo\0rld"; char dest2[128]=""; char src3[] = "\0hello world"; char dest3[128]="";
strcpy(dest1,src1); strcpy(dest2,src2); strcpy(dest3,src3);
printf("%s\n",dest1); printf("%s\n",dest2); printf("##%s##\n",dest3); return 0; }
|
运行结果:
案例 3:自己实现一个 strcpy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include<stdio.h> #include<string.h> char *my_strcpy(char *dest,const char *src){
while(*src!='\0'){ *dest=*src; src++; dest++; } *dest='\0';
} int main(int argc,char *argv[]){ char src1[] = "hello world"; char dest1[128]=""; char src3[] = "\0hello world"; char dest3[128]="";
my_strcpy(dest1,src1); my_strcpy(dest3,src3);
printf("%s\n",dest1); printf("##%s##\n",dest3); return 0; }
|
运行结果:
strncpy 函数
- 函数原型:
char *strncpy(char *dest,const char *src,int num);
- 函数功能:把 src 所指向的字符串的前 num 个复制到 dest 所指向的空间中
- 返回值:返回 dest 字符串的首地址
- 注意:
\0
不会被拷贝过去,但是遇到\0
结束
复制多少由num的值决定。如果src的前n个字符不含NULL字符,则结果不会以NULL字符结束。如果n<src
的长度,只是将src的前n个字符复制到dest的前n个字符,不自动添加’\0’,也就是结果dest不包括’\0’,需要再手动添加一个’\0’。如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。
案例4:
1 2 3 4 5 6 7 8 9 10
| #include<stdio.h> #include<string.h> int main(int argc,char *argv[]){ char src[]="hello world"; char dest[128]="";
strncpy(dest,src,3); printf("%s",dest); return 0; }
|
运行结果:
strcat 函数 字符串拼接
- 函数原型:
char *strncat(char *dest,const char *src);
- 函数功能:把 src 所指向的字符串拼接到到 dest 所指向的字符串的末尾(第一个
\0
后面)
案例5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include<stdio.h> #include<string.h> int main(int argc,char *argv[]){ char s1[128]="hello"; char s2[128]="world"; char a1[128]="hel\0lo"; char a2[128]="world"; char c1[128]="hello"; char c2[128]="wor\0ld";
strcat(s1,s2); strcat(a1,a2); strcat(c1,c2); printf("%s\n",s1); printf("%s\n",s2); printf("%s\n",a1); printf("%s\n",a2); printf("%s\n",c1); printf("%s\n",c2); return 0; }
|
运行结果:
作业:自定义my_strcat函数
strcmp/strncmp 字符串比较函数
strcmp 函数 (整个字符串比较)
- 函数原型:
int strcmp(const char *s1,const char *s2);
- 函数功能:将s1、s2指向的字符串,逐个字符比较(ASCII码)
- 返回值:
>0
表示s1>s2
;
<0
表示s1<s2
;
=0
表示s1=s2
;
- 两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止
案例6:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include<stdio.h> #include<string.h> int main(int argc,char *argv[]){ char s1[128]="aaahello"; char s2[128]="aaaworld"; int res=0; res=strcmp(s1,s2); if(res>0){ printf("s1>s2"); }else if(res<0){ printf("s1<s2"); }else if(res == 0){ printf("s1==s2"); } return 0; }
|
运行结果:
问题:如果两个字符串的长度不相等会发生什么?
strncmp 函数 (局部字符串比较)
- 函数原型:
int strcmp(const char *s1,const char *s2,unsigned int num);
- 函数功能:将s1、s2指向的字符串的前num个,逐个字符比较(ASCII码)
- 返回值:
>0
表示s1>s2
;
<0
表示s1<s2
;
=0
表示s1=s2
;
案例7:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include<stdio.h> #include<string.h> int main(int argc,char *argv[]){ char s1[128]="aaahello"; char s2[128]="aaaworld"; int res=0; res=strncmp(s1,s2,3); if(res>0){ printf("s1>s2"); }else if(res<0){ printf("s1<s2"); }else if(res == 0){ printf("s1==s2"); } return 0; }
|
运行结果:
strchr 函数
- 函数原型:
char *strchr(const char *str, int c);
- 功能:在参数str所指向的字符串中搜索第一次出现字符c(一个无符号字符)的位置(地址)。
- 返回值:该函数返回在字符串 str 中第一次出现字符 c 的位置(地址),如果未找到该字符则返回 NULL。
案例8:将str中所有的o替换成*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include<stdio.h> #include<string.h> int main(int argc, char* argv[]) { char str[] = "www.yuencode.cn"; char *res = NULL;
while (1) { res = strchr(str, 'o'); if (res == NULL) { break; } *res = '*'; } printf("%s\n", str); return 0; }
|
运行结果:
strstr函数
- 函数原型:
char *strstr(const char *haystack, const char *needle)
- 函数参数:
- haystack – 要被检索的 C 字符串。
- needle – 在 haystack 字符串内要搜索的小字符串。
- 返回值:该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 NULL。
案例9:将str中所有的cnm替换成*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include<stdio.h> #include<string.h> int main(int argc, char* argv[]) { char str[] = "www.yucnmencode.ccnmn"; char *res = NULL; int i=0; while (1) { res = strstr(str, "cnm"); if (res == NULL) { break; } memset(res,'*',strlen("cnm")); } printf("%s\n", str); return 0; }
|
运行结果:
memset函数
- 函数原型:
void *memset(void *str, int c, size_t n)
- 参数:
- str – 指向要填充的内存块。
- c – 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
- n – 要被设置为该值的字节数。
- 返回值:该值返回一个指向存储区 str 的指针。