C語言頭文件<string.h>函數(shù)詳解
1. strlen —— 求字符串長(zhǎng)度
1.1 strlen 的聲明與用處
strlen ,我們有一些英語基礎(chǔ)的話不難通過字面意思來知道這個(gè)函數(shù)是干嘛用的,str 表 string ,字符串的意思,len 表 length ,長(zhǎng)度的意思。也就是說,strlen 是求字符串長(zhǎng)度的函數(shù)。我們通過 cplusplus 這個(gè)網(wǎng)站來觀察 strlen 的函數(shù)聲明以及各個(gè)參數(shù)的意義。
我們翻譯可以知道,strlen 所求的字符串長(zhǎng)度是字符串結(jié)束標(biāo)志之前的字符個(gè)數(shù)。即我們假設(shè)有字符串 "hello world" ,那么所求的字符串長(zhǎng)度就是 '\0' 之前的所有字符個(gè)數(shù),也就是 11 。那么這個(gè)字符串長(zhǎng)度是通過返回值返回的,所以我們要知道所求的字符串長(zhǎng)度是多少就必須定義一個(gè)變量來接收返回值。那么參數(shù)部分當(dāng)然就是字符串的首地址了。
1.2 strlen 的用法
#include <stdio.h> #include <string.h> int main() { char str1[] = "hello world"; char* str2 = "hello world"; int len1 = strlen(str1);//數(shù)組名表首元素地址 int len2 = strlen(str2);//str2 指針變量存放的也是首元素地址 printf("%d\n", len1); printf("%d\n", len2); //這種寫法也可以輸出長(zhǎng)度 //printf("%d\n", strlen(str1)); //printf("%d\n", strlen(str2)); return 0; }
我們要注意的一點(diǎn)是,strlen 的返回值是一個(gè) size_t 類型,即無符號(hào)整數(shù)。 它的意義在于求長(zhǎng)度時(shí)是不可能求出負(fù)數(shù)的,所以一定程度上優(yōu)化了內(nèi)存(使用有符號(hào)整形的話會(huì)浪費(fèi)掉用來存儲(chǔ)負(fù)數(shù)的空間)。
1.3 strlen 的模擬實(shí)現(xiàn)
我們上面已經(jīng)分析過 strlen 的原理了,那么現(xiàn)在我們用自己所學(xué)過的只是來“創(chuàng)造”一個(gè)屬于自己的 strlen 函數(shù)。
#include <stdio.h> #include <assert.h> unsigned int my_strlen(const char* str)//我們不改變字符串的內(nèi)容,所以用 const 來進(jìn)行修飾 { assert(str);//避免是一個(gè)空指針 unsigned int count = 0; while (*str) { count++; str++; } return count; } int main() { char str1[] = "hello world"; char* str2 = "hello world"; int ret1 = my_strlen(str1); int ret2 = my_strlen(str2); printf("%d\n", ret1); printf("%d\n", ret2); return 0; }
2. strcpy —— 字符串拷貝
2.1 strcpy 的聲明與用處
我們對(duì)其字面翻譯進(jìn)行理解,str 表 string ,即字符串,cpy 表 copy ,即拷貝。也就是 strcpy 這個(gè)函數(shù)是用來進(jìn)行字符串拷貝的。那我們通過 cplusplus 這個(gè)網(wǎng)站來觀察 strcpy 的聲明以及各個(gè)參數(shù)的意義。
我們翻譯過來就可以知道 strcpy 的功能,拷貝 source 指針指向的字符串至 destination 指針指向的數(shù)組當(dāng)中,拷貝的內(nèi)容包含字符串終止符。并且 destination 指針指向的數(shù)組必須有足夠大的空間容納拷貝之后的內(nèi)容。
由此我們知道, strcpy 需要兩個(gè)參數(shù),一個(gè)是數(shù)組,一個(gè)是字符串。并且數(shù)組的空間必須足夠大。返回值是返回?cái)?shù)組拷貝之前的地址。這么做的意義是防止拷貝之前的內(nèi)容丟失。
2.2 strcpy 的用法
#include <stdio.h> #include <string.h> int main() { char dest[20] = "row your boat"; char src[] = "hello world"; strcpy(dest, src); printf("%s\n", dest); return 0; }
這是 strcpy 最最常用的用法,我們只需要記住一點(diǎn)即可:拷貝過去的內(nèi)容是包含 '\0' 的。也就是說即使我拷貝過去的字符串長(zhǎng)度沒有數(shù)組原來的字符串長(zhǎng)度長(zhǎng),但是我包含 '\0' 了,在 C 語言的角度來說 '\0' 之后的內(nèi)容就不算從頭往后看的字符串內(nèi)容了。
2.3 strcpy 的模擬實(shí)現(xiàn)
#include <stdio.h> #include <assert.h> char* my_strcpy(char* dest, const char* src)//dest 指向的數(shù)組空間是要被改變的,但是 src 指向的字符串不需要改變 { assert(dest && src);//防止其中某個(gè)是無效指針 char* ret = dest; while (*dest++ = *src++) ; //注意 while 循環(huán)執(zhí)行了空語句 return ret; } int main() { char dest[30] = "gently down the stream"; char src[] = "life is but a dream"; my_strcpy(dest, src); printf("%s\n", dest); return 0; }
3. strcmp —— 字符串比較
3.1 strcmp 的聲明與用處
也是一樣,我們可以通過字面翻譯來大致了解這個(gè)函數(shù)是干嘛用的。str 表 string ,即字符串,cmp 表 compare ,即比較。我們同樣通過 cplusplus 這個(gè)網(wǎng)站觀察這個(gè)函數(shù)的聲明以及各個(gè)參數(shù)的意義。
我們翻譯即可知道這個(gè)函數(shù)的原理。其原理就是:都是從兩個(gè)字符串的第一個(gè)字符開始比較,如果這兩個(gè)字符相等,那么這兩個(gè)字符串都會(huì)進(jìn)行下一對(duì)字符比較,直到兩個(gè)字符不相等,然后進(jìn)行比較大小。如果第一個(gè)字符小于第二個(gè)字符,就會(huì)返回一個(gè)小于 0 的整數(shù),等于則返回 0 ,大于則返回一個(gè)大于 0 的整數(shù)。
其兩個(gè)參數(shù)都是要比較的字符串。為了方便理解,我們通過畫圖的形式來理解。
3.2 strcmp 的用法
#include <stdio.h> #include <string.h> int main() { char* str1 = "abbbcd"; char* str2 = "abbbdd"; int ret = strcmp(str1, str2); if (ret > 0) printf("str1 > str2\n"); else if (ret < 0) printf("str1 < str2\n"); else printf("str1 == str2\n"); return 0; }
3.3 strcmp 的模擬實(shí)現(xiàn)
#include <stdio.h> #include <assert.h> int my_strcmp(const char* str1, const char* str2)//兩個(gè)字符串的內(nèi)容都不需要修改,用 const 修飾 { assert(str1 && str2);//防止是無效指針 while (*str1 == *str2)//如果相等則進(jìn)入循環(huán) { if (*str1 == '\0')//*str1 == '\0' 了并且進(jìn)入循環(huán)了,說明兩個(gè)字符串比較完成了,沒有不相等的字符 return 0; str1++; str2++; } return *str1 - *str2;//兩個(gè)字符的差作為返回值 } int main() { char* str1 = "abbbcd"; char* str2 = "abbbdd"; int ret = my_strcmp(str1, str2); if (ret > 0) printf("str1 > str2\n"); else if (ret < 0) printf("str1 < str2\n"); else printf("str1 == str2\n"); return 0; }
4. strcat —— 字符串追加
4.1 strcat 的聲明與用處
我們通過 cplusplus 這個(gè)網(wǎng)站來觀察 strcat 的聲明以及各個(gè)參數(shù)的意義。
翻譯一下即可直到 strcat 函數(shù)的用法:將 source 指針指向的字符串追加到 destination 指針指向數(shù)組并且有足夠大的空間(本人嘗試追加到字符串,但是失敗了),其追加的位置是 destination 指針指向的字符串的 '\0' 處,即從這個(gè)位置拷貝。需要注意的是,追加的 '\0' 的位置第一個(gè) '\0' 的位置。
4.2 strcat 的用法
#include <stdio.h> #include <string.h> int main() { char str1[50] = "row row row your boat,"; char* str2 = "gently down the stream"; strcat(str1, str2); printf("%s\n", str1); return 0; }
4.3 strcat 的模擬實(shí)現(xiàn)
#include <stdio.h> #include <assert.h> char* my_strcat(char* dest, const char* src)//src 指向的字符串是不改變內(nèi)容的,所以用 const 修飾 { assert(dest && src);//確保兩個(gè)指針有效 char* ret = dest; while (*dest) dest++;//先找到 dest 指向的數(shù)組的第一個(gè) '\0' 的位置 while (*dest++ = *src++)//拷貝 ; return ret; } int main() { char str1[50] = "row row row your boat,"; char* str2 = "gently down the stream"; my_strcat(str1, str2); printf("%s\n", str1); return 0; }
5. strncpy —— 長(zhǎng)度受限制的字符串拷貝
5.1 strncpy 的聲明與用處
strncpy 與 strcpy 的區(qū)別就是 strncpy 多了一個(gè)參數(shù)。這個(gè)參數(shù)是一個(gè)無符號(hào)的整數(shù),即可以自定義拷貝多少個(gè)字節(jié)的內(nèi)容。這就大大的方便了我們的使用,提高了 C 語言的靈活性。
5.2 strncpy 的用法
#include <stdio.h> #include <string.h> int main() { char str1[20] = "row your boat"; char str2[] = "hello world"; strncpy(str1, str2, 3);//我們從 str2 中拷貝三個(gè)字節(jié)的內(nèi)容到 str1 去 printf("%s\n", str1); return 0; }
我們可以看到輸出的結(jié)果非常奇怪,這是因?yàn)楫?dāng)我們只拷貝三個(gè)字節(jié)的內(nèi)容時(shí),strncpy 是不會(huì)在后面補(bǔ) '\0' 的(即要多少內(nèi)容就拷多少內(nèi)容),這就導(dǎo)致了我們能夠看到 str1 數(shù)組里面拷貝之前的內(nèi)容。
5.3 strncpy 的模擬實(shí)現(xiàn)
#include <stdio.h> #include <assert.h> char* my_strncpy(char* dest, const char* src, unsigned int num) { assert(dest && src);//確保兩個(gè)指針有效 char* ret = dest; while (num--)//拷貝幾個(gè)字節(jié) { *dest = *src; dest++; src++; } return ret; } int main() { char str1[20] = "row your boat"; char str2[] = "hello world"; my_strncpy(str1, str2, 3); printf("%s\n", str1); return 0; }
6. strncmp —— 長(zhǎng)度受限制的字符串比較
6.1 strncmp 的聲明與用處
strncmp 與 strcmp 的功能是一模一樣的,原理也就是一模一樣的。也就是說掌握了 strcmp 就能夠掌握 strncmp 。strncmp 只是相較于 strcmp 多了一個(gè)參數(shù),這個(gè)參數(shù)是一個(gè)無符號(hào)整數(shù),代表的是字節(jié)。即我們想要比對(duì)多少字節(jié)。我們通過 cplusplus 這個(gè)網(wǎng)站可以觀察這個(gè)函數(shù)的聲明以及各個(gè)參數(shù)的意義。
6.2 strncmp 的用法
#include <stdio.h> #include <string.h> int main() { char* str1 = "abbbcd"; char* str2 = "abbbdd"; int ret=strncmp(str1, str2,3);//我們只想比較字符串的前三個(gè)字節(jié) if (ret > 0) printf("str1 > str2\n"); else if (ret < 0) printf("str1 < str2\n"); else printf("str1 == str2\n"); return 0; }
6.3 strncmp 的模擬實(shí)現(xiàn)
#include <stdio.h> #include <assert.h> int my_strncmp(const char* str1, const char* str2, unsigned int num)//兩個(gè)字符串的內(nèi)容都不需要變,所以用 const 修飾 { assert(str1 && str2); while (num-- && *str1 == *str2) { if (*str1 == '\0') return 0; str1++; str2++; } return *str1 - *str2; } int main() { char* str1 = "abbbcd"; char* str2 = "abbbdd"; int ret = my_strncmp(str1, str2, 3);//我們只想比較字符串的前三個(gè)字節(jié) if (ret > 0) printf("str1 > str2\n"); else if (ret < 0) printf("str1 < str2\n"); else printf("str1 == str2\n"); return 0; }
7. strncat —— 長(zhǎng)度受限制的字符串追加
7.1 strncat 的聲明與用處
同理,掌握了 strcat 就能掌握 strncat 。strncat 其參數(shù)多了一個(gè)無符號(hào)整形的參數(shù),其意義代表字節(jié)數(shù)。即我們可以自定義想要追加多少個(gè)字符至另一個(gè)字符串的后面。我們可以通過 cplusplus 這個(gè)網(wǎng)站觀察 strncat 的聲明以及各個(gè)參數(shù)的意義。
7.2 strncat 的用法
#include <stdio.h> #include <string.h> int main() { char str1[50] = "row row row your boat,"; char str2[] = "gently down the stream"; strncat(str1, str2, 6);//我們只想追加 6 個(gè)字節(jié)的字符到 str1 中 printf("%s\n", str1); return 0; }
在這里如果我們注意觀察的話,就會(huì)發(fā)現(xiàn)一個(gè)問題。我們追加過去的 6 個(gè)字節(jié)的字符并不包含 '\0' ,但是在最后輸出打印的時(shí)候好像在字符串尾又被賦予了 '\0' 。那么這就不得不提及 strncat 的特性,即 strncat 會(huì)在要追加的字符串后面補(bǔ) '\0' 。
7.3 strncat 的模擬實(shí)現(xiàn)
#include <stdio.h> #include <assert.h> char* my_strncat(char* dest, const char* src, unsigned int num)//str2 中的字符串不需要被修改,所以用 const 修飾 { assert(dest && src);//確保兩個(gè)指針是有效指針 char* ret = dest;//記錄返回值 while (*dest)//先找到 dest 指向的 '\0' 的位置 dest++; while (num-- && (*dest++ = *src++) )//拷貝限制的字節(jié)數(shù) ; *dest = '\0'; return ret; } int main() { char str1[50] = "row row row your boat,"; char str2[] = "gently down the stream"; my_strncat(str1, str2, 8); printf("%s\n", str1); return 0; }
小結(jié)
我們上面介紹了許多長(zhǎng)度不受限制的字符串函數(shù)和長(zhǎng)度受限制的字符串函數(shù)。那么受限制和不受限制有什么區(qū)別呢? 首先不受限制的字符串函數(shù)的靈活性是比較低的,因?yàn)橹荒懿僮髡麄€(gè)字符串。但是受限制的字符串函數(shù)的靈活性是比較高的,可以自定義操作的字符個(gè)數(shù)。并且,長(zhǎng)度受限制的字符串函數(shù)相對(duì)于長(zhǎng)度不受限制的字符串函數(shù)來說是比較安全的。注意是受限制的相對(duì)于不受限制的比較安全。
8. strstr —— 字符串查找
8.1 strstr 的聲明與用處
strstr 通過字面翻譯過來就是兩個(gè)字符串。那么其意義是在其中一個(gè)字符串里面查找另外一個(gè)字符串。我們可以通過 cplusplus 這個(gè)網(wǎng)站來觀察 strstr 的聲明以及各個(gè)參數(shù)的意義。
我們翻譯一下即可知道 strstr 的某些原理。如果在字符串 1 里面查找到了字符串 2 ,那么就返回字符串 2 出現(xiàn)在字符串 1 中的首地址。如果沒有找到字符串,就返回一個(gè)空指針。
8.2 strstr 的用法
#include <stdio.h> #include <string.h> int main() { char* str1 = "row row row your boat,gently down the stream"; char* str2 = "row your boat"; char* ret = strstr(str1, str2);//在 str1 中查找 str2 printf("%s\n", ret); return 0; }
可以看到返回值是返回 str2 第一次出現(xiàn)在 str1 中的首地址。
8.3 strstr 的模擬實(shí)現(xiàn)
#include <stdio.h> #include <assert.h> char* my_strstr(const char* str1, const char* str2)//不需要改變其內(nèi)容,用 const 修飾 { assert(str1 && str2);//避免是無效指針 const char* s1 = str1; const char* s2 = str2; const char* cp = str1;//這個(gè)指針變量是至關(guān)重要的 while (*cp) { s1 = cp; s2 = str2; //在 str1 中查找 str2 的核心循環(huán) while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0')//查找完成 return (char*)cp; cp++; } return NULL; } int main() { char* str1 = "row row row your boat,gently down the stream"; char* str2 = "row your boat"; char* ret = my_strstr(str1, str2); printf("%s\n", ret); return 0; }
我們來通過畫圖來詳解一下思路。
9. strtok —— 字符串切割
9.1 strtok 的聲明與用處
對(duì)于這個(gè)函數(shù),我們只要了解了基本的使用方法即可。我們通過 cplusplus 這個(gè)網(wǎng)站來觀察 strtok 的聲明以及各個(gè)參數(shù)的意義。
這段英文的篇幅太長(zhǎng)了,我來解釋一下核心部分:我們提供兩個(gè)參數(shù)給 strtok ,一個(gè)是字符串,一個(gè)是要切割的標(biāo)記。如果在這個(gè)字符串當(dāng)中出現(xiàn)了這個(gè)標(biāo)記,那么這個(gè)位置將被修改為 '\0' ,并且返回這個(gè)標(biāo)記之前的字符串地址。如果要進(jìn)行二次傳參,那么只需要傳一個(gè)空指針即可。
9.2 strtok 的用法
#include <stdio.h> #include <string.h> int main() { char* str1 = "row@row~row%your^boat,gently@down~the^stream"; char* str2 = "@~%^"; //將 str1 拷貝至 tmp 數(shù)組,這樣不會(huì)丟失 str1 的原始數(shù)據(jù) char tmp[50] = { 0 }; strcpy(tmp, str1); char* ret = NULL; for (ret = strtok(tmp, str2); ret != NULL; ret = strtok(NULL, str2)) { printf("%s ", ret); } return 0; }
10. strerror —— 錯(cuò)誤碼解析
10.1 strerror 的聲明與用處
我們需要普及的一個(gè)點(diǎn)是,在 C 語言中,程序發(fā)生錯(cuò)誤的時(shí)候,是有一個(gè)隱藏的全局變量 errno 的,這個(gè)變量是一個(gè)整數(shù)的,譬如 0 ,1,2,3,....等都代表不同的錯(cuò)誤信息,而 strerror 的作用就是翻譯這個(gè)錯(cuò)誤碼。我們可以通過 cplusplus 這個(gè)網(wǎng)站來觀察 strerror 的聲明以及各個(gè)參數(shù)的意義。
10.2 strerror 的用法
#include <stdio.h> #include <string.h> int main() { FILE* p; p = fopen("test.txt", "r");//在我們的工程目錄下并沒有 test.txt 這個(gè)文件 if (p == NULL)//那么打不開 p 就是一個(gè)空指針 { printf("%s\n", strerror(errno));//這里就會(huì)解釋為什么是空指針的原因 } return 0; }
到此這篇關(guān)于C語言頭文件<string.h>函數(shù)詳解的文章就介紹到這了,更多相關(guān)C語言頭文件<string.h>函數(shù)詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決codeblocks致命錯(cuò)誤:openssl/aes.h:沒有這樣的文件或目錄問題
這篇文章主要介紹了解決codeblocks致命錯(cuò)誤:openssl/aes.h:沒有這樣的文件或目錄問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06C++ 實(shí)現(xiàn)求小于n的最大素?cái)?shù)的實(shí)例
這篇文章主要介紹了C++ 實(shí)現(xiàn)求小于n的最大素?cái)?shù)的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05C++實(shí)現(xiàn)簡(jiǎn)易圖書館管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)易圖書館管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03項(xiàng)目之C++如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池
這篇文章主要介紹了項(xiàng)目之C++如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03