C語言頭文件<string.h>函數(shù)詳解
1. strlen —— 求字符串長度
1.1 strlen 的聲明與用處
strlen ,我們有一些英語基礎(chǔ)的話不難通過字面意思來知道這個(gè)函數(shù)是干嘛用的,str 表 string ,字符串的意思,len 表 length ,長度的意思。也就是說,strlen 是求字符串長度的函數(shù)。我們通過 cplusplus 這個(gè)網(wǎng)站來觀察 strlen 的函數(shù)聲明以及各個(gè)參數(shù)的意義。

我們翻譯可以知道,strlen 所求的字符串長度是字符串結(jié)束標(biāo)志之前的字符個(gè)數(shù)。即我們假設(shè)有字符串 "hello world" ,那么所求的字符串長度就是 '\0' 之前的所有字符個(gè)數(shù),也就是 11 。那么這個(gè)字符串長度是通過返回值返回的,所以我們要知道所求的字符串長度是多少就必須定義一個(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);
//這種寫法也可以輸出長度
//printf("%d\n", strlen(str1));
//printf("%d\n", strlen(str2));
return 0;
}
我們要注意的一點(diǎn)是,strlen 的返回值是一個(gè) size_t 類型,即無符號整數(shù)。 它的意義在于求長度時(shí)是不可能求出負(fù)數(shù)的,所以一定程度上優(yōu)化了內(nèi)存(使用有符號整形的話會(huì)浪費(fèi)掉用來存儲負(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 的聲明與用處
我們對其字面翻譯進(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' 的。也就是說即使我拷貝過去的字符串長度沒有數(shù)組原來的字符串長度長,但是我包含 '\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)行下一對字符比較,直到兩個(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 —— 長度受限制的字符串拷貝
5.1 strncpy 的聲明與用處
strncpy 與 strcpy 的區(qū)別就是 strncpy 多了一個(gè)參數(shù)。這個(gè)參數(shù)是一個(gè)無符號的整數(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 —— 長度受限制的字符串比較
6.1 strncmp 的聲明與用處
strncmp 與 strcmp 的功能是一模一樣的,原理也就是一模一樣的。也就是說掌握了 strcmp 就能夠掌握 strncmp 。strncmp 只是相較于 strcmp 多了一個(gè)參數(shù),這個(gè)參數(shù)是一個(gè)無符號整數(shù),代表的是字節(jié)。即我們想要比對多少字節(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 —— 長度受限制的字符串追加
7.1 strncat 的聲明與用處
同理,掌握了 strcat 就能掌握 strncat 。strncat 其參數(shù)多了一個(gè)無符號整形的參數(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é)
我們上面介紹了許多長度不受限制的字符串函數(shù)和長度受限制的字符串函數(shù)。那么受限制和不受限制有什么區(qū)別呢? 首先不受限制的字符串函數(shù)的靈活性是比較低的,因?yàn)橹荒懿僮髡麄€(gè)字符串。但是受限制的字符串函數(shù)的靈活性是比較高的,可以自定義操作的字符個(gè)數(shù)。并且,長度受限制的字符串函數(shù)相對于長度不受限制的字符串函數(shù)來說是比較安全的。注意是受限制的相對于不受限制的比較安全。
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 的聲明與用處
對于這個(gè)函數(shù),我們只要了解了基本的使用方法即可。我們通過 cplusplus 這個(gè)網(wǎng)站來觀察 strtok 的聲明以及各個(gè)參數(shù)的意義。

這段英文的篇幅太長了,我來解釋一下核心部分:我們提供兩個(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決codeblocks致命錯(cuò)誤:openssl/aes.h:沒有這樣的文件或目錄問題
這篇文章主要介紹了解決codeblocks致命錯(cuò)誤:openssl/aes.h:沒有這樣的文件或目錄問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
C++ 實(shí)現(xiàn)求小于n的最大素?cái)?shù)的實(shí)例
這篇文章主要介紹了C++ 實(shí)現(xiàn)求小于n的最大素?cái)?shù)的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05
C++實(shí)現(xiàn)簡易圖書館管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡易圖書館管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
項(xiàng)目之C++如何實(shí)現(xiàn)數(shù)據(jù)庫連接池
這篇文章主要介紹了項(xiàng)目之C++如何實(shí)現(xiàn)數(shù)據(jù)庫連接池問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03

