参考链接:C 标准库 - <string.h>
string.h中主要有两类函数:
memxxx 和 strxxx,其中memxxx是针对内存操作的函数,在遇到‘\0‘的时候并不会停下来,而通常是设置一个size_t类型(其实是unsigned int)的参数来表示字节大小;
而strxxx是针对字符串操作的函数,遇到‘\0‘停下来。strxxx函数中,有一些函数是strnxxx的,这些函数可以通过传入一个size_t类型的参数来表示字节大小,所以遇到‘\0‘或到达字节大小都会停下来,相对安全。
以下分组介绍函数:
1、memcpy memmove strcpy strncpy
void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n); char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n);
// 内存拷贝。当拷贝字符串的时候,考虑到‘\0‘的问题,可以这样拷贝进str1。此时如果str2中有\0,拷贝动作仍然会进行下去,直到达到n次 memcpy(str1, str2, sizeof(str1) - 1); str1[sizeof(str1) - 1] = ‘\0‘; // 遇到内存重叠的情况,memmove是更安全的,不会造成覆盖的情况 // http://stackoverflow.com/questions/4415910/memcpy-vs-memmove char str5[] = "aabbcc"; printf( "The string: %s\n", str5 ); memcpy( str5, str5 + 2, 4 ); // cccccc , wrong printf( "New string: %s\n", str5 ); strncpy( str5, "aabbcc", sizeof(str5) ); // reset string printf( "The string: %s\n", str5 ); memmove( str5, str5 + 2, 4 ); // bbcccc , right printf( "New string: %s\n", str5 ); // 字符串拷贝。同理,strncpy也是如此。不过memcpy不考虑中间遇到‘\0‘的问题,而strncpy遇到\0就停止拷贝 ret = strncpy(str1, str2, sizeof(str1) - 1); str1[sizeof(str1) - 1] = ‘\0‘; // 如果str1的空间不足以放下str2,就会造成内存溢出 ret = strcpy(str1, str2);
2、memcmp strcmp strncmp
stackoverflow里有个回答举例很详细:what-is-the-difference-between-memcmp-strcmp-and-strncmp-in-c
strcmp 比较的是以‘\0‘ 结束的字符串
strncmp 比较的是至多n个字符、以‘\0‘结束的字符串
memcmp 比较的是n个字节的二进制字节缓冲区
void *memcpy(void *dest, const void *src, size_t n); char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n);
const char s1[] = "atoms\0\0\0\0"; // extra null bytes at end const char s2[] = "atoms\0abc"; // embedded null byte const char s3[] = "atomsaaa"; if(strcmp(s1, s2) == 0){printf("strcmp(s1, s2) == 0 \n");} // strcmp stops at null terminator if(strcmp(s1, s3) != 0){printf("strcmp(s1, s3) != 0 \n");} // Strings are different if(strncmp(s1, s3, 5) == 0){printf("strncmp(s1, s3, 5) == 0 \n");} // First 5 characters of strings are the same if(memcmp(s1, s3, 5) == 0){printf("memcmp(s1, s3, 5) == 0 \n");} // First 5 bytes are the same if(strncmp(s1, s2, 8) == 0){printf("strncmp(s1, s2, 8) == 0 \n");} // Strings are the same up through the null terminator if(memcmp(s1, s2, 8) != 0){printf("memcmp(s1, s2, 8) != 0 \n");} // First 8 bytes are different
3、memchr strchr strrchr
memchr 在内存中,从某个地址开始到n个字节之后,返回最早匹配到的字符的指针
strchr 在一个字符串中,返回最早匹配到的字符的指针
strrchr 在一个字符串中,返回最后一个匹配到的字符的指针
void *memchr(const void *str, int c, size_t n); char *strchr(const char *str, int c); char *strrchr(const char *str, int c);
char chr[] = "there is an orange"; const char *memchrres = memchr(chr, ‘r‘, 12); // 中间的int型参数其实需要传入char型的字符。。 const char *strchrres = strchr(chr, ‘r‘); const char *strrchrres = strrchr(chr, ‘r‘); printf("memchrres:(%p) %s, strchrres:(%p) %s, strrchrres:(%p) %s \n", &memchrres, memchrres, &strchrres, strchrres, &strrchrres, strrchrres);
4、memset:将s所指向的某一块内存中的前n个 字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针(摘自 百度百科)
void *memset(void *str, int c, size_t n);
struct S abc; memset(&abc, 0, sizeof(struct S));
5、strstr:在字符串 haystack 中查找第一次出现字符串 needle(不包含空结束字符)的位置。
char *strstr(const char *haystack, const char *needle);
const char haystack[20] = "W3CSchool lalala"; const char needle[10] = "School"; char *strres; strres = strstr(haystack, needle); printf("%s \n", strres);
6、strlen strnlen
strlen 计算字符串的长度,直到空结束字符,但不包含空结束字符
strnlen 以上函数不安全,如果字符串非法(不包含‘\0‘),所以需要规定最大匹配长度,防止内存溢出
size_t strlen(const char *str); size_t strnlen(const char *str, size_t maxlen);
const char strlenres[] = "test strlen"; printf("strlen = %d \n", (int)strlen(strlenres)); // 如果string没有\0的时候,会判断出错 printf("strnlen = %d \n", (int)strnlen(strlenres, sizeof(strlenres)));
7、strcat strncat
strcat 把源字符串追加到目标字符串的后面
strncat 规定最大追加数n,相对安全
char *strcat(char *dest, const char *src); char *strncat(char *dest, const char *src, size_t n);
char cat1[20] = "lalala"; char cat2[] = "short"; char cat3[] = "longlong"; printf("res1 = %s \n", strcat(cat1, cat2)); printf("res2 = %s \n", strncat(cat1, cat2, sizeof(cat1) - 1 - strlen(cat1))); printf("res3 = %s \n", strncat(cat1, cat3, sizeof(cat1) - 1 - strlen(cat1)));
8、strtok:根据给定的分隔符,分割一个长的字符串(使用方法很怪异。。)
char *strtok(char *str, const char *delim);
char tok[80] = "This is - www.w3cschool.cc - website"; const char delim[] = "-"; char *token = strtok(tok, delim); // 获取第一个字符串 while(token != NULL){ printf("%s \n", token); token = strtok(NULL, delim); // 注意! }