迭代string的最优雅的方法

什么是迭代string的最优雅的方式? string可以被认为是由空白分隔的单词组成的。

请注意,我对Cstring函数或那种字符操作/访问不感兴趣。 另外,在你的回答中,请优先考虑效率。

我现在最好的解决scheme是:

#include <iostream> #include <sstream> #include <string> using namespace std; int main() { string s = "Somewhere down the road"; istringstream iss(s); do { string subs; iss >> subs; cout << "Substring: " << subs << endl; } while (iss); } 

对于什么是值得的,这里是另一种从inputstring中提取令牌的方法,仅依赖于标准的库设施。 这是STLdevise背后的力量和优雅的一个例子。

 #include <iostream> #include <string> #include <sstream> #include <algorithm> #include <iterator> int main() { using namespace std; string sentence = "And I feel fine..."; istringstream iss(sentence); copy(istream_iterator<string>(iss), istream_iterator<string>(), ostream_iterator<string>(cout, "\n")); } 

而不是将提取的标记复制到输出stream,可以使用相同的通用copyalgorithm将它们插入到容器中。

 vector<string> tokens; copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens)); 

…或直接创buildvector

 vector<string> tokens{istream_iterator<string>{iss}, istream_iterator<string>{}}; 

我用这个来分隔string的分隔符。 第一个将结果放入一个预先构造的向量中,第二个返回一个新的向量。

 #include <string> #include <sstream> #include <vector> #include <iterator> template<typename Out> void split(const std::string &s, char delim, Out result) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { *(result++) = item; } } std::vector<std::string> split(const std::string &s, char delim) { std::vector<std::string> elems; split(s, delim, std::back_inserter(elems)); return elems; } 

编辑:

请注意,此解决scheme不会跳过空标记,因此以下内容将查找4个项目,其中一个为空:

 std::vector<std::string> x = split("one:two::three", ':'); 

使用Boost的一个可能的解决scheme可能是:

 #include <boost/algorithm/string.hpp> std::vector<std::string> strs; boost::split(strs, "string to split", boost::is_any_of("\t ")); 

这种方法可能比stringstream方法更快。 由于这是一个通用的模板函数,因此可以使用各种分隔符来分割其他types的string(wchar等或UTF-8)。

详细信息请参阅文档 。

 #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); } 

对于那些为了代码大小而牺牲一切效率并将“高效”看作优雅types的人来说,下面应该是一个甜蜜的地方(我认为模板容器类是一个非常优雅的补充):

 template < class ContainerT > void tokenize(const std::string& str, ContainerT& tokens, const std::string& delimiters = " ", bool trimEmpty = false) { std::string::size_type pos, lastPos = 0, length = str.length(); using value_type = typename ContainerT::value_type; using size_type = typename ContainerT::size_type; while(lastPos < length + 1) { pos = str.find_first_of(delimiters, lastPos); if(pos == std::string::npos) { pos = length; } if(pos != lastPos || !trimEmpty) tokens.push_back(value_type(str.data()+lastPos, (size_type)pos-lastPos )); lastPos = pos + 1; } } 

我通常select使用std::vector<std::string>types作为我的第二个参数( ContainerT )…但是list<>vector<>要快,因为不需要直接访问,甚至可以创build你自己的string类,并使用像std::list<subString>其中subString不会做任何副本令人难以置信的速度增加。

它比这个页面上最快的标记化速度快了一倍,比其他一些快了近5倍。 此外,使用完美的参数types,您可以消除所有string和列表副本以提高速度。

此外,它不会执行结果的(非常低效的)返回,而是将令牌作为参考传递,因此如果您愿意,还允许您使用多个调用来构build令牌。

最后,它允许您指定是否通过最后一个可选参数修剪结果中的空记号。

所有它需要的是std::string …其余的是可选的。 它不使用stream或boost库,但是足够灵活,能够自然地接受这些外部types。

