您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)c++中如何實(shí)現(xiàn)字符串分割,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
C++ 中經(jīng)常需要對(duì)字符串按照分隔符進(jìn)行分割以獲得子串序列,子串的順序與其在原字符串中出現(xiàn)的順序一致。一般有兩種需求場景:
(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; }
測試如下:
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 << " "; } // 邊界測試 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; }
測試如下:
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 << " "; } // 邊界測試 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í)刻記住代碼的簡潔與優(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; }
代碼主要說明:
(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; }
關(guān)于c++中如何實(shí)現(xiàn)字符串分割就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。