參考鏈接:C 標準庫 - <string.h> string.h中主要有兩類函數: memxxx 和 strxxx,其中memxxx是針對記憶體操作的函數,在遇到'\0'的時候並不會停下來,而通常是設置一個size_t類型(其實是unsigned int)的參數來表示位元組大小; 而strxxx是針對字 ...
參考鏈接: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); // 註意! }