这是另一个解决scheme。 它结构紧凑,合理高效:

 std::vector<std::string> split(const std::string &text, char sep) { std::vector<std::string> tokens; std::size_t start = 0, end = 0; while ((end = text.find(sep, start)) != std::string::npos) { tokens.push_back(text.substr(start, end - start)); start = end + 1; } tokens.push_back(text.substr(start)); return tokens; } 

它可以很容易地模板化处理string分隔符,宽string等

请注意,将""结果分割为单个空string并分割"," (即.sep)会产生两个空string。

它也可以很容易地扩展到跳过空的标记:

 std::vector<std::string> split(const std::string &text, char sep) { std::vector<std::string> tokens; std::size_t start = 0, end = 0; while ((end = text.find(sep, start)) != std::string::npos) { if (end != start) { tokens.push_back(text.substr(start, end - start)); } start = end + 1; } if (end != start) { tokens.push_back(text.substr(start)); } return tokens; } 

如果希望在跳过空令牌的情况下在多个分隔符处分割string,则可以使用以下版本:

 std::vector<std::string> split(const std::string& text, const std::string& delims) { std::vector<std::string> tokens; std::size_t start = text.find_first_not_of(delims), end = 0; while((end = text.find_first_of(delims, start)) != std::string::npos) { tokens.push_back(text.substr(start, end - start)); start = text.find_first_not_of(delims, end); } if(start != std::string::npos) tokens.push_back(text.substr(start)); return tokens; } 
 string line = "a line of text to iterate through"; string word; istringstream iss(line, istringstream::in); while( iss >> word ) { ... } 

这是我最喜欢的方式来遍历一个string。 你可以做你想要的每个字。

这是类似于堆栈溢出问题如何在C ++中标记string?

 #include <iostream> #include <string> #include <boost/tokenizer.hpp> using namespace std; using namespace boost; int main(int argc, char** argv) { string text = "token test\tstring"; char_separator<char> sep(" \t"); tokenizer<char_separator<char>> tokens(text, sep); for (const string& t : tokens) { cout << t << "." << endl; } } 

我喜欢以下内容,因为它将结果放入向量中,支持将string作为分隔符,并控制保留空值。 但是,那看起来不太好。

 #include <ostream> #include <string> #include <vector> #include <algorithm> #include <iterator> using namespace std; vector<string> split(const string& s, const string& delim, const bool keep_empty = true) { vector<string> result; if (delim.empty()) { result.push_back(s); return result; } string::const_iterator substart = s.begin(), subend; while (true) { subend = search(substart, s.end(), delim.begin(), delim.end()); string temp(substart, subend); if (keep_empty || !temp.empty()) { result.push_back(temp); } if (subend == s.end()) { break; } substart = subend + delim.size(); } return result; } int main() { const vector<string> words = split("So close no matter how far", " "); copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n")); } 

当然,Boost有一个split() ,就像这样。 而且,如果使用“空白”,则确实意味着任何types的空白,使用Boost与is_any_of()的分割效果很好。

STL没有这样的方法。

