前言
最近要調(diào)整狀態(tài),寫(xiě)的文章質(zhì)量不佳讓大家失望,我現(xiàn)在也在反思我在做什么,我會(huì)什么,我學(xué)了什么。等我想明白的那天,我一定能跟大家頂峰相見(jiàn)的,也祝大家低頭趕路,敬事如儀。
我也在這用基普喬格的一句話感謝大家的支持:" No human is limited.",最后回到正題 我們今天講的是c語(yǔ)言缺少的一部分東西,<string.h>庫(kù)里的函數(shù),這里面的函數(shù)可大有來(lái)頭,聽(tīng)我娓娓道來(lái)。
strlen函數(shù)
你雖然看這函數(shù)這么點(diǎn)單詞,肯定不高級(jí),欸,這函數(shù)還真是不得了了,這函數(shù)大有來(lái)頭,聽(tīng)我一一分析,聽(tīng)完你知乎內(nèi)涵呀
size_t strlen ( const char * str );
可知這代碼結(jié)構(gòu)式雖然這么簡(jiǎn)單,但在不管是做題,工作中,這代碼的重要程度僅此于sizeof。所以我們引出第一個(gè)話題 跟sizeof的區(qū)別
strlen
strlen作為一個(gè)庫(kù)函數(shù),他作用于字符串已經(jīng) ‘\0’ 作為結(jié)束標(biāo)志,strlen函數(shù)返回的是在字符串中 ‘\0’ 前面出現(xiàn)的字符個(gè)數(shù)(不包含 ‘\0’ )。又有人問(wèn)了 啥意思,說(shuō)話能解決的事情要代碼干嘛,代碼展示:
#include <stdio.h>
#include <string.h>
int main(){
char str[100] = { 0 };
size_t len;
gets(str);
len = strlen(str);
printf("Length: %d\n", len);
return 0;
}
其實(shí)根據(jù)我們也能發(fā)現(xiàn) strlen是根據(jù)\0的位置找出前面字符的個(gè)數(shù)。這就是strlen中的最重要的最用,其實(shí)不管是在oj題中還是練習(xí)題,strlen能最快幫我們定位到一個(gè)數(shù)組最后的一個(gè)元素,更好去使用。
#include <stdio.h>
#include <string.h>
#include <assert.h>
void reverse(char* left, char* right) //逆序字符串(整個(gè)字符串的逆序)
{
assert(left != NULL && right != NULL);
while (left < right)
{
int ret = *left;
*left = *right;
*right = ret;
left += 1;
right -= 1;
}
}
int main()
{
char arr[100] = { 0 };
gets(arr);
int len = strlen(arr);
reverse(arr, arr + len - 1);
printf("%s", arr);
return 0;
}
就也是最簡(jiǎn)單最暴力的逆序排序了。
用到strlen找到最后一個(gè)元素。
最后要一下strlen函數(shù)的返回類型是size_t - 無(wú)符號(hào)整型
sizeof
首先注意的是sizeof更重要的在于他不是個(gè)函數(shù),而是一個(gè)操作符。
sizeof操作符以字節(jié)形式給出了其操作數(shù)的存儲(chǔ)大小。操作數(shù)可以是一個(gè)表達(dá)式或括在括號(hào)內(nèi)的類型名。操作數(shù)的存儲(chǔ)大小由操作數(shù)的類型決定。
其實(shí)簡(jiǎn)單來(lái)說(shuō) 記錄就是字符串的所占空間,可以說(shuō)跟strlen打不到一邊
但為什么總是于strlen弄混(本人也弄混),其實(shí)最主要的是對(duì)兩個(gè)的用法含義不太理解。但是看了我這一部分你會(huì)懂了很多的
sizeof使用形式: sizeof(type)
數(shù)據(jù)類型必須用括號(hào)括住: sizeof(int)
int a=10;
int arr[]={1,2,3};
char str[]="hello";
int len_a = sizeof(a);
int len_arr = sizeof(arr);
int len_str = sizeof(str);
printf("len_a=%d,len_arr=%d,len_str=%d\n",len_a,len_arr,len_str);
計(jì)算了每個(gè)不同類型的所占空間
strcpy函數(shù)
Copies the C string pointed by source into the array pointed by destination, including theter minating null character (and stopping at that point)
我們翻譯一遍就是拷貝功能,那他有啥功能讓我把英文都列舉出來(lái)了。
char *strcpy(char *dest, const char *src)
簡(jiǎn)單來(lái)看一下,我們會(huì)發(fā)現(xiàn)每個(gè)字符串都有一個(gè)‘\0’,我們進(jìn)行猜想 為啥拷貝完結(jié)束了,會(huì)不會(huì)也把‘\0’拷貝進(jìn)去了,我們上機(jī)模擬
int main()
{
char str1[] = "Sample string";
char str2[40];
char str3[40];
strcpy(str2, str1);
strcpy(str3, "copy successful");
printf("str1: %s\nstr2: %s\nstr3: %s\n", str1, str2, str3);
return 0;
}
其實(shí)我們也發(fā)現(xiàn)strcpy還是把‘\0’傳過(guò)去了,所以strcpy有以下規(guī)則
- 源字符串必須以 ‘\0’ 結(jié)束。
- 會(huì)將源字符串中的 ‘\0’ 拷貝到目標(biāo)空間。
- 目標(biāo)空間必須足夠大,以確保能存放源字符串
我們知道以下規(guī)則 那我們?nèi)?chuàng)作一個(gè)自己的strcpy函數(shù)
#include <assert.h>
//返回的是目標(biāo)空間的起始地址
char* my_strcpy(char* dest, const char*src)
{
char* ret = dest;
assert(dest && src);
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "hehe";
char arr2[20] = { 0 };
//my_strcpy(arr2, arr1);
//printf("%s\n", arr2);
printf("%s\n", my_strcpy(arr2, arr1));
return 0;
}
通過(guò)使用欸,跟原本函數(shù)不一樣,我們就知道了這可能就是strpy函數(shù)的源碼了。
學(xué)到這,你其實(shí)就發(fā)現(xiàn)其實(shí)這些函數(shù)都是程序都是程序員模擬的。
strcat函數(shù)
這個(gè)函數(shù)可能很多人沒(méi)見(jiàn)過(guò),那會(huì)不多說(shuō) 我放英文原意
Copies the first num characters of source to destination. If the end
of the source C string (which is signaled by a null-character) is
found before num characters have been copied, destination is padded
with zeros until a total of num characters have been written to it
原意就是 在后面字符串中往后添加后面的數(shù)組的內(nèi)容
char * strcat ( char * destination, const char * source );
在這int main()
{
char arr1[20] = "hello \0xxxxxxxxx";
char arr2[] = "world";
//追加
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
我通過(guò)運(yùn)行也發(fā)現(xiàn)得出結(jié)果是hello world
源字符串必須以 ‘\0’ 結(jié)束。
目標(biāo)空間必須有足夠的大,能容納下源字符串的內(nèi)容。
目標(biāo)空間必須可修改
那如果是自己給自己追加呢,上代碼
int main()
{
char arr2[] = "world";
//追加
strcat(arr2, arr2);
printf("%s\n", arr2);
return 0;
}
我們會(huì)發(fā)現(xiàn) 這個(gè)代碼一直在循環(huán),下面也是我畫(huà)的圖,根據(jù)圖你會(huì)發(fā)現(xiàn)‘\0’被原本覆蓋了。
我們知道了規(guī)則,寫(xiě)出一串代碼就變了容易很多
自作代碼:
#include<assert.h>
char* my_strcat(char* dest, const char*src)
{
assert(dest && src);
char* ret = dest;
//找目標(biāo)空間中的\0
while (*dest != '\0')
{
dest++;
}
//拷貝
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "bit";
my_strcat(arr1, arr1);
printf("%s\n", arr1);
//char arr1[20] = "hello ";
//char arr2[] = "world";
//追加
//my_strcat(arr1, arr2);
//printf("%s\n", arr1);
return 0;
}
這是代碼的形成,通過(guò)這個(gè)代碼更能分析出strcat的規(guī)則。
strcmp函數(shù)
這個(gè)函數(shù)是str+cmp組成的,欸,我們要警覺(jué)了,但我們還是要猜想是不是一個(gè)比較兩個(gè)數(shù)組的函數(shù),那我們就看下
This function starts comparing the first character of each string. If
they are equal to each other, it continues with the following pairs
until the characters differ or until a terminating null-character is
reached.
我們會(huì)發(fā)現(xiàn)這就是一個(gè)比較兩數(shù)組的函數(shù),我們用代碼測(cè)試一下他的規(guī)則
int main()
{
//char* p = "abcdef";
比較2個(gè)字符串的內(nèi)容的時(shí)候,不能使用==,應(yīng)該使用strcmp
//if ("abcdef" == "bbcdef")//這里比較的是連個(gè)字符串首字符的地址,而并不是字符串的內(nèi)容
//{
//}
char arr1[] = "abq";
char arr2[] = "abq";
char arr3[] = "abc";
char arr4[] = "abz";
int ret = strcmp(arr1, arr2);
int ret1 = strcmp(arr1, arr3);
int ret2 = strcmp(arr1, arr4);
printf("%d\n", ret);
printf("%d\n", ret1);
printf("%d\n", ret2);
return 0;
}
所以我們發(fā)現(xiàn)以下規(guī)則:
標(biāo)準(zhǔn)規(guī)定:
第一個(gè)字符串大于第二個(gè)字符串,則返回大于0的數(shù)字
第一個(gè)字符串等于第二個(gè)字符串,則返回0
第一個(gè)字符串小于第二個(gè)字符串,則返回小于0的數(shù)字
就是一個(gè)一個(gè)字母比較 ,如果相同則跳過(guò),直到比較到一個(gè)ascII不相同的字符,則停下,顯示屏輸出返回值。
知道一下規(guī)則,我們模擬此函數(shù)
#include <stdio.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;
//if (*str1 > *str2)
// return 1;
//else
// return -1;
}
int main()
{
char arr1[] = "abzqw";
char arr2[] = "abq";
/*int ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);*/
if (strcmp(arr1, arr2) >0)
printf(">\n");
return 0;
}
通過(guò)一個(gè)一個(gè)指針指向的函數(shù)進(jìn)行比較,使的比較更簡(jiǎn)單。這也是學(xué)習(xí)的意義呀。
總結(jié)
寫(xiě)文章其實(shí)對(duì)于我來(lái)說(shuō)就是放松。面對(duì)嚴(yán)峻的考試,痛苦的會(huì)議,學(xué)校的壓力。
唯有寫(xiě)文章可以放松自我,提升自我,讓自己有更好的理解,而我是一個(gè)喜歡分享生活,享受生活的人,有生活煩惱來(lái)找我,有故事來(lái)找我,有酒,私信必回。
最后也祝所有看我的文章的人,生意順利,沒(méi)有任何煩惱,幸福走下后面的路。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-793246.html
用林俊杰的話作為結(jié)尾:輸了你贏了世界又如何。加油各位文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-793246.html
到了這里,關(guān)于字符函數(shù)和字符串函數(shù)詳解(1)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!