C语言字符串操作
C语言字符串操作函数
1.strlen
strlen用于求一个C风格字符串的长度,函数原型为
#include <string.h> size_t strlen(const char *s);
返回值为字符串的长度,当遇到'\0'时,认为字符串结束,'\0'不算入长度中。
#include <stdio.h> #include <string.h> int main(void) { char *str = "hello,world"; int count = strlen(str); printf("%d\n",count); return 0; }
结果测试:11
测试结果符合预期,下面以三种方式实现自己的strlen函数。
size_t my_strlen1(const char *str) { int count=0; assert(str); // while(str[count++]); // return count-1; while(*str++) count++; return count; } size_t my_strlen2(const char *str) { assert(str); if(*str == '\0') return 0; else return my_strlen2(++str)+1; } size_t my_strlen3(const char *str) { char *headstr = str; assert(str); while(*++str); return str - headstr; }
第一种使用一次遍历字符串,当字符不为'\0'时,count++;
第二种使用递归
第三种使用指针的减法,用指向最后一个字符的指针减去指向首字符的指针。
2.strnlen
strnlen的原型为
#include <string.h> size_t strnlen(const char *s, size_t maxlen);
strnlen的功能相当于一个计数器,函数从s的开头往下数,直到遇见'\0'或者计数器达到maxlne的值时,停止计数。
其用途主要在于网络图形中,字节流一般是没有'\0'的,所以,使用strlen一般会有问题,所有引入strnlen.
3.strcpy
strcpy的原型为
#include <string.h> char *strcpy(char *dest, const char *src);
strcpy的作用是将src开始的字符串(包括'\0')复制到以dest为起始点的地址空间,返回值为指向dest的指针。
#include <stdio.h> #include <string.h> int main() { char dest[100]; char *src = "hello,world"; strcpy(dest,src); printf("%s\n",dest); return 0; }
测试结果:hello,world
符合预期
实现自己的strcpy
#include <stdio.h> #include <assert.h> char *my_strcpy(char *dest,const char *src) { assert(dest); assert(src); while (*dest++ = *src++); return dest; }
4.strncpy
strncpy的原型是
#include <string.h> char *strncpy(char *dest, const char *src, size_t n);
该函数同样字符串拷贝函数,与strcpy不同的是,多了一个参数n。函数的作用是将src所指向的字符串中前n个字符复制到dest中。
5.strcmp
#include <string.h> int strcmp(const char *s1, const char *s2);
strcmp用来比较字符串s1和s2的大小,比较方式为字典式比较,比较标准为字符的ASCII值,比如"erfas"和"eradfasa";
逐个比较前两个字符相等,第三个字符‘f’大于'a',所以第一个字符串大。
当s1 大于 s2时,返回正数;
当s1 等于 s2时,返回0;
当s1 小于 s2时,返回负数;
#include <string> #include <stdio.h> int main() { char *s1 = "hello wolrd"; char *s2 = "change world"; int count = strcmp(s1,s2); printf("%d\n",count); return 0; }
这段代码在vs2010下结果为1,在gcc下测试结果为5
C语言标准只规定当s1 大于 s2时,返回值为正数,vs一律返回1,而gcc返回ASCII值的差,所以为了程序的
可移植性,不要写出
strcmp(s1,s2) == 1
这样的代码,建议这样写
strcmp(s1,s2) > 0
下面我们尝试实现自己的strcmp
#include <stdio.h> #include <assert.h> int my_strcmp(const char *s1,const char *s2) { assert(s1); assert(s2); while((*s1) == (*s2)) { if((*s1) == '\0') return 0; s1++; s2++; } if((*s1) - (*s2) > 0) return 1; else return -1; }
6.strncmp
strncmp的原型为
#include <string.h> int strncmp(const char *s1, const char *s2, size_t n);
该函数基本与strcmp差不多,但是只比较两个字符串的前n个字符。
7.strstr
strstr的原型为
#include <string.h> char *strstr(const char *haystack, const char *needle);
判断needle是否是haystack的子串,如果是,返回needle在haystack中首次出现的地址,否则,返回NULL
#include <string.h> #include <stdio.h> int main() { char *s1 = "hello,world"; char *s2 = "llo,w"; char *s3 = strstr(s1,s2); printf("%s\n",s3); return 0; }
测试结果为:
llo,world
结果符合预期
8.memset
memset的原型为
#include <string.h> void *memset(void *s, int c, size_t n);
memset的作用是将s所指向的内存中的前n个字节全部置为字符c的ASCII值。
#include <string.h> #include <stdio.h> int main() { char s[100]; memset((char *)s,'c',10); s[10] = '\0'; printf("%s\n",s); return 0; }
测试结果:cccccccccc
9.memcpy
memcpy
#include <string.h> void *memcpy(void *dest, const void *src, size_t n);
将src的数据复制n个到dest
#include <string.h> #include <stdio.h> int main() { char src[100] = "hello,world"; char dest[100]; memcpy(dest,src,11); printf("%s\n",dest); return 0; }
测试结果:hello,world
符合预期
memcpy不考虑内存重叠
10.memmove
memmove的原型为
#include <string.h> void *memmove(void *dest, const void *src, size_t n);
memmove与memcpy相似,但可以处理内存重叠的问题。