聲明:html
水平有限,若有翻譯不當,歡迎探討、批評與指正。ios
帖子內容:算法
C++ 切分字符串的最優雅的方式是什麼?咱們假定字符串中每一個單詞分隔符是空格。(備註:我對C的字符串函數或者那種字符處理/存取方式不是很感興趣。所以,請優先選擇優雅而不是效率)函數
我如今能想到的最好的方式是:學習
#include <iostream> #include <sstream> #include <string> using namespace std; int main() { string s("Somewhere down the road"); istringstream iss(s); do { string sub; iss >> sub; cout << "Substring: " << sub << endl; } while (iss); return 0; }
另外一種方式去萃取輸入字符串的分隔符,使用標準庫函數很容易實現。下面是使用 STL 的設計方案(健壯而且優雅):spa
#include <iostream> #include <string> #include <sstream> #include <algorithm> #include <iterator> int main() { using namespace std; string sentence = "Something in the way she moves..."; istringstream iss(sentence); copy(istream_iterator<string>(iss), istream_iterator<string>(), ostream_iterator<string>(cout, "\n")); }
若是想要把分割後的字符串放到一個容器中,而不是控制檯的話,使用相同的泛型算法便可。翻譯
vector tokens;
copy(istream_iterator(iss),
istream_iterator(),
back_inserter >(tokens));[/c]
評:這種方案只能分割空格,沒有伸縮性。設計
使用 boost 庫:code
std::vector strs; boost::split(strs, "string to split", boost::is_any_of("\t "));
我打賭這個要比使用 stringstream 快的多。而且這是一個泛型模板方法,它能夠用來分割任意類型的字符串(wchar,etc. or UTF-8),使用任意的分隔符。具體請看文檔。htm
評:不是每一個人都用 boost 的。
把 delim 做爲做爲分隔符,第一個函數把結果放到一個已經存在構造好了的 vector 中,第二個函數返回一個新的 vector。
std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while(std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } std::vector split(const std::string &s, char delim) { std::vector elems; return split(s, delim, elems); }
注意:這種方法不能跳過空的符號,好比下面有四個數據項,其中的一個是空的。
std::vector x = split("one:two::three", ':');
template < class ContainerT > void tokenize(const std::string& str, ContainerT& tokens, const std::string& delimiters = " ", const bool trimEmpty = false) { std::string::size_type pos, lastPos = 0; while(true) { pos = str.find_first_of(delimiters, lastPos); if(pos == std::string::npos) { pos = str.length(); if(pos != lastPos || !trimEmpty) tokens.push_back(ContainerT::value_type(str.data()+lastPos, (ContainerT::value_type::size_type)pos-lastPos )); break; } else { if(pos != lastPos || !trimEmpty) tokens.push_back(ContainerT::value_type(str.data()+lastPos, (ContainerT::value_type::size_type)pos-lastPos )); } lastPos = pos + 1; } };
#include <vector> #include <string> #include <sstream> using namespace std; int main() { string str("Split me by whitespaces"); string buf; // Have a buffer string stringstream ss(str); // Insert the string into a stream vector<string> tokens; // Create vector to hold our words while (ss >> buf) tokens.push_back(buf); }
筆者注: