求字符串長(zhǎng)度
size_t strlen ( const char * str );
#includeint main()
{int len = strlen("abcdef");
printf("%d\n", len);
return 0;
}//6
結(jié)果
上一篇寫(xiě)strlen()函數(shù)的模擬實(shí)現(xiàn)中有3種方法:大齡失業(yè)學(xué)生轉(zhuǎn)碼日記:2022-12-02(strlen函數(shù))
1、計(jì)數(shù)器的方法;
2、遞歸的方法;
3、指針-指針的方法
#include
#include//因?yàn)榍蟮氖亲址L(zhǎng)度,不會(huì)改變str所指向字符串的內(nèi)容,所以加const修飾,
//即使str所指向的內(nèi)容想要被修改也沒(méi)有機(jī)會(huì)了。
int my_strlen(const char* str)
{//斷言:保證指針的有效性:
assert(str != NULL);
//用計(jì)數(shù)器的方法實(shí)現(xiàn):
int count = 0;
while (*str != '\0')//或while(*str)都可以
{count++;
str++;
}
return count;
}
int main()
{int len = my_strlen("abcdef");
//表面?zhèn)鞯氖亲址?,?shí)際傳的是字符串首字符地址。
printf("%d\n", len);
return 0;
}
結(jié)果
sizeof——是操作符,計(jì)算大小。sizeof計(jì)算的結(jié)果返回的類(lèi)型是size_t;size_t 是專(zhuān)門(mén)為sizeof的返回值設(shè)計(jì)的。
size_t——其實(shí)是unsigned int類(lèi)型,只表示正數(shù)。
strlen()函數(shù)返回的是無(wú)符號(hào)數(shù),兩個(gè)無(wú)符號(hào)的數(shù)相減得到的也是無(wú)符號(hào)的數(shù),比如下述代碼中會(huì)把-3當(dāng)做無(wú)符號(hào)的數(shù)處理,是一個(gè)非常大的正數(shù)而會(huì)引入bug。
#include#includeint main()
{if (strlen("abc") - strlen("abcdef") >0)
{printf(">");
}
else
{printf("<=");
}
return 0;
}
結(jié)果
strlen()的返回值可以寫(xiě)成int類(lèi)型,size_t類(lèi)型或unsigned_int類(lèi)型都可以。
上述代碼強(qiáng)制類(lèi)型轉(zhuǎn)換為int可以得出“<=”:
#include#includeint main()
{if ((int)strlen("abc") - (int)strlen("abcdef") >0)
{printf(">");
}
else
{printf("<=");
}
return 0;
}
結(jié)果
使用庫(kù)函數(shù)時(shí)需要包含頭文件,不包含會(huì)有bug。
使用strlen()函數(shù)時(shí):
字符串以 ‘\0’ 作為結(jié)束標(biāo)志,strlen函數(shù)返回的是在字符串中 ‘\0’ 前面出現(xiàn)的字符個(gè)數(shù)(不包
含 ‘\0’ )。
參數(shù)指向的字符串必須要以 ‘\0’ 結(jié)束。
函數(shù)的返回值為size_t,是無(wú)符號(hào)的。
strcpy()函數(shù)用來(lái)拷貝字符串,會(huì)把源字符串內(nèi)容拷貝到目標(biāo)空間中,\0也會(huì)被拷貝過(guò)去。
char* strcpy(char * destination, const char * source );
把a(bǔ)rr1的內(nèi)容拷貝放到arr2中
#include#includeint main()
{char arr1[] = "abcdef";
char arr2[20] = {0 };
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
結(jié)果
注意:在使用strcpy()函數(shù)時(shí):
源字符串必須以 ‘\0’ 結(jié)束。
會(huì)將源字符串中的 ‘\0’ 拷貝到目標(biāo)空間。
目標(biāo)空間必須足夠大,以確保能存放源字符串,防止造成越界訪問(wèn)而使程序崩潰。
目標(biāo)空間必須可變。
#include#includeint main()
{char arr1[] = {'a','b','c','d','e','f' };
char arr2[20] = "XXXXXXXX";
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
程序會(huì)崩潰,拷貝內(nèi)容混亂
可以改為如下寫(xiě)法
#include#includeint main()
{char arr1[] = {'a','b','c','d','e','f','\0' };
char arr2[20] = "XXXXXXXX";
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
結(jié)果
strcpy()函數(shù)可以將源字符串內(nèi)容拷貝到已有數(shù)據(jù)的數(shù)組中。
注意:遇到\0的時(shí)候,打印也結(jié)束了。所以即使目標(biāo)空間在\0(這里的\0是從源數(shù)據(jù)中拷貝的)后面還有數(shù)據(jù)也不能打印了。
#include#includeint main()
{char arr1[] = {'a','b','c','\0','d','e','f' };
char arr2[20] = "XXXXXXXX";
strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
結(jié)果
strcpy()函數(shù)的模擬實(shí)現(xiàn):
#include#include
//把源頭數(shù)據(jù)拷貝到目標(biāo)空間中,整個(gè)過(guò)程中,源數(shù)據(jù)是不需要發(fā)生變化的,目標(biāo)空間需要變化
//所以在源數(shù)據(jù)前面可以用const修飾限定,保護(hù)源頭數(shù)據(jù)。
char* my_strcpy(char* dest, const char* src)
{char* ret = dest;
assert(dest && src);
while (*src)
{*dest = *src;
dest++;
src++;
}
*dest = *src;//拷貝\0
return ret;
}
int main()
{char arr1[] = {'a','b','c','d','e','f','\0' };
char arr2[] = "xxxxxxxx";
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}//abcdef
結(jié)果
把源字符串內(nèi)容追加到目標(biāo)字符串的后面。
char * strcat ( char * destination, const char * source );
strcpy()函數(shù)是拷貝,覆蓋原來(lái)的數(shù)據(jù)。
strcat()函數(shù)是把源字符串內(nèi)容追加到目標(biāo)字符串的后面。
#includeint main()
{char arr1[30] = "hello";
char arr2[] = "world";
//把a(bǔ)rr2中的數(shù)據(jù)追加到arr1中
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
結(jié)果
原理:arr2找到arr1的‘\0’,把‘\0’覆蓋掉然后拷貝arr2的內(nèi)容。這里arr2是源字符串,‘\0’不會(huì)拷貝。
#include#includeint main()
{char arr1[30] = "hello";
char arr2[] = {'w','o','r','l','d' };
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
源字符串并沒(méi)有以’\0’結(jié)束,程序崩潰
改為如下
#include#includeint main()
{char arr1[30] = {'h','e','l','l','o'};
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
結(jié)果
用來(lái)比較兩個(gè)字符串。比較的是對(duì)應(yīng)位置上的字符的大小——比較的是字符的ASCII碼值。a、b、c、d……按照順序ASCII碼值依次增大。
int strcmp ( const char * str1, const char * str2 );
標(biāo)準(zhǔn)規(guī)定:
第一個(gè)字符串大于第二個(gè)字符串,則返回大于0的數(shù)字;
第一個(gè)字符串等于第二個(gè)字符串,則返回0;
第一個(gè)字符串小于第二個(gè)字符串,則返回小于0的數(shù)字。
#include#includeint main()
{char arr1[] = "abcdef";
char arr2[] = "bbq";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
結(jié)果
比的不是長(zhǎng)度。
“abcdef”;
“bbq”;
這兩個(gè)字符串對(duì)應(yīng)的第一個(gè)字符比,a“abcdef”;
“abq”;
這兩個(gè)字符串對(duì)應(yīng)的第一個(gè)字符相等,就比較第二個(gè)對(duì)應(yīng)的字符,第二個(gè)字符相等就比較第三對(duì)……直到比較雙方的‘\0’。
#include#includeint main()
{char arr1[] = "bbq";
char arr2[] = "bbq";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
#include#includeint main()
{char arr1[] = "qbq";
char arr2[] = "bbq";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
結(jié)果
模擬實(shí)現(xiàn)strcmp()函數(shù):
#include#include
int my_strcmp(const char* str1, const char* str2)//因?yàn)橹辉L問(wèn)內(nèi)容不會(huì)修改這兩個(gè)字符串內(nèi)容所以可以加const保護(hù)
{//因?yàn)楹竺嬗袑?duì)這兩個(gè)指針解引用操作,所以需要斷言是否是空指針
assert(str1 && str2);
while (*str1 == *str2)
{if (*str1 == '\0')
{ return 0;
}
str1++;
str2++;
}
if (*str1 >*str2)
{return 1;
}
else
{return -1;
}
}
int main()
{char arr1[] = "abc";
char arr2[] = "abcd";
printf("%d\n", my_strcmp(arr1, arr2));
return 0;
}
結(jié)果
‘\0’的ASCII碼值是0。
注意:兩個(gè)字符串是不能相減的,兩個(gè)字符串不能用等號(hào)來(lái)判斷是否相等,更不能相減。
if ("abq" == "abc")
錯(cuò)誤代碼,"abq"表達(dá)式產(chǎn)生的是它的a的地址(首字符的地址);
"abc"表達(dá)式產(chǎn)生的是它的a的地址;
這兩個(gè)地址一定不相等,所以不能用等號(hào)比。
if("abc" - "abq")
意思是這兩個(gè)地址相減比較的是地址,就不是比較的兩個(gè)字符串的內(nèi)容是否相等了;
所以?xún)蓚€(gè)字符串不能相加,不能相減。
如果兩個(gè)字符串是常量字符串,那么二者的地址是相同的;
但是如果是兩個(gè)字符串?dāng)?shù)組,即使字符串內(nèi)容相同地址也不會(huì)相同,因?yàn)槭莾蓚€(gè)完全不同的空間。
總結(jié):
1 strcpy()函數(shù)在拷貝的時(shí)候,直到把源字符串中的\0拷貝完之后才停止拷貝,即拷貝到\0。
2 strcat()函數(shù)在追加的時(shí)候,也只在乎\0的問(wèn)題,追加到\0。
3 strcmp()函數(shù)比較字符串的時(shí)候不相等就結(jié)束,相等就比較到\0。
4 這三個(gè)函數(shù)在拷貝的時(shí)候并沒(méi)有考慮拷貝的長(zhǎng)度,一直到\0,所以這三個(gè)函數(shù)均是長(zhǎng)度不受限制的字符串函數(shù),與字符串的長(zhǎng)度沒(méi)有關(guān)系。這三者頭文件均是
拷貝num個(gè)字符從源字符串到目標(biāo)空間。
如果源字符串的長(zhǎng)度小于num,則拷貝完源字符串之后,在目標(biāo)的后邊追加0,直到num個(gè)。
char * strncpy ( char * destination, const char * source, size_t num );
#include#includeint main()
{char arr1[] = "xxxxxxxxxxxxx";
char arr2[] = "hello world";
//若把a(bǔ)rr2中的hello這5個(gè)字符拷貝到arr1中:
strncpy(arr1, arr2, 5);//只是把前5個(gè)hello拷貝過(guò)去
printf("%s\n", arr1);
return 0;
}
結(jié)果
如果長(zhǎng)度不夠,會(huì)主動(dòng)放上’\0’
#include#includeint main()
{char arr1[] = "xxxxxxxxxxxxx";
char arr2[] = "he";
strncpy(arr1, arr2, 5);
printf("%s\n", arr1);
return 0;
}
結(jié)果
如果長(zhǎng)度不夠,會(huì)主動(dòng)放上’\0’
strncpy()函數(shù)相對(duì)較靈活,更可控、相對(duì)安全。
把源字符串的num個(gè)字符追加到目標(biāo)空間中。
char * strncat ( char * destination, const char * source, size_t num );
#include#includeint main()
{char arr1[20] = "hello";
char arr2[] = "world";
//把a(bǔ)rr2中的world這5個(gè)字符追加到arr1中
strncat(arr1, arr2, 5);
printf("%s\n", arr1);
return 0;
}
結(jié)果
#include#includeint main()
{char arr1[20] = "hello";
char arr2[] = "world";
//把a(bǔ)rr2中的world中的3個(gè)字符追加到arr1中
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
結(jié)果
#include#includeint main()
{char arr1[20] = "hello\0";
char arr2[] = "world";
//把a(bǔ)rr2中的world中的3個(gè)字符追加到arr1中
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
結(jié)果
#include#includeint main()
{char arr1[20] = "hello\0xxxxxxx";
char arr2[] = "world";
//把a(bǔ)rr2中的world中的3個(gè)字符追加到arr1中
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
結(jié)果
strncat追加后還是字符串,所以會(huì)在追加指定的幾個(gè)字符后主動(dòng)自己加上\0,所以追加完就停止打印。
#include#includeint main()
{char arr1[20] = "hello\0xxxxxxx";
char arr2[] = "world";
//把a(bǔ)rr2中的world這5個(gè)字符追加到arr1中
strncat(arr1, arr2, 5);
printf("%s\n", arr1);
return 0;
}
結(jié)果
#include#includeint main()
{char arr1[20] = "helloxxxxxxx";
char arr2[] = "world";
strncat(arr1, arr2, 7);
printf("%s\n", arr1);
return 0;
}
結(jié)果
#include#includeint main()
{char arr1[20] = "helloxxxxxxx";
char arr2[] = "world";
//把a(bǔ)rr2中的world中3個(gè)字符追加到arr1中
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
結(jié)果
注意:
1、遇到\0;
2、追加的數(shù)字小于源字符串長(zhǎng)度時(shí),追加完要追加的字符后就不追加了。
比較num個(gè)字符串大小。
int strncmp ( const char * str1, const char * str2, size_t num );
#include#includeint main()
{char arr1[] = "abcdef";
char arr2[] = "abcqqqqqq";
int ret = strncmp(arr1, arr2, 3);
printf("%d\n", ret);
return 0;
}
結(jié)果
#include#includeint main()
{char arr1[] = "abcdef";
char arr2[] = "abcqqqqqq";
int ret = strncmp(arr1, arr2, 4);
printf("%d\n", ret);
return 0;
}
結(jié)果
#include#includeint main()
{char arr1[] = "abcwef";
char arr2[] = "abcqqqqqq";
int ret = strncmp(arr1, arr2, 4);
printf("%d\n", ret);
return 0;
}
結(jié)果
總結(jié):
strncpy()函數(shù) —— 拷貝
strncat ()函數(shù) —— 追加
strncmp()函數(shù) —— 比較
這三者是長(zhǎng)度受限制的字符串函數(shù),頭文件均是
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