C語言字符串函數(shù)介紹與模擬實現(xiàn)詳解
1. strlen(求字符串長度)
這個函數(shù)就是求一個字符串的長度。
注意它是不算'\0'的,即以'\0'為結(jié)束標志,計算其之前的字符串長度,但不能沒有'\0'.
讓我們來一個有趣的例子:
int main() { if (strlen("abc") - strlen("abcdef")) printf("hehe"); else printf("haha"); return 0; }
以上的代碼乍一眼看是3 - 6 = -3,應該輸出haha
但是strlen函數(shù)返回的是無符號整型,所以-3被看作無符號整數(shù),應該是一個大于0的數(shù)。
1.1 strlen 模擬實現(xiàn)
那么這個函數(shù)自己來寫應該怎樣實現(xiàn)呢?
模擬實現(xiàn)需要考慮到所有情況:
所以 const 防止改變字符串與 assert 防止傳入空指針不可少。
size_t my_strlen(const char* a) { assert(a); int count = 0; while (*a) { count++; a++; } return count; }
2. strcpy(復制字符串)
這個函數(shù)用于把一個字符串內(nèi)容賦給另一個字符串內(nèi),如果目的字符串有內(nèi)容,直接覆蓋。
注意點:strcpy復制字符串從arr2到arr1
被復制的字符串一定要帶'\0',因為這個是結(jié)束標志
目標空間也要足夠大且可變(可變:用數(shù)組寫,而非指針卡死)
int main() { char arr1[] = "xxxxxxxxxxxxxxx"; //char *p = "xxx";//不可變且空間小 char arr2[] = "abcd\0efg"; strcpy(arr1, arr2); printf("%s", arr1); return 0; }
2.1 strncpy函數(shù)
這個函數(shù)是不是很相像?由于strcpy 直接將一個字符串完全復制過去,
那么有沒有一個函數(shù)能只復制一部分呢?此函數(shù)就是充當這個作用的。
它將 num 個字符從源字符串中取出,放入目的字符串。
int main() { char a[] = "abcde"; char b[] = "abc"; strncpy(a, b, 6); printf("%s", a); return 0; }
如果遇到源字符串不夠的情況,會自動補0.
2.2 模擬實現(xiàn)strcpy
char* my_strcpy(char* a1, const char* a2)//原指針被修改,不加const { assert(a1 && a2); char* ret = a1; while (*a1++ = *a2++) { ; } return ret; }
來解釋一下這個寫法(*a1++ = *a2++ ):
先把a2賦給a1,然后各自++。當a2為0時,這個表達式值為0,就退出循環(huán)。
因為值放在地址內(nèi),所以a1的地址給ret存好后,最后返回ret的地址就是返回a1的值.
3. strcat (追加字符)
傳入兩個字符串,將后一個字符串追加到前一個字符串上。
源字符串必須要有 '\0' 作為結(jié)束標志,且目標字符串足夠大且可變。(提前定義目標數(shù)組大?。?/p>
如果需要自己給自己追加,那么就使用這個函數(shù)。
3.1 strncat 函數(shù)
就是將源字符串 num 個字符追加到目標字符串上,如下圖:
3.2 模擬實現(xiàn)strcat
char* my_strcat(char* a, const char* b) { assert(a && b); char* p = a; //先找到a字符串為'\0'的位置 while (*a) { a++; } while (*a++ = *b++) { ; } return p; }
4. strcmp(比較兩個字符串內(nèi)容)
傳入兩個字符串,比較兩個字符串。
str1 > str2 返回正數(shù); = 返回0; < 返回負數(shù)
那么是怎么比較的呢?
記住是比較不相同的那個字符大小,跟長度沒有一點關系。
如圖就是比較 'e' 和 'q' 的字符大小,明顯 'q' 更大,所以返回 -1.
4.1 strncmp函數(shù)
和strncpy相似,就是將兩個字符串前num個字符比較,規(guī)則同 strcmp 函數(shù) 。
4.2 模擬實現(xiàn)strcmp
int my_strcmp(const char* a, const char* b) { assert(a && b); while (*a == *b) { if (*b == '\0') return 0; a++; b++; } /*if (*a > *b) return 1; if (*a < *b) return -1;*/ return *a - *b;//這樣一步到位 }
5. strstr (返回str1出現(xiàn)在str2位置處第一次的指針)
就是返回b字符串在a中第一次出現(xiàn)的位置的指針,如下就會打印 am a student.
如果沒有找到就返回空指針。
int main() { char a[] = "I am a student."; char b[] = "am"; printf("%s", strstr(a, b)); return 0; }
5.1 模擬實現(xiàn)strstr
char* my_strstr(const char* str1, const char* str2) { assert(str1 && str2); char* s1; char* s2; char* cp = str1; if (*str2 == '\0')//如果傳入了"" return str1; while (*cp) { s1 = cp; s2 = str2; while (*s1 == *s2 && *s1 && *s2) { s1++; s2++; } if (*s2 == '\0') { return cp; } cp++; } return NULL; }
6. strtok(分割字符串)
這個函數(shù)能以我們所需分割字符串,sep是分割的標志,str是被分割的字符串。
下面來一個例子:
int main() { char a[] = "123@qq.com"; char b[] = "@."; printf("%s\n", strtok(a, b));//分割了123 printf("%s\n", strtok(NULL, b));//分割了qq printf("%s\n", strtok(NULL, b));//分割了com return 0; }
第一次分割完,之后這個函數(shù)會記住分割的位置,把目標函數(shù)的分割標志變?yōu)?\0'
所以這個函數(shù)會修改字符串,要小心使用。
下次使用只需要傳入空指針,這是這個函數(shù)的重點。
我們也可以使用循環(huán)來表達它的結(jié)果:
int main() { char *p = "666@qq.com"; const char* sep = ".@"; char arr[30]; char *str = NULL; strcpy(arr, p);//將數(shù)據(jù)拷貝一份,處理arr數(shù)組的內(nèi)容 for(str=strtok(arr, sep); str != NULL; str=strtok(NULL, sep)) { printf("%s\n", str); } }
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!
相關文章
C++實現(xiàn)二分法求連續(xù)一元函數(shù)根
這篇文章主要為大家詳細介紹了C++實現(xiàn)二分法求連續(xù)一元函數(shù)根,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-06-06