C++ <cstring>字串處理函式
阿新 • • 發佈:2021-02-07
字串處理函式包括幾大類可以滿足對char*字串大部分操作,需要包括標頭檔案<cstring>或者<string.h>,選擇幾個仔細研究一下:
#include <iostream> #include <cstring> #include <assert.h> using namespace std; int strLen(const char *s) { if (NULL==s) throw "Invalid argument"; //assert(s!=NULL); //或者用<assert.h>庫函式assert() int i; //for(;*s!='\0';++s) i++; while(*s++!='\0') i++; //兩種迴圈都可以 return i; } char *strCpy(char *dest,const char *src) { assert(NULL!=dest); assert(NULL!=src); //兩個條件可以用&&合併,但不知錯在哪個條件 while (*src!='\0'){ *dest=*src; dest++; src++; } *dest=*src; //此時等價於*dest='\0'; //while ((*dest++ = *src++)!='\0'); //可合併為一行 return dest; } char *strCpy1(char *dest,const char *src) { char *p=dest; cout<<"begin copying:"<<endl; while (*src!='\0'){ cout<<*src<<endl; *dest++=*src++; } *dest='\0'; cout<<"end!"<<endl; return p; } int main() { int len=0; char aChar; const char *str = "hello"; // 宣告和賦值 //const 不能省,否則有警告提示,但能通過編譯 cout<<str<<endl<<endl; cout<<"測試:sizeof()、strlen()"<<endl; const char msg1[] = "hello,world!hello,world!"; len = strlen(msg1); //<cstring>庫函式 cout<<sizeof(msg1)<<"|"<<len<<endl; //sizeof 與 strlen 的區別,此時sizeof的值是陣列的大小 len = strLen(msg1); //有大寫字母的為自定義函式,以下同 cout<<sizeof(msg1)<<"|"<<len<<endl<<endl; //定義和賦值分開進行 const char *msg; msg = "hello,world!hello,world!"; len = strlen(msg); //<cstring>庫函式 cout<<sizeof(msg)<<"|"<<len<<endl; //此時sizeof的值是指標的大小:64位系統是8;32位系統是4 len = strLen(msg); //有大寫字母的為自定義函式,以下同 cout<<sizeof(msg)<<"|"<<len<<endl<<endl; //結論:sizeof不適合計算字串長度 cout<<"測試:移動指標"<<endl; cout<<msg<<endl; *msg++;*msg++; //向後移動指標,對比顯示的內容 aChar=*msg; cout<<&msg<<endl; //取地址 cout<<*msg<<endl; cout<<aChar<<endl<<endl; *msg--;*msg--; //向前移動指標,對比顯示的內容 aChar=*msg; cout<<&msg<<endl; cout<<*msg<<endl; cout<<aChar<<endl; cout<<*(msg+0)<<"="<<msg[0]<<endl; cout<<*(msg+1)<<"="<<msg[1]<<endl; cout<<*(msg+2)<<"="<<msg[2]<<endl; cout<<*(msg+3)<<"="<<msg[3]<<endl; cout<<*(msg+4)<<"="<<msg[4]<<endl; cout<<*(msg+5)<<"="<<msg[5]<<endl; cout<<"["<<*(msg+strlen(msg))<<"]<-NULL/\'0\'"<<endl; cout<<msg<<endl<<endl; cout<<"測試:strcpy()"<<endl; for (int i=0;i<12;i++) *msg++; //源字串的長度必須不大於目標字串長度 cout<<msg<<endl; char dest[21]="ABCDEFGHIJKLMNOPQRST"; //20個字母+'\0' cout<<"["<<dest<<"]:"<<sizeof(dest)<<"|"<<strlen(dest)<<endl; strcpy(dest,msg); //sizeof值未變,strlen值變小 cout<<"["<<dest<<"]:"<<sizeof(dest)<<"|"<<strlen(dest)<<endl; strCpy(dest,msg); cout<<"["<<dest<<"]:"<<sizeof(dest)<<"|"<<strlen(dest)<<endl; strCpy1(dest,msg); cout<<"["<<dest<<"]:"<<sizeof(dest)<<"|"<<strlen(dest)<<endl<<endl; cout<<"測試:strncpy()"<<endl; char dest1[15]="abcdefghijklmn"; strncpy(dest1,msg,strlen(msg)); cout<<dest1<<endl; char dest2[10]={0}; //設一個最大長度可為10的空串 cout<<dest2<<"|"<<endl; strncpy(dest2,msg,strlen(dest2)); //沒複製到內容 cout<<dest2<<"|"<<endl; strncpy(dest2,msg,sizeof(dest2)); //只能複製到10個字元 cout<<dest2<<endl; strncpy(dest2,msg,strlen(msg)); //可以得到12個字元,但後2個越界 cout<<dest2<<"|"<<sizeof(dest2)<<"|"<<strlen(dest2)<<endl; //結論:dest必須有足夠的空間來容納source的字元長度+'\0';相比strcpy更容易溢位出錯棄用,建議用strncpy return 0; }
測試結果:
hello 測試:sizeof()、strlen() 25|24 25|24 8|24 8|24 測試:移動指標 hello,world!hello,world! 0x22fe08 l l 0x22fe08 h h h=h e=e l=l l=l o=o ,=, []<-NULL/'\0' hello,world!hello,world! 測試:strcpy() hello,world! [ABCDEFGHIJKLMNOPQRST]:21|20 [hello,world!]:21|12 [hello,world!]:21|12 begin copying: h e l l o , w o r l d ! end! [hello,world!]:21|12 測試:strncpy() hello,world!mn | | hello,worl hello,world!|10|12 -------------------------------- Process exited after 1.042 seconds with return value 0 請按任意鍵繼續. . .
待續......
附錄:
複製函式
char *strcpy(char *s1, const char *s2);
char *strncpy(char *s1, const char *s2, size_t n);
void *memcpy(void *s1, const void *s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);
strcpy,strcpy,memcpy,memmove
的第一個引數都為複製的dest,而第二個引數都為複製的源source。strcpy
將一個以空字元結尾的字串s2
複製給s1
strncpy
跟strcpy
一樣,只不過它限制了複製的字元的個數,最多複製n
個字元。如果n
過小,那麼strncpy
就不能複製末尾的空字元,如果n
比源字串長度大,strncpy
在遇到空字元後會不斷向目的字串追加空字元,直到達到n
個。同時strcpy
和strncpy
在源和目的重疊時也會有問題的。memcpy
函式從位元組陣列s2
向s1
複製n
個位元組。如果源和目的有重疊,那麼使用memcpy
會有問題。memmove
函式可以在源和目的重合時正常處理,在其他方面與memcpy
相同。memcpy
、memmove
和strncpy
函式可用於包括字元在內的任何記憶體塊,而strcpy
函式只適合字串,它會持續複製字元,直到遇到源字元中的空字元為止。
拼接函式
char *strcat(char *s1, const char *s2);
char *strncat(char *s1, const char *s2, size_t n);
strcat
函式將它的第二個引數s2
追加到第一個引數s1
的末尾。s1
和s2
必須都是以空字元結尾的字串。strcat
會用s2的第一個字元覆蓋s1
的空字元,並在拼接字串的後邊新增空字元。strncat
與strcat
功能相同,只是限制了從s2
中取出拼接到s1
的字元個數。
比較函式
int memcmp(const void *s1, const void *s2, size_t n);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
int stricmp(const char *s1, const char *s2);
int strcoll(const char *s1, const char *s2);
size_t strxfrm(char *s1, const char *s2, size_t n);
memcmp,
strcmp,
strncmp,stricmp
函式以指向字元(位元組)陣列的指標為引數,逐個比較兩個字元(位元組)陣列的每個字元。根據比較結束時第一個字元(位元組)陣列中的字元(位元組)是小於、等於或大於第二個字元(位元組)陣列中的字元(位元組)而返回-1,0或1。三個函式的主要區別是在於何時結束比較,如果第一個不同的字元在memcmp
和strncmp
的範圍n
之內,則三者相同。否則,strcmp
在遇到空字元停止比較,memcmp
不關心空字元,在比較的位元組數達到n
個時停止比較,strncmp
結合了上述兩個函式的特點,在達到n
個字元或遇到空字元時停止比較。stricmp與strcmp功能相似,只不過以
大小寫不敏感方式比較。strcroll
和strcmp
功能相似,只不過比較結果依賴於本地化設定(根據不同的地點比較結果不同)。然而strcoll
函式的速度不是很快,當這是個問題或者希望在改變本地設定而不影響比較結果的話,可以使用strxfrm
函式,strxfrm
將第二個引數進行本地化轉換,並將轉換結果放在第一個引數,引數n
限制了轉換的字元個數。
搜尋函式
void *memchr(const void *s, int c, size_t n);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
char *strpbrk(const char *s1, const char *s2);
size_t strcspn(const char *s1, const char *s2);
size_t strspn(const char *s1, const char *s2);
char *strstr(const char *s1, const char *s2);
char *strtok(char *s1, const char *s2);
strchr
函式在字串s
中搜索字元c
,它會返回一個指向s
中第一個字元c
的指標,如果沒找到,則返回空指標。當遇到空字元時停止搜尋。memchr
函式在搜尋了n
個字元後停止搜尋,返回第一個字元c
的指標,若未找到,則返回空指標。strrchr
與strchr
類似,只是從字串s
的空字元開始,反向搜尋字元c
。如果找到,則返回反向第一個字元c
的地址,若未找到返回空指標。strpbrk
函式從s1
中尋找與s2
中任意一個字元匹配的第一個字元,並返回指向它的指標。若找不到,則返回空。strspn
函式從字串s1
中搜索字符集s2
,並返回字元組中第一個不屬於給定字符集中的字元的下標,而strcspn
函式返回第一個屬於給定字符集中的字元的下標。strstr
函式在字串s1
中搜索字串s2
,返回找到的第一處匹配子串的指標,如果找不到,則返回空。strtok
函式在s1
中搜索,查詢一個非空字元序列(稱作記號),這個序列不包括s2
中指定的字元。將找到的記號後面的那個字元替換為一個空字元標記該記號的末尾,然後返回一個指向該記號的首字元的指標。使用strtok(NULL,s2)
就可以繼續上一次的strtok
函式呼叫,直到其返回一個空指標為止。
其他函式
void *memset(void *s, int c, size_t n);
size_t strlen(const char *s);
char *strerror(int errnum);
memset
函式將一個字元的多個副本儲存到指定的記憶體區域。strlen
返回字串的長度,不包括字串末尾的空字元。strerror
當輸入儲存在errno
的錯誤碼時,會返回一個指向描述這種錯誤的字串的指標。