?歡迎來到 Claffic 的博客???????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????專欄:《C生萬物 | 先來學(xué)C》??
前言:
過了指針這個坎后,下一步就是C語言中關(guān)于字符的處理,這一期來講講常用字符函數(shù)和字符串函數(shù):strlen,strcpy,strcat,memcpy,memmove,memcmp 等。?
目錄
Part1:寫在前面
Part2:函數(shù)介紹
1.strlen
2.strcpy
3.strcat
4.strcmp
5.strncpy
6.strncat
7.strncmp
8.strstr
9.strtok
10.memcpy
11.memmove
12.memcmp?
Part1:寫在前面
說到字符串大家應(yīng)該不陌生了,但你知道如何處理字符串嗎?
Part2:函數(shù)介紹
1.strlen
strlen - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strlen/?kw=strlen
size_t strlen ( const char * str );
這個函數(shù)是獲取字符串長度的,下面是注意的點:
? 字符串已經(jīng) '\0' 作為結(jié)束標(biāo)志, strlen 函數(shù)返回的是在字符串中 '\0' 前面出現(xiàn)的字符個數(shù)(不包含 '\0' );? 參數(shù)指向的字符串必須要以 '\0' 結(jié)束;? 注意函數(shù)的返回值為 size_t ,是無符號的。
可以利用此函數(shù)來比較兩個字符串的大?。?/p>
#include<stdio.h>
#include<string.h>
int main()
{
const char* str1 = "abcdef";
const char* str2 = "ggg";
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
???????運行結(jié)果:?
2.strcpy
strcpy - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strcpy/?kw=strcpy
char* strcpy(char * destination, const char * source );
這個函數(shù)是用來拷貝字符串的
注意傳參:將后部的字符串拷貝到前部的空間中
? 源字符串必須以 '\0' 結(jié)束;? 會將源字符串中的 '\0' 拷貝到目標(biāo)空間;? 目標(biāo)空間必須足夠大,以確保能存放源字符串;? 目標(biāo)空間必須可變。
例子:
#include<stdio.h>
#include<string.h>
int main()
{
char str1[40];
const char* str2 = "abc";
char* str = strcpy(str1, str2);
printf("%s\n", str);
return 0;
}
????????運行結(jié)果:?
3.strcat
strcat - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strcat/?kw=strcat
char * strcat ( char * destination, const char * source );
這個函數(shù)是在一個字符串末尾追加字符串的
? 源字符串必須以 '\0' 結(jié)束;? 目標(biāo)空間必須有足夠的大,能容納下源字符串的內(nèi)容;? 目標(biāo)空間必須可修改。
例子:
#include<stdio.h>
#include<string.h>
int main()
{
char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");
puts(str); // 輸出字符串,傳遞char*類型,遇到\0結(jié)束
return 0;
}
???????運行結(jié)果:
4.strcmp
strcmp - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strcmp/?kw=strcmp
int strcmp ( const char * str1, const char * str2 );
這個函數(shù)的作用就是比較兩個字符串的
標(biāo)準(zhǔn)規(guī)定:?
? 第一個字符串大于第二個字符串,則返回大于0 的數(shù)字;? 第一個字符串等于第二個字符串,則返回0;? 第一個字符串小于第二個字符串,則返回小于0 的數(shù)字。
注意注意:不是比較字符串的長度,而是一個字符一個字符地比較字符的 ASCII 碼值
例子:
#include<stdio.h>
#include<string.h>
int main()
{
char* str1 = "abcdef";
char* str2 = "abcdef";
char* str3 = "abcde";
char* str4 = "cpp";
printf("%d\n", strcmp(str1, str2));
printf("%d\n", strcmp(str1, str3));
printf("%d\n", strcmp(str1, str4)); // 第一個字符就小
return 0;
}
????????運行結(jié)果:
其實這個函數(shù)的最大作用就是0的情況,即判斷兩個字符串相等。
5.strncpy
strncpy - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strncpy/?kw=strncpy
char * strncpy ( char * destination, const char * source, size_t num );
這個函數(shù)也是拷貝字符串的,不過它相比 strcpy 多了一個參數(shù) num ,說明可以指定拷貝字符串的字符個數(shù)。
? 拷貝? num? 個字符從源字符串到目標(biāo)空間;? 如果源字符串的長度小于? num? ,則拷貝完源字符串之后,在目標(biāo)的后邊追加 0 ,直到? num 個。
例子:
#include<stdio.h>
#include<string.h>
int main()
{
char str1[40] = { '0' };
char str2[30] = { '0' };
const char* str3 = "abcdef";
strncpy(str1, str3, 6);
strncpy(str2, str3, 2);
printf("%s\n", str1);
printf("%s\n", str2);
return 0;
}
???????輸出結(jié)果:?
6.strncat
?strncat - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strncat/?kw=strncat
這個函數(shù)也是,加了 n ,可控制要追加的字符長度
? 追加字符,
例子:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20];
char str2[20];
strcpy(str1, "To be "); str1 中存入 To be
strcpy(str2, "or not to be"); str2 中存入 or not to be
strncat(str1, str2, 6); str1 追加 str2 中的6個字符 or no
puts(str1);
return 0;
}
???????輸出結(jié)果:?
7.strncmp
?strncmp - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strncmp/?kw=strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
相比 strcmp,它可以指定最多比較 num 個字符
? 比較到出現(xiàn)另個字符不一樣或者一個字符串結(jié)束或者 num 個字符全部比較完。
例子:
#include <stdio.h>
#include <string.h>
int main()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts("Looking for R2 astromech droids...");
for (n = 0; n < 3; n++)
{
if (strncmp(str[n], "R2xx", 2) == 0)
printf("found %s\n", str[n]);
}
return 0;
}
????????輸出結(jié)果:?
這個例子的意思就是在 str 中尋找含有 R2 的字符串。
8.strstr
strstr - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strstr/?kw=strstr
char * strstr ( const char *str1, const char * str2);
這個函數(shù)的作用就是尋找相等的字符串,返回指針類型
? 在 str1 中尋找 str2 ,找到了就返回指向 str1 中與 str2 相同字符的指針,如果沒有(str2 不是 str1 的一部分),就返回 NULL;
? 匹配過程不包括空字符串。?
例子:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "This is a simple string";
char* pch;
pch = strstr(str, "simple");
if (pch != NULL)
strncpy(pch, "sample", 6);
puts(str);
return 0;
}
???????輸出結(jié)果:
簡單解釋,在 str 中尋找字符串 simple,將其地址保存到 pch 中,再將 simple 替換為 sample,最終輸出替換后的結(jié)果。
9.strtok
strtok - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/strtok/?kw=strtok
char * strtok ( char * str, const char * sep );
這個函數(shù)是做字符串切分的
? sep? 參數(shù)是個字符串,定義了用作分隔符的字符集合;? 第一個參數(shù)指定一個字符串,它包含了 0? 個或者多個由? sep ? 字符串中一個或者多個分隔符分割的標(biāo)記;? strtok 函數(shù)找到 str 中的下一個標(biāo)記,并將其用 \0 結(jié)尾,返回一個指向這個標(biāo)記的指針;(注:strtok函數(shù)會改變被操作的字符串,所以在使用? strtok? 函數(shù)切分的字符串一般都是臨時拷貝的內(nèi)容并且可修改。)? strtok 函數(shù)的第一個參數(shù) 不 為 NULL ,函數(shù)將找到 str 中第一個標(biāo)記, strtok ? 函數(shù)將保存它在字符串中的位置;? strtok 函數(shù)的第一個參數(shù)為 NULL ,函數(shù)將在同一個字符串中被保存的位置開始,查找下一個標(biāo)記;? 如果字符串中不存在更多的標(biāo)記,則返回 NULL 指針。
看著挺復(fù)雜的,其實... ...就是復(fù)雜的。
接下來看個例子,相信會好些:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "- This, a sample string.";
char* pch;
printf("Splitting string \"%s\" into tokens:\n", str);
pch = strtok(str, " ,.-"); // 分割符可以是字符集合
while (pch != NULL)
{
printf("%s\n", pch);
pch = strtok(NULL, " ,.-");
}
return 0;
}
????????輸出結(jié)果:
這個例子就是將字符串 - This, a sample string. 按照 , - . 三個分隔符切割,注意進(jìn)行多個字符的切割時,要進(jìn)行?pch = strtok(NULL, " ,.-"); 操作,對應(yīng)?strtok 函數(shù)的第一個參數(shù)為 NULL ,函數(shù)將在同一個字符串中被保存的位置開始,查找下一個標(biāo)記?
10.memcpy
?
memcpy - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/memcpy/?kw=memcpy
void * memcpy ( void * destination, const void * source, size_t num );
這個 void 類型不是沒有,而是可以接受多種類型?
這個函數(shù)是復(fù)制數(shù)據(jù)用的
? 函數(shù) ?memcpy? 從? source? 的位置開始向后復(fù)制 ?num? 個字節(jié)的數(shù)據(jù)到? destination? 的內(nèi)存位置;? 這個函數(shù)在遇到 '\0' 的時候并 不會 停下來;? 如果 source ? 和? destination ? 有任何的重疊,復(fù)制的結(jié)果都是未定義的。 ?
例子:
#include <stdio.h>
#include <string.h>
struct
{
char name[40];
int age;
} person, person_copy;
int main()
{
char myname[] = "Pierre de Fermat";
/* using memcpy to copy string: */
memcpy(person.name, myname, strlen(myname) + 1);// +1是要把'\0'拷貝上
person.age = 46;
/* using memcpy to copy structure: */
memcpy(&person_copy, &person, sizeof(person));
printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
return 0;
}
???????輸出結(jié)果:
解釋:定義了一個結(jié)構(gòu)體,包含名字和年齡,先將 myname 中的內(nèi)容拷貝到結(jié)構(gòu)體的 name 成員中,再將整個結(jié)構(gòu)體拷貝給自己(可拷貝類型有多種)。?
11.memmove
?
memmove - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/memmove/?kw=memmove
void * memmove ( void * destination, const void * source, size_t num );
參數(shù)類型與 memcpy 是相同的,兩者的不同在哪里呢?
? 差別就是?memmove?函數(shù)處理的源內(nèi)存塊和目標(biāo)內(nèi)存塊是可以重疊的;
? 如果源空間和目標(biāo)空間出現(xiàn)重疊,就得使用 memmove?函數(shù)處理。
也就是說,在不確定源空間和目標(biāo)空間是否重疊的情況下,memmove 可以保證拷貝的內(nèi)容是正確的,所以 memmove 相比 memcpy 更安全。
例子:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "memmove can be very useful......";
memmove(str + 20, str + 15, 11);
puts(str);
return 0;
}
???????輸出結(jié)果:
這個例子可以充分說明源空間和目標(biāo)空間存在重疊的時候可以保證拷貝成功。
12.memcmp?
memcmp - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/cstring/memcmp/?kw=memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
看返回類型是 int 類型,啊哈,這個函數(shù)是比較兩個數(shù)據(jù)的
? 比較從 ?ptr1 ? 和 ?ptr2? 指針開始的? num? 個字節(jié);
例子:
#include <stdio.h>
#include <string.h>
int main()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n = memcmp(buffer1, buffer2, sizeof(buffer1));
// 注意:大寫字符的ASCII碼值 小于 小寫字符的ASCII碼值
if (n > 0)
printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
else if (n < 0)
printf("'%s' is less than '%s'.\n", buffer1, buffer2);
else
printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
return 0;
}
???????輸出結(jié)果:
大寫字符的ASCII碼值 小于 小寫字符的ASCII碼值
所以才會有這樣的結(jié)果,跟想想中的不一樣... ...?
總結(jié):?
這期主要是帶大家認(rèn)識各種常見的字符串處理函數(shù),知道有這些好用的函數(shù)并且會應(yīng)用就可以了,下期帶大家嘗試實現(xiàn)幾個其中的函數(shù)。
碼文不易?文章來源:http://www.zghlxwxcb.cn/news/detail-462314.html
如果你覺得這篇文章還不錯并且對你有幫助,不妨支持一波哦????????文章來源地址http://www.zghlxwxcb.cn/news/detail-462314.html
到了這里,關(guān)于【C生萬物】 字符串&內(nèi)存函數(shù)篇 (上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!