C語(yǔ)言切割多層字符串(strtok_r strtok使用方法)
1. strtok介紹
眾所周知,strtok可以根據(jù)用戶所提供的分割符(同時(shí)分隔符也可以為復(fù)數(shù)比如“,?!保?BR>將一段字符串分割直到遇到"\0".
比如,分隔符=“,” 字符串=“Fred,John,Ann”
通過(guò)strtok 就可以把3個(gè)字符串 “Fred” “John” “Ann”提取出來(lái)。
上面的C代碼為
int in=0;
char buffer[]="Fred,John,Ann"
char *p[3];
char *buff = buffer;
while((p[in]=strtok(buf,","))!=NULL) {
i++;
buf=NULL; }
如上代碼,第一次執(zhí)行strtok需要以目標(biāo)字符串的地址為第一參數(shù)(buf=buffer),之后strtok需要以NULL為第一參數(shù) (buf=NULL)。指針列p[],則儲(chǔ)存了分割后的結(jié)果,p[0]="John",p[1]="John",p[2]="Ann",而buf就變 成 Fred\0John\0Ann\0。
2. strtok的弱點(diǎn)
讓我們更改一下我們的計(jì)劃:我們有一段字符串 "Fred male 25,John male 62,Anna female 16" 我們希望把這個(gè)字符串整理輸入到一個(gè)struct,
struct person {
char [25] name ;
char [6] sex;
char [4] age;
}
要做到這個(gè),其中一個(gè)方法就是先提取一段被“,”分割的字符串,然后再將其以“ ”(空格)分割。
比如: 截取 "Fred male 25" 然后分割成 "Fred" "male" "25"
以下我寫了個(gè)小程序去表現(xiàn)這個(gè)過(guò)程:
#include<stdio.h>
#include<string.h>
#define INFO_MAX_SZ 255
int main()
{
int in=0;
char buffer[INFO_MAX_SZ]="Fred male 25,John male 62,Anna female 16";
char *p[20];
char *buf=buffer;
while((p[in]=strtok(buf,","))!=NULL) {
buf=p[in];
while((p[in]=strtok(buf," "))!=NULL) {
in++;
buf=NULL;
}
p[in++]="***"; //表現(xiàn)分割
buf=NULL; }
printf("Here we have %d strings\n",in);
for (int j=0; j<in; j++)
printf(">%s<\n",p[j]);
return 0;
}
這個(gè)程序輸出為:
Here we have 4 strings
>Fred<
>male<
>25<
>***<
這只是一小段的數(shù)據(jù),并不是我們需要的。但這是為什么呢? 這是因?yàn)閟trtok使用一個(gè)static(靜態(tài))指針來(lái)操作數(shù)據(jù),讓我來(lái)分析一下以上代碼的運(yùn)行過(guò)程:
紅色為strtok的內(nèi)置指針指向的位置,藍(lán)色為strtok對(duì)字符串的修改
1."Fred male 25,John male 62,Anna female 16" //外循環(huán)
2."Fred male 25\0John male 62,Anna female 16" //進(jìn)入內(nèi)循環(huán)
3."Fred\0male 25\0John male 62,Anna female 16"
4."Fred\0male\025\0John male 62,Anna female 16"
5 "Fred\0male\025\0John male 62,Anna female 16" //內(nèi)循環(huán)遇到"\0"回到外循環(huán)
6 "Fred\0male\025\0John male 62,Anna female 16" //外循環(huán)遇到"\0"運(yùn)行結(jié)束。
3. 使用strtok_r
在這種情況我們應(yīng)該使用strtok_r, strtok reentrant.
char *strtok_r(char *s, const char *delim, char **ptrptr);
相對(duì)strtok我們需要為strtok提供一個(gè)指針來(lái)操作,而不是像strtok使用配套的指針。
代碼:
#include<stdio.h>
#include<string.h>
#define INFO_MAX_SZ 255
int main()
{
int in=0;
char buffer[INFO_MAX_SZ]="Fred male 25,John male 62,Anna female 16";
char *p[20];
char *buf=buffer;
char *outer_ptr=NULL;
char *inner_ptr=NULL;
while((p[in]=strtok_r(buf,",",&outer_ptr))!=NULL) {
buf=p[in];
while((p[in]=strtok_r(buf," ",&inner_ptr))!=NULL) {
in++;
buf=NULL;
}
p[in++]="***";
buf=NULL; }
printf("Here we have %d strings\n",in);
for (int j=0; j<in; j++)
printf(">%s<\n",p[j]);
return 0;
}
這一次的輸出為:
Here we have 12 strings
>Fred<
>male<
>25<
>***<
>John<
>male<
>62<
>***<
>Anna<
>female<
>16<
>***<
讓我來(lái)分析一下以上代碼的運(yùn)行過(guò)程:
紅色為strtok_r的outer_ptr指向的位置,
紫色為strtok_r的inner_ptr指向的位置,
藍(lán)色為strtok對(duì)字符串的修改
1. "Fred male 25,John male 62,Anna female 16" //外循環(huán)
2. "Fred male 25\0John male 62,Anna female 16"http://進(jìn)入內(nèi)循環(huán)
3. "Fred\0male 25\0John male 62,Anna female 16"
4 "Fred\0male\025\0John male 62,Anna female 16"
5 "Fred\0male\025\0John male 62,Anna female 16" //內(nèi)循環(huán)遇到"\0"回到外循環(huán)
6 "Fred\0male\025\0John male 62\0Anna female 16"http://進(jìn)入內(nèi)循環(huán)
原來(lái), 該函數(shù)修改了原串.
所以,當(dāng)使用char *test2 = "feng,ke,wei"作為第一個(gè)參數(shù)傳入時(shí),在位置①處, 由于test2指向的內(nèi)容保存在文字常量區(qū),該區(qū)的內(nèi)容是不能修改的,所以會(huì)出現(xiàn)內(nèi)存錯(cuò)誤. 而char test1[] = "feng,ke,wei" 中的test1指向的內(nèi)容是保存在棧區(qū)的,所以可以修改
- C語(yǔ)言strlen,strcpy,strcmp,strcat,strstr字符串操作函數(shù)實(shí)現(xiàn)
- C語(yǔ)言模擬實(shí)現(xiàn)strstr函數(shù)的示例代碼
- 關(guān)于C語(yǔ)言函數(shù)strstr()的分析以及實(shí)現(xiàn)
- C語(yǔ)言錯(cuò)誤信息報(bào)告strerror函數(shù)和perror函數(shù)詳解
- 帶你用C語(yǔ)言實(shí)現(xiàn)strtok和字符串分割函數(shù)
- c語(yǔ)言字符串函數(shù)strstr,strtok,strerror的使用和實(shí)現(xiàn)
相關(guān)文章
C語(yǔ)言結(jié)構(gòu)體(struct)的詳細(xì)講解
C語(yǔ)言中,結(jié)構(gòu)體類型屬于一種構(gòu)造類型(其他的構(gòu)造類型還有:數(shù)組類型,聯(lián)合類型),下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言結(jié)構(gòu)體(struct)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03C++中fstream,ifstream及ofstream用法淺析
這篇文章主要介紹了C++中fstream,ifstream及ofstream用法,適合C++初學(xué)者學(xué)習(xí)文件流的操作,需要的朋友可以參考下2014-08-08詳解C++中的對(duì)象指針與對(duì)象數(shù)組
這篇文章主要介紹了詳解C++中的對(duì)象指針與對(duì)象數(shù)組,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09C++實(shí)現(xiàn)LeetCode(2.兩個(gè)數(shù)字相加)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(兩個(gè)數(shù)字相加),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07通過(guò)c語(yǔ)言調(diào)用系統(tǒng)curl動(dòng)態(tài)庫(kù)的示例詳解
這篇文章中我們將通過(guò)一個(gè)簡(jiǎn)單的示例來(lái)講解如何在Ubuntu系統(tǒng)中通過(guò)C語(yǔ)言調(diào)用動(dòng)態(tài)庫(kù)(共享庫(kù))的方法,我們將使用libcurl庫(kù),這是一個(gè)基于客戶端的URL傳輸庫(kù),廣泛用于各種程序和應(yīng)用中以訪問(wèn)網(wǎng)頁(yè)和服務(wù)器數(shù)據(jù),需要的朋友可以參考下2024-03-03