如何迭代由空格分隔的单词组成的字符串中的单词?
注意,我对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);
}
并不是说我们需要更多的答案,但这是我受到埃文·特兰启发后想到的。
std::vector <std::string> split(const string &input, auto delimiter, bool skipEmpty=true) {
/*
Splits a string at each delimiter and returns these strings as a string vector.
If the delimiter is not found then nothing is returned.
If skipEmpty is true then strings between delimiters that are 0 in length will be skipped.
*/
bool delimiterFound = false;
int pos=0, pPos=0;
std::vector <std::string> result;
while (true) {
pos = input.find(delimiter,pPos);
if (pos != std::string::npos) {
if (skipEmpty==false or pos-pPos > 0) // if empty values are to be kept or not
result.push_back(input.substr(pPos,pos-pPos));
delimiterFound = true;
} else {
if (pPos < input.length() and delimiterFound) {
if (skipEmpty==false or input.length()-pPos > 0) // if empty values are to be kept or not
result.push_back(input.substr(pPos,input.length()-pPos));
}
break;
}
pPos = pos+1;
}
return result;
}
STL还没有这样的方法。
但是,您可以通过使用std::string::C_str()成员来使用C的strtok()函数,也可以编写自己的函数。下面是我在快速谷歌搜索(“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++编程-HOWTO-7.html
如果您对代码示例有疑问,请留下评论,我会解释。
仅仅因为它没有实现称为迭代器的typedef或重载<<运算符,并不意味着它是错误的代码。我经常使用C函数。例如,printf和scanf都比std::cin和std::cout快(很明显),fopen语法对二进制类型更友好,它们也倾向于生成更小的EXE。
不要被这种“优雅胜过性能”的交易所吸引。
根据Galik的回答,我做了这个。这大部分都在这里,所以我不必一遍又一遍地写。C++仍然没有原生拆分函数,这真是太疯狂了。特征:
应该很快。容易理解(我认为)。合并空节。使用多个分隔符(例如“\r\n”)很简单
#include <string>
#include <vector>
#include <algorithm>
std::vector<std::string> split(const std::string& s, const std::string& delims)
{
using namespace std;
vector<string> v;
// Start of an element.
size_t elemStart = 0;
// We start searching from the end of the previous element, which
// initially is the start of the string.
size_t elemEnd = 0;
// Find the first non-delim, i.e. the start of an element, after the end of the previous element.
while((elemStart = s.find_first_not_of(delims, elemEnd)) != string::npos)
{
// Find the first delem, i.e. the end of the element (or if this fails it is the end of the string).
elemEnd = s.find_first_of(delims, elemStart);
// Add it.
v.emplace_back(s, elemStart, elemEnd == string::npos ? string::npos : elemEnd - elemStart);
}
// When there are no more non-spaces, we are done.
return v;
}
如果您希望按某些字符分割字符串,可以使用
#include<iostream>
#include<string>
#include<vector>
#include<iterator>
#include<sstream>
#include<string>
using namespace std;
void replaceOtherChars(string &input, vector<char> ÷rs)
{
const char divider = dividers.at(0);
int replaceIndex = 0;
vector<char>::iterator it_begin = dividers.begin()+1,
it_end= dividers.end();
for(;it_begin!=it_end;++it_begin)
{
replaceIndex = 0;
while(true)
{
replaceIndex=input.find_first_of(*it_begin,replaceIndex);
if(replaceIndex==-1)
break;
input.at(replaceIndex)=divider;
}
}
}
vector<string> split(string str, vector<char> chars, bool missEmptySpace =true )
{
vector<string> result;
const char divider = chars.at(0);
replaceOtherChars(str,chars);
stringstream stream;
stream<<str;
string temp;
while(getline(stream,temp,divider))
{
if(missEmptySpace && temp.empty())
continue;
result.push_back(temp);
}
return result;
}
int main()
{
string str ="milk, pigs.... hot-dogs ";
vector<char> arr;
arr.push_back(' '); arr.push_back(','); arr.push_back('.');
vector<string> result = split(str,arr);
vector<string>::iterator it_begin= result.begin(),
it_end= result.end();
for(;it_begin!=it_end;++it_begin)
{
cout<<*it_begin<<endl;
}
return 0;
}