盤(pán)點(diǎn)分析C語(yǔ)言中少見(jiàn)卻強(qiáng)大的字符串函數(shù)
正片開(kāi)始
字符串函數(shù)
首先神魔是字符串函數(shù)?
指的是編程語(yǔ)言中用來(lái)進(jìn)行字符串處理的函數(shù),如C,pascal,Visual以及LotusScript中進(jìn)行字符串拷貝,計(jì)算長(zhǎng)度,字符查找等的函數(shù)。 功能:把src所指由NUL結(jié)束的字符串復(fù)制到dest所指的 數(shù)組 中。 返回指向dest結(jié)尾處字符 (NUL)的 指針 。
像之前我寫(xiě)到過(guò)的 strcpy,strcat,strcmp 這些函數(shù)都屬于長(zhǎng)度不受限的字符串函數(shù),由此就有下面兩種分類(lèi)
1.長(zhǎng)度不受限的字符串函數(shù)
2.長(zhǎng)度受限的字符串函數(shù)
長(zhǎng)度不受限就是以‘ \0 ’為函數(shù)結(jié)束標(biāo)準(zhǔn)的判定,當(dāng)對(duì)象沒(méi)給定 ’ \0 '時(shí),就跑不出結(jié)果或者報(bào)錯(cuò);相反則為長(zhǎng)度受限。我再整理一下,好做個(gè)對(duì)比:
strcpy
字符串拷貝,把指向的字符串復(fù)制到目標(biāo)字符串,聲明為
char *strcpy(char *dest, const char *src)
strcat
字符串連續(xù),把指向的字符串追加到目標(biāo)字符串的結(jié)尾(無(wú)間隔),聲明為:
char *strcat(char *dest, const char *src)
strcmp
把所指向的字符串和目標(biāo)字符串進(jìn)行比較, 返回值大小決定二者的相對(duì)大小,聲明如下:
int strcmp(const char *str1, const char *str2)
以上三種是函數(shù)的長(zhǎng)度受限,我們可以變 strncpy,strncat 和 strncmp,就是長(zhǎng)度不受限函數(shù)了,相比多了一個(gè) n ,這個(gè) n 是指函數(shù)作用范圍最多在前 n 個(gè)字節(jié),比如 strncmp 中的n 就是要比較的最大字符數(shù),就相當(dāng)于一個(gè)限制機(jī)制了。
這里主要補(bǔ)充幾個(gè)比較實(shí)用的吧:
strstr
其實(shí)顧名思義,翻譯過(guò)來(lái)就是“字符串字符串”,其實(shí)作用就是在一個(gè)字符串里面找我的目標(biāo)字符串,不包含終止符 ‘\0’,返回值是該函數(shù)在 目標(biāo)字符串中第一次出現(xiàn)該字符串的位置。聲明為:
char *strstr(const char *haystack, const char *needle)
舉個(gè)栗子:
int main() { char a[] = "overwatch"; char b[] = "wa"; char* c = strstr(a, b); if (c != NULL) { printf("found it: %s\n", c); } else { printf("there was nothing\n"); } return 0; }
我們用最常規(guī)的代碼也可以模擬出 strstr 的功能,庫(kù)函數(shù)的實(shí)現(xiàn)方法也是類(lèi)似
#include<assert.h> char* strstr1(const char* a, const char* b) { assert(a && b); const char* c = NULL; const char* d = NULL; const char* str = a; if (*b == '\0') { return (char*)a; //處理查找語(yǔ)句為空語(yǔ)句 } while (*str) { c = str; d = b; while (*c && *d && (*c == *d))//防止相同元素為'\0' 循環(huán)繼續(xù)導(dǎo)致越界訪問(wèn) { *c++; *d++; } if (*d == '\0') { return (char*)str; } str++;//多次查找,匹配錯(cuò)誤會(huì)回到起點(diǎn)++再重新查找 } return NULL; }
要注意的是,該函數(shù)規(guī)定當(dāng)查找對(duì)象字符串為空 (\0) 時(shí),會(huì)返回目標(biāo)字符串的地址。
KMP算法
說(shuō)到了 strstr ,引申一下KMP算法,也就是字符串查找算法,稱(chēng)之為 Knuth-Morria-Pratt 算法。該算法相對(duì)于暴力算法有比較大的改進(jìn),主要是消除了主串指針的回溯,從而使算法效率有了某種程度的提高。KMP算法比我們的 strstr 效率要高,我們?nèi)蘸笤偌?xì)細(xì)講解
strtok
我們可以稱(chēng)之為字符串刀,作用就是分割字符串,strtok() 函數(shù)的聲明如下:
char *strtok(char *str, const char *delim)
str 為一組字符串,delim 為分隔符,也可以是個(gè)集合,分割結(jié)果變成第一個(gè)子字符串。
因?yàn)榻Y(jié)果被修改所以 strtok 對(duì)象一般為臨時(shí)拷貝的可修改內(nèi)容。舉個(gè)栗子:
int main() { char a[] = "overwatch"; char b[20] = { 0 }; char* ret = NULL; strcpy(b, a); //進(jìn)行臨時(shí)拷貝方便切割 char* p = "w";//指針類(lèi)型維護(hù)分隔符 ret = strtok(b, p); printf("%s\n", ret); return 0; }
若要進(jìn)一步分割,我們需要空指針進(jìn)行維護(hù),什么意思?
分割完一次,結(jié)尾就會(huì)變成 ‘ \0 ’,此時(shí)的 strtok 記憶能力已經(jīng)記住了 ‘ \0 ’的位置,這個(gè)記憶功能我們大致都能猜出是一個(gè)靜態(tài)變量,static 修飾一個(gè)局部變量時(shí)就可以做到這點(diǎn),就是我們只需要傳入一個(gè) null ,就可以自動(dòng)進(jìn)行分割,以此類(lèi)推:
strtok(b, p); ret = strtok(NULL,"t");
strerror
咱在使用庫(kù)函數(shù)時(shí),總會(huì)有調(diào)用失敗的時(shí)候,這時(shí)候都會(huì)有一個(gè)錯(cuò)誤碼被設(shè)置,這個(gè)錯(cuò)碼都會(huì)放進(jìn) errno 這個(gè)全局錯(cuò)誤碼里面,我們看到的錯(cuò)誤信息可能是一個(gè)莫名其妙的數(shù)字,而 strerror 就是將錯(cuò)誤碼翻譯成錯(cuò)誤信息,并返回一個(gè)指向錯(cuò)誤消息字符串的指針。strerror 生成的錯(cuò)誤字符串取決于開(kāi)發(fā)平臺(tái)和編譯器。
char *strerror(int errnum)
比如:
int main() { printf("%s\n", strerror(10)); printf("%s\n", strerror(20)); printf("%s\n", strerror(30)); return 0; }
結(jié)果分別是:無(wú)子進(jìn)程,非目錄元素,只讀文件系統(tǒng)
但其實(shí) strerror 并不是小題大做拿來(lái)查詢錯(cuò)誤的,是在文本上輸入輸出時(shí)方便我們得知打開(kāi)寫(xiě)入打開(kāi)失敗的原因的,當(dāng)我們嘗試打開(kāi)一個(gè)不存在的文件時(shí)就會(huì)報(bào)錯(cuò): No such file or directory
#include <errno.h> int main () { FILE *fp; fp = fopen("file.txt","search"); if( fp == NULL ) { printf("Error: %s\n", strerror(errno)); } return(0); }
因?yàn)槲覀円{(diào)用C語(yǔ)言給出的全局變量 errno,所以記得要引 <errno.h> 頭文件。
以上就是盤(pán)點(diǎn)分析C語(yǔ)言中少見(jiàn)卻強(qiáng)大的字符串函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言字符串函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Cocos2d-x UI開(kāi)發(fā)之CCControlButton控件類(lèi)實(shí)例
這篇文章主要介紹了Cocos2d-x UI開(kāi)發(fā)之CCControlButton控件類(lèi)實(shí)例,本文代碼中包含大量注釋來(lái)講解CCControlButton控件類(lèi)的使用,需要的朋友可以參考下2014-09-09C++指針運(yùn)算符(&和*)的實(shí)現(xiàn)
C++ 提供了兩種指針運(yùn)算符,一種是取地址運(yùn)算符 &,一種是間接尋址運(yùn)算符 *,本文就詳細(xì)的介紹一下這兩種運(yùn)算符的使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08C語(yǔ)言中fgetgrent()函數(shù)和fgetpwent()函數(shù)的用法對(duì)比
這篇文章主要介紹了C語(yǔ)言中fgetgrent()函數(shù)和fgetpwent()函數(shù)的用法對(duì)比,分別用于讀取組格式函數(shù)和讀取密碼格式,需要的朋友可以參考下2015-08-08C++深入刨析優(yōu)先級(jí)隊(duì)列priority_queue的使用
最近我學(xué)習(xí)了C++中的STL庫(kù)中的優(yōu)先級(jí)隊(duì)列(priority_queue)容器適配器,對(duì)于優(yōu)先級(jí)隊(duì)列,我們不僅要會(huì)使用常用的函數(shù)接口,我們還有明白這些接口在其底層是如何實(shí)現(xiàn)的2022-08-08C++中double浮點(diǎn)數(shù)精度丟失的深入分析
這篇文章主要給大家介紹了關(guān)于C++中double浮點(diǎn)數(shù)精度丟失的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01C語(yǔ)言中關(guān)于庫(kù)函數(shù) qsort 快排的用法
快速排序Qsort是所有學(xué)習(xí)算法和數(shù)據(jù)結(jié)構(gòu)最基礎(chǔ)的一個(gè)部分,也是考試題和面試的一個(gè)小重點(diǎn)。本片文章帶你了解Qsort的詳細(xì)用法規(guī)則2021-09-09一篇文章帶你了解C++多態(tài)的實(shí)現(xiàn)原理
這篇文章主要介紹了C++多態(tài)的實(shí)現(xiàn)機(jī)制理解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下,希望能給你帶來(lái)幫助2021-08-08