如何遍历字符串中的单词?
我正在尝试遍历字符串中的单词。
可以假定字符串由空格分隔的单词组成。
请注意,我对C字符串函数或那种字符操作/访问不感兴趣。 另外,在回答问题时,请优先考虑优雅而不是效率。
我目前拥有的最佳解决方案是:
#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);
}
有没有更优雅的方法可以做到这一点?
#1楼
我之所以这样做,是因为我需要一种简单的方法来分割字符串和基于C的字符串……希望其他人也能找到它的用处。 而且它不依赖标记,您可以将字段用作定界符,这是我需要的另一个关键。
我敢肯定,可以做些改进,以进一步提高其优雅度,请务必采取一切措施
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;
}
将输出:
这个
是
一个
例
弦
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;
}
要保留空条目(默认情况下,将不包括空):
StringSplit ss = mystring;
ss.keep_empty = true;
vector<string> Split = ss.split_string(":DELIM:");
目的是使其类似于C#的Split()方法,在该方法中,拆分字符串非常简单:
String[] Split = "Hey:cut:what's:cut:your:cut:name?".Split(new[]{":cut:"}, StringSplitOptions.None);foreach(String X in Split)
{Console.Write(X);
}
我希望其他人能像我一样有用。
#2楼
我对此问题有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;
然后,您可以将其放入向量中,而不是进行打印。
#3楼
这是仅使用标准正则表达式库的正则表达式解决方案。 (我有点生疏,所以可能会有一些语法错误,但这至少是一般性想法)
#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 wordsvector<string> result<regex_iterator>(rit, rend);return result; //iterates through the matches to fill the vector
}
#4楼
对于那些不愿意为了代码大小而牺牲所有效率并且将“效率”视为一种优雅的人来说,以下内容应该是一个不错的选择(我认为模板容器类是非常出色的添加):
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;}
}
我通常选择使用std::vector<std::string>
类型作为我的第二个参数( ContainerT
)...但是对于不需要直接访问的情况, list<>
比vector<>
快得多,甚至可以创建您自己的字符串类,并使用类似std::list<subString>
类的东西,其中subString
不执行任何复制以实现惊人的速度提高。
它是此页面上最快的标记化速度的两倍以上,几乎是其他一些标记速度的5倍。 同样,使用理想的参数类型,您可以消除所有字符串和列表副本,从而进一步提高速度。
此外,它不会返回结果(效率极低),而是将令牌作为参考传递,因此,如果您愿意,还可以使用多个调用来构建令牌。
最后,它允许您指定是否通过最后一个可选参数从结果中修剪空标记。
它需要的只是std::string
...其余都是可选的。 它不使用流或boost库,但足够灵活以能够自然地接受其中一些外部类型。
#5楼
获取助推 ! :-)
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <vector>using namespace std;
using namespace boost;int main(int argc, char**argv) {typedef vector < string > list_type;list_type list;string line;line = "Somewhere down the road";split(list, line, is_any_of(" "));for(int i = 0; i < list.size(); i++){cout << list[i] << endl;}return 0;
}
这个例子给出了输出-
Somewhere
down
the
road
#6楼
#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;
}
#7楼
这是另一种方法。
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);}
}
#8楼
我使用strtok滚动了自己的文件,并使用boost来拆分字符串。 我发现的最佳方法是C ++ String Toolkit库 。 它非常灵活和快速。
#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 stringsstd::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 spacesstd::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 variablesstd::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;
}
该工具包比此简单示例显示的灵活性要大得多,但是它在将字符串解析为有用元素方面的实用性令人难以置信。
#9楼
这是仅使用标准正则表达式库的简单解决方案
#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:checkresult.emplace_back( it->str() );}return result;
}
regex参数允许检查多个参数(空格,逗号等)。
我通常只检查空格和逗号,所以我也有这个默认功能:
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
注意,根据您的编译器,您可能还想通过引用获取字符串参数。
#10楼
STL还没有可用的这种方法。
但是,您可以通过使用std::string::c_str()
成员来使用C的strtok()
函数,也可以编写自己的函数。 这是经过快速Google搜索( “ STL字符串拆分” )后发现的代码示例:
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
都比std::cin
和std::cout
都快(明显), fopen
语法对二进制类型友好得多,并且它们也倾向于生成更小的EXE。
不要因为这项“绩效上的优雅”交易而被出售。
#11楼
这是我最喜欢的遍历字符串的方式。 您可以按单词做任何您想做的事情。
string line = "a line of text to iterate through";
string word;istringstream iss(line, istringstream::in);while( iss >> word )
{// Do something on `word` here...
}
#12楼
使用std::stringstream
可以正常工作,并且完全按照您的要求进行。 如果您只是在寻找不同的处理方式,则可以使用std::find()
/ std::find_first_of()
和std::string::substr()
。
这是一个例子:
#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 wordstd::cout << substring << '\n';return 0;
}
#13楼
我喜欢以下内容,因为它将结果放入向量中,支持字符串作为delim并控制保留空值。 但是,那时看起来还不怎么样。
#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()
,部分工作原理是这样的。 而且,如果使用“空白”,则实际上意味着任何类型的空白,将Boost的split与is_any_of()
效果很好。
#14楼
这类似于堆栈溢出问题, 如何在C ++中标记字符串? 。
#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;}
}
#15楼
我用它用定界符分割字符串。 第一个将结果放入预先构造的向量中,第二个返回一个新向量。
#include <string>
#include <sstream>
#include <vector>
#include <iterator>template <typename Out>
void split(const std::string &s, char delim, Out result) {std::istringstream iss(s);std::string item;while (std::getline(iss, 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;
}
请注意,此解决方案不会跳过空令牌,因此以下内容将找到4个项目,其中之一为空:
std::vector<std::string> x = split("one:two::three", ':');
#16楼
使用Boost的可能解决方案可能是:
#include <boost/algorithm/string.hpp>
std::vector<std::string> strs;
boost::split(strs, "string to split", boost::is_any_of("\t "));
这种方法甚至可能比stringstream
方法更快。 而且由于这是一个通用的模板函数,因此可以使用各种分隔符来分割其他类型的字符串(wchar等或UTF-8)。
有关详细信息,请参见文档 。
#17楼
值得的是,这是另一种仅依靠标准库工具从输入字符串中提取令牌的方法。 这是STL设计背后的力量和优雅的典范。
#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"));
}
与其将提取的令牌复制到输出流,还可以使用相同的通用copy
算法将其插入到容器中。
vector<string> tokens;
copy(istream_iterator<string>(iss),istream_iterator<string>(),back_inserter(tokens));
...或直接创建vector
:
vector<string> tokens{istream_iterator<string>{iss},istream_iterator<string>{}};
#18楼
另一种灵活而快速的方法
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;}
}
将其与字符串向量一起使用(编辑:由于有人指出不要继承STL类... 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 );
受想象力限制;)
#19楼
有一个名为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;
}
#20楼
简短而优雅
#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 overflowdo{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;
}
可以使用任何字符串作为分隔符,也可以用于二进制数据(std :: string支持二进制数据,包括null)
使用:
auto a = split("this!!is!!!example!string", "!!");
输出:
this
is
!example!string
#21楼
到目前为止,我在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
可以传递多个字符。
#22楼
这个答案接受字符串并将其放入字符串向量中。 它使用boost库。
#include <boost/algorithm/string.hpp>
std::vector<std::string> strs;
boost::split(strs, "string to split", boost::is_any_of("\t "));
#23楼
#include <vector>
#include <string>
#include <sstream>int main()
{std::string str("Split me by whitespaces");std::string buf; // Have a buffer stringstd::stringstream ss(str); // Insert the string into a streamstd::vector<std::string> tokens; // Create vector to hold our wordswhile (ss >> buf)tokens.push_back(buf);return 0;
}
#24楼
如果您想使用boost,但想使用整个字符串作为定界符(而不是像大多数先前提出的解决方案中那样使用单个字符),则可以使用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 examplesplit("HelloFOOworldFOO!", "FOO", ostream_iterator<string>(cout, "\n"));return 0;
}
#25楼
我喜欢将boost / regex方法用于此任务,因为它们为指定拆分标准提供了最大的灵活性。
#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 splitboost::sregex_token_iterator tokens(line.begin(),line.end(),re,-1);boost::sregex_token_iterator end;for (; tokens != end; ++tokens)std::cout << *tokens << std::endl;
}
#26楼
那这个呢:
#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;
}
#27楼
如果您需要按非空格符号解析字符串,则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, ';')
#28楼
这是另一个解决方案。 它紧凑且相当有效:
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;
}
可以很容易地将其模板化以处理字符串分隔符,宽字符串等。
请注意,分割""
导致一个空字符串,分割","
(即sep)会导致两个空字符串。
也可以轻松地扩展它以跳过空令牌:
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;
}
如果需要在多个定界符处拆分字符串同时跳过空标记,则可以使用以下版本:
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;
}
#29楼
最近,我不得不将驼峰式单词拆分为子单词。 没有定界符,只有大写字符。
#include <string>
#include <list>
#include <locale> // std::isuppertemplate<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;
}
例如,这将“ AQueryTrades”拆分为“ A”,“ Query”和“ Trades”。 该函数适用于窄和宽字符串。 因为它尊重当前语言环境,所以将“RaumfahrtÜberwachungsVerordnung”分为“ Raumfahrt”,“Überwachungs”和“ Verordnung”。
注意std::upper
应该真正作为函数模板参数传递。 然后,可以将此函数的更一般化的名称拆分为","
, ";"
等分隔符 或" "
。
#30楼
这是一个拆分函数:
- 是通用的
- 使用标准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";,");
如何遍历字符串中的单词?相关推荐
- 557. 反转字符串中的单词 III
557. 反转字符串中的单词 III 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例: 输入:"Let's take LeetCode cont ...
- 【leetcode】557 反转字符串中的单词III(字符串)
题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/ 题目描述 给定一个字符串,你需要反转字符串中每个单词的字符顺序 ...
- Suzy找到实习了吗Day 8 | 字符串开始啦 344. 反转字符串,541. 反转字符串 II,剑指 Offer 05. 替换空格,151. 反转字符串中的单词,左旋转字符串
这里是目录 344. 反转字符串 题目 Solution 541. 反转字符串 II 题目 Solution(v1) Solution(v2) 剑指 Offer 05. 替换空格 做题记录 151. ...
- Leetcode 557 反转字符串中的单词
Leetcode 557 反转字符串中的单词 题目描述: 给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例1: 输入:s = "Let's ...
- 将字符串中的单词翻转,不能使用php提供的任何函数 strlen 除外
将字符串中的单词翻转,不能使用php提供的任何函数 strlen 除外 题目: 写一个函数将字符串中的单词翻转,不能使用php提供的任何函数 strlen 除外. 单词的定义是: 1.只包含字母 2. ...
- 从零单刷Leetcode(JAVA描述)—— 557. 反转字符串中的单词 III
链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格 ...
- 如何大写字符串中每个单词的第一个字符
Java中是否内置了一个函数,该函数可以大写字符串中每个单词的第一个字符,而不会影响其他单词? 例子: jon skeet - > Jon Skeet miles o'Brien > Mi ...
- LeetCode-字符串-反转字符串中的单词 II
557. 反转字符串中的单词 III class Solution {public:string reverseWords(string s) {s+=' '; //为了让最后一个单词进入循环stri ...
- 习题:统计字符串中的单词个数
1 /*统计字符串中的单词个数*/ 2 #include<stdio.h> 3 int main(void) 4 { 5 char a[80]={""},c; 6 in ...
最新文章
- OpenStack环境搭建(五:附加项虚拟机文件备份使用)
- pytorch生成网络WGAN-GP实例
- 手把手带你玩转 AWS Lambda
- plot与legend画图与图例
- mysql dba失业_DBA要失业了?AI优化水平超DBA老炮儿
- 在数组中找出3个数使得它们和为0
- Web前端学习技巧有哪些?本文给你答案
- 谈谈如何利用 valgrind 排查内存错误
- ubuntu如何进入超级权限模式,退出超级权限模式,sudo su——root权限
- 安卓前端布局Android,Android开发的几种常见布局
- mpvue 从零开始 女友拉黑了我 5 不在以下request 合法域名列表中,请参考文档
- python 可执行文件打包_使用可执行文件打包Python库
- 硬核知识,C/C++移植法则分享
- 用单片机测量流体流速的_旋进旋涡流量计的测量原理及优点
- java使用Redis(六个类型)
- 计算机并口地址定义,电脑并口(LPT)引脚定义
- Tiktok/抖音全球用户数据统计
- 微商怎么做大做强,教你一套做微商全新打法
- php redis 批量发邮件,PHP使用Redis实现订阅发布与批量发送短信
- 添加SearchView控件时飘红的问题
热门文章
- RelativeLayout 深入理解
- Android中XML的命名空间、自定义属性
- html语言制作留言条,利用DIV+CSS制作右下角弹出留言板
- mysql timdir_MySQL备份之mysqlhotcopy与注意事项
- ConcurrentHashMap源码分析(2)——JDK1.8的实现
- iOS架构-静态库.framework之依赖第三方库(7)
- JavaScript常用DOM集合
- 懒人必备:.NetCore快速搭建ELK分布式日志中心
- LODOP提示、报错、现象,简短问答
- 二叉树原理和作用,总结