參考鏈接: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); // 注意! }