c++字符串分割的方法
C++ 中經(jīng)常需要對字符串按照分隔符進行分割以獲得子串序列,子串的順序與其在原字符串中出現(xiàn)的順序一致。一般有兩種需求場景:
(1)給定一個分隔符(單個字符或子串)分割字符串;
(2)給定一個或多個分隔符(單個字符),分割字符串。
當給定的分隔符不在原字符串中,則原字符串不被分割,返回單個元素為原字符串的 vector。
注意,本文實現(xiàn)時,如果被分割后的子串為空串,則不計入最終的子串序列。比如原字符串是"a,b",分隔符為",",那么分割后的子串序列為 [“a”, “b”],而不是 [“a”, “”, “b”]。
1.單個分隔符(單個字符或子串)分割字符串
#include <iostream> #include <vector> #include <string> using namespace std; //@brief: 指定單個分隔符(單個字符或子串)分割字符串 //@param: src 原字符串;delimiter 分隔符,單個字符或子串 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.分隔符為空返回單個元素為原字符串的 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); } // 取最后一個子串 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.單個或多個分隔符(單個字符)分割字符串
實現(xiàn)和單個分隔符(單個字符或子串)分割字符串基本一致,關鍵地方是將獲取分隔符下標的函數(shù)由 std::string::find(…) 改為 std::string::find_first_of(…)。二者的區(qū)別如下:
std::string::find(...)
將分隔符看作一個整體在原字符串中查找并返回匹配的下標,比如 string("I love China").find("love") 返回 2。
std::string::find_first_of(...)
在字符串中搜索分隔符中任意一個字符出現(xiàn)的第一個位置。與 std::string::find(...) 的區(qū)別是不需要整個分隔符匹配,只需要分隔符中的單個字符匹配即可。
具體實現(xiàn)如下:
//@brief: 指定單個或多個分隔符(單個字符)分割字符串 //@param: src 原字符串;delimiter 單個或多個分隔符(單個字符) vector<string> splitStr(const string& src, const string& delimiter) { std::vector<string> vtStr; // 入?yún)z查 // 1.原字符串為空返回空 vector if (src == "") { return vtStr; } // 2.分隔符為空返回單個元素為原字符串的 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); } // 取最后一個子串 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 與逗號分割 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.反面實例
下面是我情急之下實現(xiàn)的單個或多個分隔符(單個字符)分割字符串的函數(shù),有點“臟亂差”,作為反面教材,希望能夠幫助大家時刻記住代碼的簡潔與優(yōu)雅是多么可貴,大家可以對比感受一下。另外,適當?shù)拇a注釋,對提高代碼的可讀性會有很大幫助。
臟亂差版本一:
//qsort函數(shù)需要的比較函數(shù),按照升序排序 int comp(const void*a,const void*b) { return *(int*)a-*(int*)b; } //@brief: 指定單個或多個分隔符(單個字符)分割字符串 //@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); //取出第一個子串 string substrFir=src.substr(0,pos[0]); if(substrFir!="") strRes.push_back(substrFir); //取出中間j-1個子串 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); } } //取出最后一個子串 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ù)實現(xiàn)分割功能;
(2)代碼中,需要對分割符出現(xiàn)的下標進行排序,這樣才能順序取出子串。
臟亂差版本二:
//@brief: 指定單個或多個分隔符(單個字符)分割字符串 //@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++字符串分割的方法的詳細內(nèi)容,更多關于C++ 字符串分割的資料請關注腳本之家其它相關文章!
相關文章
Qt6.0+vs2019環(huán)境配置的實現(xiàn)教程
這篇文章主要介紹了Qt6.0+vs2019環(huán)境配置的實現(xiàn)教程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03C/C++細數(shù)宏與函數(shù)有那些區(qū)別
在C程序中,可以用宏代碼提高執(zhí)行效率。宏代碼本身不是函數(shù),但使用起來象函數(shù)。預處理器用復制宏代碼的方式代替函數(shù)調(diào)用,省去了參數(shù)壓棧、生成匯編語言的CALL調(diào)用、返回參數(shù)、執(zhí)行return等過程,從而提高了速度2022-10-10C語言運算符深入探究優(yōu)先級與結(jié)合性及種類
C語言運算符號指的是運算符號。C語言中的符號分為10類:算術運算符、關系運算符、邏輯運算符、位操作運算符、賦值運算符、條件運算符、逗號運算符、指針運算符、求字節(jié)數(shù)運算符和特殊運算符2022-05-05