但是,您可以使用string.c_str()成员使用C的strtok函数,也可以编写自己的。 这里是一个我快速谷歌search后发现的代码示例(“STL string split”):

 void Tokenize(const string& str, vector<string>& tokens, const string& delimiters = " ") { // Skip delimiters at beginning. string::size_type lastPos = str.find_first_not_of(delimiters, 0); // Find first "non-delimiter". string::size_type pos = str.find_first_of(delimiters, lastPos); while (string::npos != pos || string::npos != lastPos) { // Found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); // Skip delimiters. Note the "not_of" lastPos = str.find_first_not_of(delimiters, pos); // Find next "non-delimiter" pos = str.find_first_of(delimiters, lastPos); } } 

取自: http : //oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

如果您对代码示例有疑问,请留下评论,我将解释。

只是因为它没有实现一个称为迭代器或重载的typedef,<<运算符并不意味着它是错误的代码。 我经常使用C函数。 例如,printf和scanf都比cin和cout(显着)要快,fopen语法对二进制types更友好,而且他们也倾向于产生更小的EXE。

不要在这个“优雅的performance”交易上卖掉。

这是一个拆分函数:

  • 是通用的
  • 使用标准的C ++(不提升)
  • 接受多个分隔符
  • 忽略空的标记(可以很容易地被改变)

     template<typename T> vector<T> split(const T & str, const T & delimiters) { vector<T> v; typename T::size_type start = 0; auto pos = str.find_first_of(delimiters, start); while(pos != T::npos) { if(pos != start) // ignore empty tokens v.emplace_back(str, start, pos - start); start = pos + 1; pos = str.find_first_of(delimiters, start); } if(start < str.length()) // ignore trailing delimiter v.emplace_back(str, start, str.length() - start); // add what's left of the string return v; } 

用法示例:

  vector<string> v = split<string>("Hello, there; World", ";,"); vector<wstring> v = split<wstring>(L"Hello, there; World", L";,"); 

我有一个2线解决这个问题:

 char sep = ' '; std::string s="1 This is an example"; for(size_t p=0, q=0; p!=s.npos; p=q) std::cout << s.substr(p+(p!=0), (q=s.find(sep, p+1))-p-(p!=0)) << std::endl; 

然后,而不是打印,你可以把它放在一个vector。

又一个灵活而快捷的方式

 template<typename Operator> void tokenize(Operator& op, const char* input, const char* delimiters) { const char* s = input; const char* e = s; while (*e != 0) { e = s; while (*e != 0 && strchr(delimiters, *e) == 0) ++e; if (e - s > 0) { op(s, e - s); } s = e + 1; } } 

使用它的string的vector(编辑:由于有人指出不inheritanceSTL类… hrmf;)):

 template<class ContainerType> class Appender { public: Appender(ContainerType& container) : container_(container) {;} void operator() (const char* s, unsigned length) { container_.push_back(std::string(s,length)); } private: ContainerType& container_; }; std::vector<std::string> strVector; Appender v(strVector); tokenize(v, "A number of words to be tokenized", " \t"); 

而已! 这只是使用标记器的一种方式,就像如何计算单词一样:

 class WordCounter { public: WordCounter() : noOfWords(0) {} void operator() (const char*, unsigned) { ++noOfWords; } unsigned noOfWords; }; WordCounter wc; tokenize(wc, "A number of words to be counted", " \t"); ASSERT( wc.noOfWords == 7 ); 

受想象力的限制;)

如果你喜欢使用boost,但是想使用整个string作为分隔符(而不是像以前提出的大多数解决scheme那样使用单个字符),那么可以使用boost_split_iterator

示例代码包括方便的模板:

 #include <iostream> #include <vector> #include <boost/algorithm/string.hpp> template<typename _OutputIterator> inline void split( const std::string& str, const std::string& delim, _OutputIterator result) { using namespace boost::algorithm; typedef split_iterator<std::string::const_iterator> It; for(It iter=make_split_iterator(str, first_finder(delim, is_equal())); iter!=It(); ++iter) { *(result++) = boost::copy_range<std::string>(*iter); } } int main(int argc, char* argv[]) { using namespace std; vector<string> splitted; split("HelloFOOworldFOO!", "FOO", back_inserter(splitted)); // or directly to console, for example split("HelloFOOworldFOO!", "FOO", ostream_iterator<string>(cout, "\n")); return 0; } 

这是一个简单的解决scheme,只使用标准的正则expression式库

 #include <regex> #include <string> #include <vector> std::vector<string> Tokenize( const string str, const std::regex regex ) { using namespace std; std::vector<string> result; sregex_token_iterator it( str.begin(), str.end(), regex, -1 ); sregex_token_iterator reg_end; for ( ; it != reg_end; ++it ) { if ( !it->str().empty() ) //token could be empty:check result.emplace_back( it->str() ); } return result; } 

正则expression式参数允许检查多个参数(空格,逗号等)

我通常只检查分隔空格和逗号,所以我也有这个默认的function:

 std::vector<string> TokenizeDefault( const string str ) { using namespace std; regex re( "[\\s,]+" ); return Tokenize( str, re ); } 

"[\\s,]+"检查空格( \\s )和逗号( , )。

注意,如果你想分割wstring而不是string

  • 将所有std::regex更改为std::wregex
  • 将所有sregex_token_iterator更改为wsregex_token_iterator

请注意,根据您的编译器,您可能还希望通过引用来获取string参数。

使用stringstream,因为你有完美的工作,并做到你想要的。 如果你只是寻找不同的方式做事,你可以使用find / find_first_of和substring。

 #include <iostream> #include <string> int main() { std::string s("Somewhere down the road"); std::string::size_type prev_pos = 0, pos = 0; while( (pos = s.find(' ', pos)) != std::string::npos ) { std::string substring( s.substr(prev_pos, pos-prev_pos) ); std::cout << substring << '\n'; prev_pos = ++pos; } std::string substring( s.substr(prev_pos, pos-prev_pos) ); // Last word std::cout << substring << '\n'; } 

有一个名为strtok的函数。

 #include<string> using namespace std; vector<string> split(char* str,const char* delim) { char* saveptr; char* token = strtok_r(str,delim,&saveptr); vector<string> result; while(token != NULL) { result.push_back(token); token = strtok_r(NULL,delim,&saveptr); } return result; } 

下面是一个只使用标准正则expression式库的正则expression式解决scheme。 (我有点生疏,所以可能有一些语法错误,但这至less是一般的想法)

 #include <regex.h> #include <string.h> #include <vector.h> using namespace std; vector<string> split(string s){ regex r ("\\w+"); //regex matches whole words, (greedy, so no fragment words) regex_iterator<string::iterator> rit ( s.begin(), s.end(), r ); regex_iterator<string::iterator> rend; //iterators to iterate thru words vector<string> result<regex_iterator>(rit, rend); return result; //iterates through the matches to fill the vector } 

到目前为止,我使用了Boost中的那个,但是我需要的东西不依赖于它,所以我来到这个:

 static void Split(std::vector<std::string>& lst, const std::string& input, const std::string& separators, bool remove_empty = true) { std::ostringstream word; for (size_t n = 0; n < input.size(); ++n) { if (std::string::npos == separators.find(input[n])) word << input[n]; else { if (!word.str().empty() || !remove_empty) lst.push_back(word.str()); word.str(""); } } if (!word.str().empty() || !remove_empty) lst.push_back(word.str()); } 

好的一点是在separators可以传递多个字符。

我已经使用strtok来滚动自己,并使用boost来分割一个string。 我发现的最好的方法是C ++string工具包库 。 它非常灵活和快速。

 #include <iostream> #include <vector> #include <string> #include <strtk.hpp> const char *whitespace = " \t\r\n\f"; const char *whitespace_and_punctuation = " \t\r\n\f;,="; int main() { { // normal parsing of a string into a vector of strings std::string s("Somewhere down the road"); std::vector<std::string> result; if( strtk::parse( s, whitespace, result ) ) { for(size_t i = 0; i < result.size(); ++i ) std::cout << result[i] << std::endl; } } { // parsing a string into a vector of floats with other separators // besides spaces std::string s("3.0, 3.14; 4.0"); std::vector<float> values; if( strtk::parse( s, whitespace_and_punctuation, values ) ) { for(size_t i = 0; i < values.size(); ++i ) std::cout << values[i] << std::endl; } } { // parsing a string into specific variables std::string s("angle = 45; radius = 9.9"); std::string w1, w2; float v1, v2; if( strtk::parse( s, whitespace_and_punctuation, w1, v1, w2, v2) ) { std::cout << "word " << w1 << ", value " << v1 << std::endl; std::cout << "word " << w2 << ", value " << v2 << std::endl; } } return 0; } 

该工具箱比这个简单的例子显示了更多的灵活性,但是它将stringparsing成有用的元素的效用是不可思议的。

如果您需要使用非空格符号parsingstring,那么stringstream可以很方便:

 string s = "Name:JAck; Spouse:Susan; ..."; string dummy, name, spouse; istringstream iss(s); getline(iss, dummy, ':'); getline(iss, name, ';'); getline(iss, dummy, ':'); getline(iss, spouse, ';') 

短而优雅

 #include <vector> #include <string> using namespace std; vector<string> split(string data, string token) { vector<string> output; size_t pos = string::npos; // size_t to avoid improbable overflow do { pos = data.find(token); output.push_back(data.substr(0, pos)); if (string::npos != pos) data = data.substr(pos + token.size()); } while (string::npos != pos); return output; } 

可以使用任何string作为分隔符,也可以使用二进制数据(std :: string支持二进制数据,包括空值)

使用:

 auto a = split("this!!is!!!example!string", "!!"); 

输出:

 this is !example!string 

我做这个是因为我需要一个简单的方法来拆分string和基于c的string…希望别人也可以find它有用。 也不依赖于令牌,你可以使用字段作为分隔符,这是我需要的另一个关键。

我相信有进一步的改进,可以进一步提高其优雅,请尽一切办法

StringSplitter.hpp:

 #include <vector> #include <iostream> #include <string.h> using namespace std; class StringSplit { private: void copy_fragment(char*, char*, char*); void copy_fragment(char*, char*, char); bool match_fragment(char*, char*, int); int untilnextdelim(char*, char); int untilnextdelim(char*, char*); void assimilate(char*, char); void assimilate(char*, char*); bool string_contains(char*, char*); long calc_string_size(char*); void copy_string(char*, char*); public: vector<char*> split_cstr(char); vector<char*> split_cstr(char*); vector<string> split_string(char); vector<string> split_string(char*); char* String; bool do_string; bool keep_empty; vector<char*> Container; vector<string> ContainerS; StringSplit(char * in) { String = in; } StringSplit(string in) { size_t len = calc_string_size((char*)in.c_str()); String = new char[len + 1]; memset(String, 0, len + 1); copy_string(String, (char*)in.c_str()); do_string = true; } ~StringSplit() { for (int i = 0; i < Container.size(); i++) { if (Container[i] != NULL) { delete[] Container[i]; } } if (do_string) { delete[] String; } } }; 

StringSplitter.cpp:

 #include <string.h> #include <iostream> #include <vector> #include "StringSplit.hpp" using namespace std; void StringSplit::assimilate(char*src, char delim) { int until = untilnextdelim(src, delim); if (until > 0) { char * temp = new char[until + 1]; memset(temp, 0, until + 1); copy_fragment(temp, src, delim); if (keep_empty || *temp != 0) { if (!do_string) { Container.push_back(temp); } else { string x = temp; ContainerS.push_back(x); } } else { delete[] temp; } } } void StringSplit::assimilate(char*src, char* delim) { int until = untilnextdelim(src, delim); if (until > 0) { char * temp = new char[until + 1]; memset(temp, 0, until + 1); copy_fragment(temp, src, delim); if (keep_empty || *temp != 0) { if (!do_string) { Container.push_back(temp); } else { string x = temp; ContainerS.push_back(x); } } else { delete[] temp; } } } long StringSplit::calc_string_size(char* _in) { long i = 0; while (*_in++) { i++; } return i; } bool StringSplit::string_contains(char* haystack, char* needle) { size_t len = calc_string_size(needle); size_t lenh = calc_string_size(haystack); while (lenh--) { if (match_fragment(haystack + lenh, needle, len)) { return true; } } return false; } bool StringSplit::match_fragment(char* _src, char* cmp, int len) { while (len--) { if (*(_src + len) != *(cmp + len)) { return false; } } return true; } int StringSplit::untilnextdelim(char* _in, char delim) { size_t len = calc_string_size(_in); if (*_in == delim) { _in += 1; return len - 1; } int c = 0; while (*(_in + c) != delim && c < len) { c++; } return c; } int StringSplit::untilnextdelim(char* _in, char* delim) { int s = calc_string_size(delim); int c = 1 + s; if (!string_contains(_in, delim)) { return calc_string_size(_in); } else if (match_fragment(_in, delim, s)) { _in += s; return calc_string_size(_in); } while (!match_fragment(_in + c, delim, s)) { c++; } return c; } void StringSplit::copy_fragment(char* dest, char* src, char delim) { if (*src == delim) { src++; } int c = 0; while (*(src + c) != delim && *(src + c)) { *(dest + c) = *(src + c); c++; } *(dest + c) = 0; } void StringSplit::copy_string(char* dest, char* src) { int i = 0; while (*(src + i)) { *(dest + i) = *(src + i); i++; } } void StringSplit::copy_fragment(char* dest, char* src, char* delim) { size_t len = calc_string_size(delim); size_t lens = calc_string_size(src); if (match_fragment(src, delim, len)) { src += len; lens -= len; } int c = 0; while (!match_fragment(src + c, delim, len) && (c < lens)) { *(dest + c) = *(src + c); c++; } *(dest + c) = 0; } vector<char*> StringSplit::split_cstr(char Delimiter) { int i = 0; while (*String) { if (*String != Delimiter && i == 0) { assimilate(String, Delimiter); } if (*String == Delimiter) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return Container; } vector<string> StringSplit::split_string(char Delimiter) { do_string = true; int i = 0; while (*String) { if (*String != Delimiter && i == 0) { assimilate(String, Delimiter); } if (*String == Delimiter) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return ContainerS; } vector<char*> StringSplit::split_cstr(char* Delimiter) { int i = 0; size_t LenDelim = calc_string_size(Delimiter); while(*String) { if (!match_fragment(String, Delimiter, LenDelim) && i == 0) { assimilate(String, Delimiter); } if (match_fragment(String, Delimiter, LenDelim)) { assimilate(String,Delimiter); } i++; String++; } String -= i; delete[] String; return Container; } vector<string> StringSplit::split_string(char* Delimiter) { do_string = true; int i = 0; size_t LenDelim = calc_string_size(Delimiter); while (*String) { if (!match_fragment(String, Delimiter, LenDelim) && i == 0) { assimilate(String, Delimiter); } if (match_fragment(String, Delimiter, LenDelim)) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return ContainerS; } 

例子:

 int main(int argc, char*argv[]) { StringSplit ss = "This:CUT:is:CUT:an:CUT:example:CUT:cstring"; vector<char*> Split = ss.split_cstr(":CUT:"); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } 

会输出:

这个

一个

cstring

 int main(int argc, char*argv[]) { StringSplit ss = "This:is:an:example:cstring"; vector<char*> Split = ss.split_cstr(':'); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } int main(int argc, char*argv[]) { string mystring = "This[SPLIT]is[SPLIT]an[SPLIT]example[SPLIT]string"; StringSplit ss = mystring; vector<string> Split = ss.split_string("[SPLIT]"); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } int main(int argc, char*argv[]) { string mystring = "This|is|an|example|string"; StringSplit ss = mystring; vector<string> Split = ss.split_string('|'); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } 

To keep empty entries (by default empties will be excluded):

 StringSplit ss = mystring; ss.keep_empty = true; vector<string> Split = ss.split_string(":DELIM:"); 

The goal was to make it similar to C#'s Split() method where splitting a string is as easy as:

 String[] Split = "Hey:cut:what's:cut:your:cut:name?".Split(new[]{":cut:"}, StringSplitOptions.None); foreach(String X in Split) { Console.Write(X); } 

I hope someone else can find this as useful as I do.

What about this:

 #include <string> #include <vector> using namespace std; vector<string> split(string str, const char delim) { vector<string> v; string tmp; for(string::const_iterator i; i = str.begin(); i <= str.end(); ++i) { if(*i != delim && i != str.end()) { tmp += *i; } else { v.push_back(tmp); tmp = ""; } } return v; } 

Here's another way of doing it..

 void split_string(string text,vector<string>& words) { int i=0; char ch; string word; while(ch=text[i++]) { if (isspace(ch)) { if (!word.empty()) { words.push_back(word); } word = ""; } else { word += ch; } } if (!word.empty()) { words.push_back(word); } } 

I like to use the boost/regex methods for this task since they provide maximum flexibility for specifying the splitting criteria.

 #include <iostream> #include <string> #include <boost/regex.hpp> int main() { std::string line("A:::line::to:split"); const boost::regex re(":+"); // one or more colons // -1 means find inverse matches aka split boost::sregex_token_iterator tokens(line.begin(),line.end(),re,-1); boost::sregex_token_iterator end; for (; tokens != end; ++tokens) std::cout << *tokens << std::endl; } 

Recently I had to split a camel-cased word into subwords. There are no delimiters, just upper characters.

 #include <string> #include <list> #include <locale> // std::isupper template<class String> const std::list<String> split_camel_case_string(const String &s) { std::list<String> R; String w; for (String::const_iterator i = s.begin(); i < s.end(); ++i) { { if (std::isupper(*i)) { if (w.length()) { R.push_back(w); w.clear(); } } w += *i; } if (w.length()) R.push_back(w); return R; } 

For example, this splits "AQueryTrades" into "A", "Query" and "Trades". The function works with narrow and wide strings. Because it respects the current locale it splits "RaumfahrtÜberwachungsVerordnung" into "Raumfahrt", "Überwachungs" and "Verordnung".

Note std::upper should be really passed as function template argument. Then the more generalized from of this function can split at delimiters like "," , ";" or " " too.

The code below uses strtok() to split a string into tokens and stores the tokens in a vector.

 #include <iostream> #include <algorithm> #include <vector> #include <string> using namespace std; char one_line_string[] = "hello hi how are you nice weather we are having ok then bye"; char seps[] = " ,\t\n"; char *token; int main() { vector<string> vec_String_Lines; token = strtok( one_line_string, seps ); cout << "Extracting and storing data in a vector..\n\n\n"; while( token != NULL ) { vec_String_Lines.push_back(token); token = strtok( NULL, seps ); } cout << "Displaying end result in vector line storage..\n\n"; for ( int i = 0; i < vec_String_Lines.size(); ++i) cout << vec_String_Lines[i] << "\n"; cout << "\n\n\n"; return 0; } 
 #include<iostream> #include<string> #include<sstream> #include<vector> using namespace std; vector<string> split(const string &s, char delim) { vector<string> elems; stringstream ss(s); string item; while (getline(ss, item, delim)) { elems.push_back(item); } return elems; } int main() { vector<string> x = split("thi is an sample test",' '); unsigned int i; for(i=0;i<x.size();i++) cout<<i<<":"<<x[i]<<endl; return 0; } 

I use this simpleton because we got our String class "special" (ie not standard):

 void splitString(const String &s, const String &delim, std::vector<String> &result) { const int l = delim.length(); int f = 0; int i = s.indexOf(delim,f); while (i>=0) { String token( if > 0 ? s.substring(f,if) : ""); result.push_back(token); f=i+l; i = s.indexOf(delim,f); } String token = s.substring(f); result.push_back(token); }