c++字符串分割的方法
C++ 中經(jīng)常需要對(duì)字符串按照分隔符進(jìn)行分割以獲得子串序列,子串的順序與其在原字符串中出現(xiàn)的順序一致。一般有兩種需求場(chǎng)景:
(1)給定一個(gè)分隔符(單個(gè)字符或子串)分割字符串;
(2)給定一個(gè)或多個(gè)分隔符(單個(gè)字符),分割字符串。
當(dāng)給定的分隔符不在原字符串中,則原字符串不被分割,返回單個(gè)元素為原字符串的 vector。
注意,本文實(shí)現(xiàn)時(shí),如果被分割后的子串為空串,則不計(jì)入最終的子串序列。比如原字符串是"a,b",分隔符為",",那么分割后的子串序列為 [“a”, “b”],而不是 [“a”, “”, “b”]。
1.單個(gè)分隔符(單個(gè)字符或子串)分割字符串
#include <iostream> #include <vector> #include <string> using namespace std; //@brief: 指定單個(gè)分隔符(單個(gè)字符或子串)分割字符串 //@param: src 原字符串;delimiter 分隔符,單個(gè)字符或子串 vector<string> splitStr(const string& src, const string& delimiter) { std::vector<string> vetStr; // 入?yún)z查 // 1.原字符串為空或等于分隔符,返回空 vector if (src == "" || src == delimiter) { return vetStr; } // 2.分隔符為空返回單個(gè)元素為原字符串的 vector if (delimiter == "") { vetStr.push_back(src); return vetStr; } string::size_type startPos = 0; auto index = src.find(delimiter); while (index != string::npos) { auto str = src.substr(startPos, index - startPos); if (str != "") { vetStr.push_back(str); } startPos = index + delimiter.length(); index = src.find(delimiter, startPos); } // 取最后一個(gè)子串 auto str = src.substr(startPos); if (str != "") { vetStr.push_back(str); } return vetStr; }
測(cè)試如下:
int main(int argc, char* argv[]) { string str = "I,love,China"; // 正常分割 auto vetStr = splitStr(str, ","); cout << "vetStr.size() = " << vetStr.size() << endl; for (auto v : vetStr) { cout << v << " "; } // 邊界測(cè)試 vetStr = splitStr(str, "I,"); cout << endl << "vetStr.size() = " << vetStr.size() << endl; for (auto v : vetStr) { cout << v << " "; } // 不包含分隔符 vetStr = splitStr(str, "what"); cout << endl << "vetStr.size() = " << vetStr.size() << endl; for (auto v : vetStr) { cout << v << " "; } return 0; }
輸出結(jié)果:
vetStr.size() = 3
I love China
vetStr.size() = 1
love,China
vetStr.size() = 1
I,love,China
2.單個(gè)或多個(gè)分隔符(單個(gè)字符)分割字符串
實(shí)現(xiàn)和單個(gè)分隔符(單個(gè)字符或子串)分割字符串基本一致,關(guān)鍵地方是將獲取分隔符下標(biāo)的函數(shù)由 std::string::find(…) 改為 std::string::find_first_of(…)。二者的區(qū)別如下:
std::string::find(...)
將分隔符看作一個(gè)整體在原字符串中查找并返回匹配的下標(biāo),比如 string("I love China").find("love") 返回 2。
std::string::find_first_of(...)
在字符串中搜索分隔符中任意一個(gè)字符出現(xiàn)的第一個(gè)位置。與 std::string::find(...) 的區(qū)別是不需要整個(gè)分隔符匹配,只需要分隔符中的單個(gè)字符匹配即可。
具體實(shí)現(xiàn)如下:
//@brief: 指定單個(gè)或多個(gè)分隔符(單個(gè)字符)分割字符串 //@param: src 原字符串;delimiter 單個(gè)或多個(gè)分隔符(單個(gè)字符) vector<string> splitStr(const string& src, const string& delimiter) { std::vector<string> vtStr; // 入?yún)z查 // 1.原字符串為空返回空 vector if (src == "") { return vtStr; } // 2.分隔符為空返回單個(gè)元素為原字符串的 vector if (delimiter == "") { vtStr.push_back(src); return vtStr; } string::size_type startPos = 0; auto index = src.find_first_of(delimiter); while (index != string::npos) { auto str = src.substr(startPos, index - startPos); if (str != "") { vtStr.push_back(str); } startPos = index + 1; index = src.find_first_of(delimiter, startPos); } // 取最后一個(gè)子串 auto str = src.substr(startPos); if (str != "") { vtStr.push_back(str); } return vtStr; }
測(cè)試如下:
int main(int argc, char* argv[]) { string str = "I,love,China"; // 正常分割。按照 h 與逗號(hào)分割 auto vetStr = splitStr(str, "h,"); cout << "vetStr.size() = " << vetStr.size() << endl; for (auto v : vetStr) { cout << v << " "; } // 邊界測(cè)試 vetStr = splitStr(str, "Ia"); cout << endl << "vetStr.size() = " << vetStr.size() << endl; for (auto v : vetStr) { cout << v << " "; } // 不包含分隔符 vetStr = splitStr(str, "_:"); cout << endl << "vetStr.size() = " << vetStr.size() << endl; for (auto v : vetStr) { cout << v << " "; } return 0; }
輸出結(jié)果:
vetStr.size() = 4
I love C ina
vetStr.size() = 1
,love,Chin
vetStr.size() = 1
I,love,China
3.反面實(shí)例
下面是我情急之下實(shí)現(xiàn)的單個(gè)或多個(gè)分隔符(單個(gè)字符)分割字符串的函數(shù),有點(diǎn)“臟亂差”,作為反面教材,希望能夠幫助大家時(shí)刻記住代碼的簡(jiǎn)潔與優(yōu)雅是多么可貴,大家可以對(duì)比感受一下。另外,適當(dāng)?shù)拇a注釋,對(duì)提高代碼的可讀性會(huì)有很大幫助。
臟亂差版本一:
//qsort函數(shù)需要的比較函數(shù),按照升序排序 int comp(const void*a,const void*b) { return *(int*)a-*(int*)b; } //@brief: 指定單個(gè)或多個(gè)分隔符(單個(gè)字符)分割字符串 //@param: src 原字符串;delimiter 分隔符集合 vector<string> splitStr(const string& src,const string& delimiter) { vector<string> strRes; int maxSubstrNum=src.size(); int* pos=new int[maxSubstrNum]; memset(pos,0,maxSubstrNum*sizeof(int)); int j=0; for(size_t i=0;i<delimiter.size();++i) { string::size_type index=src.find(delimiter[i]); while(index!=string::npos) { pos[j++]=index; index=src.find(delimiter[i],index+1); } } //排序 qsort(pos,j,sizeof(int),comp); //取出第一個(gè)子串 string substrFir=src.substr(0,pos[0]); if(substrFir!="") strRes.push_back(substrFir); //取出中間j-1個(gè)子串 for(int i=0;i<j-1;++i) { string substr=src.substr(pos[i]+1,pos[i+1]-pos[i]-1); if(substr!="") { strRes.push_back(substr); } } //取出最后一個(gè)子串 string substrLast=src.substr(pos[j-1]+1,src.size()-pos[j-1]-1); if(substrLast!="") { strRes.push_back(substrLast); } delete[] pos; return strRes; }
代碼主要說(shuō)明:
(1)利用 find() 和 substr() 函數(shù)實(shí)現(xiàn)分割功能;
(2)代碼中,需要對(duì)分割符出現(xiàn)的下標(biāo)進(jìn)行排序,這樣才能順序取出子串。
臟亂差版本二:
//@brief: 指定單個(gè)或多個(gè)分隔符(單個(gè)字符)分割字符串 //@param: src 原字符串;delimiter 分隔符集合 std::vector<std::string> splitStr(const std::string &sStr, const std::string &sSep) { std::vector<std::string> vt; std::string::size_type pos = 0; std::string::size_type pos1 = 0; int pos_tmp = -1; while(true) { std::string s; std::string s1; pos1 = sStr.find_first_of(sSep, pos); if(pos1 == std::string::npos) { if(pos + 1 <= sStr.length()) { s = sStr.substr(-1 != pos_tmp ? pos_tmp : pos); s1 = ""; } } else if(pos1 == pos && (pos1 + 1 == sStr.length())) { s = ""; s1 = ""; } else { s = sStr.substr(-1 != pos_tmp ? pos_tmp : pos, pos1 - (-1 != pos_tmp ? pos_tmp : pos)); s1 = sStr.substr(pos1 + 1); if (-1 == pos_tmp) { pos_tmp = pos; } pos = pos1; } if(!s.empty()) { vt.push_back(s); } pos_tmp = -1; if(pos1 == std::string::npos) { break; } pos++; } return vt; }
以上就是c++字符串分割的方法的詳細(xì)內(nèi)容,更多關(guān)于C++ 字符串分割的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Linux vmstat命令實(shí)戰(zhàn)詳細(xì)解析
這個(gè)命令是我查看Linux/Unix最喜愛的命令,一個(gè)是Linux/Unix都支持,二是相比top,我可以看到整個(gè)機(jī)器的CPU,內(nèi)存,IO的使用情況,而不是單單看到各個(gè)進(jìn)程的CPU使用率和內(nèi)存使用率(使用場(chǎng)景不一樣)2013-09-09C語(yǔ)言實(shí)現(xiàn)掃雷游戲詳細(xì)流程
windows自帶的游戲《掃雷》是陪伴了無(wú)數(shù)人的經(jīng)典游戲,本文將利用C語(yǔ)言實(shí)現(xiàn)這一經(jīng)典的游戲,文中的示例代碼講解詳細(xì),感興趣的可以學(xué)習(xí)一下2022-05-05Qt6.0+vs2019環(huán)境配置的實(shí)現(xiàn)教程
這篇文章主要介紹了Qt6.0+vs2019環(huán)境配置的實(shí)現(xiàn)教程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03C語(yǔ)言超細(xì)致講解循環(huán)語(yǔ)句
我們說(shuō)到當(dāng)滿足特定條件時(shí),就會(huì)執(zhí)行if語(yǔ)句或者switch語(yǔ)句后面的語(yǔ)句,否則不執(zhí)行,但是這只能執(zhí)行一次,在日常生活中,有些事情是需要重復(fù)去做的,C語(yǔ)句就為此引入了循環(huán)語(yǔ)句。所以今天繼續(xù)為大家分享C語(yǔ)言循環(huán)家族2022-05-05C/C++細(xì)數(shù)宏與函數(shù)有那些區(qū)別
在C程序中,可以用宏代碼提高執(zhí)行效率。宏代碼本身不是函數(shù),但使用起來(lái)象函數(shù)。預(yù)處理器用復(fù)制宏代碼的方式代替函數(shù)調(diào)用,省去了參數(shù)壓棧、生成匯編語(yǔ)言的CALL調(diào)用、返回參數(shù)、執(zhí)行return等過程,從而提高了速度2022-10-10C語(yǔ)言運(yùn)算符深入探究?jī)?yōu)先級(jí)與結(jié)合性及種類
C語(yǔ)言運(yùn)算符號(hào)指的是運(yùn)算符號(hào)。C語(yǔ)言中的符號(hào)分為10類:算術(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位操作運(yùn)算符、賦值運(yùn)算符、條件運(yùn)算符、逗號(hào)運(yùn)算符、指針運(yùn)算符、求字節(jié)數(shù)運(yùn)算符和特殊運(yùn)算符2022-05-05