C++中string字符串分割函數(shù)split()的4種實(shí)現(xiàn)方法
如:
string str1 = "This is a test"; string str2 = "This-is-a-test"; string str2 = "This+is+a+test";
我們?nèi)绾螌⒁陨献址凑漳撤N分隔符( ,-,+),將其分割成四個(gè)子串,其值分別為 “This” “is” “a” “test” 。
一、使用stringstream流
這里我們只需要用到 istringstream(字符串輸入流) 構(gòu)造字符串流,然后從字符串流中按照一定的格式讀取數(shù)據(jù)即可。
通常我們使用 cin 從流中讀取數(shù)據(jù),而我們也可以使用 getline 讀取,而后者在讀取時(shí)可以選擇接受的數(shù)據(jù)格式,其函數(shù)原型如下:
// istream & getline(char* buf, int bufSize); // 讀到 \n 為止 istream & getline(char* buf, int bufSize, char delim); //讀到 delim 字符為止 // \n 或 delim 都不會(huì)被讀入 buf,但會(huì)被從文件輸入流緩沖區(qū)中取走
因此,我們可以按照此方式設(shè)計(jì)一個(gè)C++中的string split函數(shù)。
void Stringsplit(string str,const const char split) { istringstream iss(str); // 輸入流 string token; // 接收緩沖區(qū) while (getline(iss, token, split)) // 以split為分隔符 { cout << token << endl; // 輸出 } }
如此,我們就設(shè)計(jì)出了我們的Stringsplit() 函數(shù)。該函數(shù)有以下 2 種語法格式
void Stringsplit(string str,const const char split); // 默認(rèn)將傳入的字符串str以split為分隔符進(jìn)行分割,并將得到的子串打印在屏幕上,無返回值 void Stringsplit(string str, const const char split,vector<string>& rst); // 默認(rèn)將傳入的字符串str以split為分隔符進(jìn)行分割, 不會(huì)將子串打印在屏幕上,無返回值 // 分割的子串將會(huì)保存在rst數(shù)組中被帶出函數(shù)。
以上,我們簡單的設(shè)計(jì)了一種C++中的分割字符串的函數(shù),下面來看一個(gè)測(cè)試用例:
int main() { string str("This is a test"); Stringsplit(str, ' '); // 打印子串 vector<string> strList; string str2("This-is-a-test"); Stringsplit(str2, '-', strList); // 將子串存放到strList中 for (auto s : strList) cout << s << " "; cout << endl; return 0; }
# 輸出
This
is
a
test
This is a test
二、使用string類提供的find方法與substr方法
find函數(shù)原型:
size_type find( const basic_string& str, size_type pos = 0 ) const;
參數(shù):
str - 要搜索的 string , pos - 開始搜索的位置
返回值
找到的子串的首字符位置,或若找不到這種子串則為 npos 。
substr函數(shù)原型:
basic_string substr( size_type pos = 0, size_type count = npos ) const;
參數(shù):
pos - 要包含的首個(gè)字符的位置 ,count - 子串的長度
返回值
含子串 [pos, pos+count) 的 string 。
由以上兩個(gè)函數(shù)我們便可以設(shè)計(jì)出我們的Stringsplit()來。同時(shí),因?yàn)閒ind()函數(shù)查找的可以是字符串,因此我們的分隔符可以是單個(gè)的字符,也可以是一個(gè)字符串。
// 使用字符分割 void Stringsplit(const string& str, const char split, vector<string>& res) { if (str == "") return; //在字符串末尾也加入分隔符,方便截取最后一段 string strs = str + split; size_t pos = strs.find(split); // 若找不到內(nèi)容則字符串搜索函數(shù)返回 npos while (pos != strs.npos) { string temp = strs.substr(0, pos); res.push_back(temp); //去掉已分割的字符串,在剩下的字符串中進(jìn)行分割 strs = strs.substr(pos + 1, strs.size()); pos = strs.find(split); } } // 使用字符串分割 void Stringsplit(const string& str, const string& splits, vector<string>& res) { if (str == "") return; //在字符串末尾也加入分隔符,方便截取最后一段 string strs = str + splits; size_t pos = strs.find(splits); int step = splits.size(); // 若找不到內(nèi)容則字符串搜索函數(shù)返回 npos while (pos != strs.npos) { string temp = strs.substr(0, pos); res.push_back(temp); //去掉已分割的字符串,在剩下的字符串中進(jìn)行分割 strs = strs.substr(pos + step, strs.size()); pos = strs.find(splits); } }
下面是一個(gè)測(cè)試用例:
int main() { vector<string> strList; string str("This-is-a-test"); Stringsplit(str, '-', strList); for (auto s : strList) cout << s << " "; cout << endl; vector<string> strList2; string str2("This%20is%20a%20test"); Stringsplit(str2, "%20", strList2); for (auto s : strList2) cout << s << " "; cout << endl; return 0; }
# 輸出
This is a test
This is a test
三、使用C庫函數(shù)strtok
char* strtok( char* str, const char* delim );
參數(shù):
- str - 指向要記號(hào)化的空終止字節(jié)字符串的指針
- delim - 指向標(biāo)識(shí)分隔符的空終止字節(jié)字符串的指針
返回值:
指向下個(gè)記號(hào)起始的指針,或若無更多記號(hào)則為空指針。
需要注意的是,該函數(shù)使用一個(gè)全局的靜態(tài)變量來保存每次分割后的位置,因此在多線程中是不安全的,這里我們也可以選擇使用它的線程安全版本
char *strtok_r(char *str, const char *delim, char **saveptr); 。
void Stringsplit(const string& str, const string& split, vector<string>& res) { char* strc = new char[str.size() + 1]; strcpy(strc, str.c_str()); // 將str拷貝到 char類型的strc中 char* temp = strtok(strc, split.c_str()); while (temp != NULL) { res.push_back(string(temp)); temp = strtok(NULL, split.c_str()); // 下一個(gè)被分割的串 } delete[] strc; }
如此,我們的使用 strtok 版本的Stringsplit() 就完成了。不過,我們使用這種方法實(shí)現(xiàn)的字符串分割函數(shù)只能根據(jù)字符來分割,而我們傳入的參數(shù)是字符串類型,這樣可能會(huì)對(duì)函數(shù)的使用這造成誤導(dǎo)(注:參數(shù)傳入字符串用的雙引號(hào),傳入字符用的單引號(hào)),因此我們也可以使用下面的方法封裝一個(gè)參數(shù)是字符類型的函數(shù)。
void Stringsplit(const string& str, const char split, vector<string>& res) { Stringsplit(str, string(1,split), res); // 調(diào)用上一個(gè)版本的Stringsplit() }
下面給出一個(gè)測(cè)試用例,我們分別使用單/雙引號(hào)傳入分割的限定字符。
int main() { vector<string> strList; string str("This+is+a+test"); Stringsplit(str, '+', strList); for (auto s : strList) cout << s << " "; cout << endl; vector<string> strList2; string str2("This-is-a-test"); Stringsplit(str2, "-", strList2); for (auto s : strList2) cout << s << " "; cout << endl; return 0; }
四、使用regex_token_iterator(正則表達(dá)式)
正則表達(dá)式(regular expression)描述了一種字符串匹配的模式(pattern),可以用來檢查一個(gè)串是否含有某種子串、將匹配的子串替換或者從某個(gè)串中取出符合某個(gè)條件的子串等。
而在C++的正則中,把這種操作稱為Tokenize分詞(或者叫切割)。這種操作剛好可以滿足我們的需求,用模板類regex_token_iterator<>提供分詞迭代器,可以完成字符串的分割。
void Stringsplit(const string& str, const string& split, vector<string>& res) { //std::regex ws_re("\\s+"); // 正則表達(dá)式,匹配空格 std::regex reg(split); // 匹配split std::sregex_token_iterator pos(str.begin(), str.end(), reg, -1); decltype(pos) end; // 自動(dòng)推導(dǎo)類型 for (; pos != end; ++pos) { res.push_back(pos->str()); } }
測(cè)試用例:
int main() { // 單個(gè)字符分詞 vector<string> strList; string str("This is a test"); Stringsplit(str," ", strList); for (auto s : strList) cout << s << " "; cout << endl; // 使用字符串分詞 vector<string> strList2; string str2("ThisABCisABCaABCtest"); Stringsplit(str2, "ABC", strList2); for (auto s : strList2) cout << s << " "; cout << endl; }
# 輸出
This is a test
This is a test
總結(jié)
到此這篇關(guān)于C++中string字符串分割函數(shù)split()的4種實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)C++ 字符串分割函數(shù)split()內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VisualStudio2022 cmake配置opencv開發(fā)環(huán)境
本文主要介紹了VisualStudio2022 cmake配置opencv開發(fā)環(huán)境,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08C語言實(shí)例真題講解數(shù)據(jù)結(jié)構(gòu)中單向環(huán)形鏈表
鏈表可以說是一種最為基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)了,而單向鏈表更是基礎(chǔ)中的基礎(chǔ)。鏈表是由一組元素以特定的順序組合或鏈接在一起的,不同元素之間在邏輯上相鄰,但是在物理上并不一定相鄰。在維護(hù)一組數(shù)據(jù)集合時(shí),就可以使用鏈表,這一點(diǎn)和數(shù)組很相似2022-04-04C++線性表深度解析之動(dòng)態(tài)數(shù)組與單鏈表和棧及隊(duì)列的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)動(dòng)態(tài)數(shù)組、單鏈表、棧、隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05C++找出字符串中出現(xiàn)最多的字符和次數(shù),時(shí)間復(fù)雜度小于O(n^2)
今天小編就為大家分享一篇關(guān)于C++找出字符串中出現(xiàn)最多的字符和次數(shù),時(shí)間復(fù)雜度小于O(n^2),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12