如何迭代由空格分隔的单词组成的字符串中的单词?
注意,我对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);
}
这里有一个拆分函数:
是通用的使用标准C++(无增强)接受多个分隔符忽略空标记(可以轻松更改)模板<typename T>矢量<T>拆分(常量T&str,常量T&分隔符){向量<T>v;typename T::size_type start=0;自动位置=str.find_first_of(分隔符,开始);而(pos!=T::npos){if(pos!=开始)//忽略空标记v.template_back(str,start,pos-start);开始=位置+1;pos=str.find_first_of(分隔符,开始);}if(start<str.length())//忽略尾随分隔符v.template_back(str,start,str.length()-start);//添加字符串的剩余部分返回v;}
示例用法:
vector<string> v = split<string>("Hello, there; World", ";,");
vector<wstring> v = split<wstring>(L"Hello, there; World", L";,");
使用std::string_view和Eric Niebler的range-v3库:
https://wandbox.org/permlink/kW5lwRCL1pxjp2pW
#include <iostream>
#include <string>
#include <string_view>
#include "range/v3/view.hpp"
#include "range/v3/algorithm.hpp"
int main() {
std::string s = "Somewhere down the range v3 library";
ranges::for_each(s
| ranges::view::split(' ')
| ranges::view::transform([](auto &&sub) {
return std::string_view(&*sub.begin(), ranges::distance(sub));
}),
[](auto s) {std::cout << "Substring: " << s << "\n";}
);
}
通过使用循环的范围而不是范围::for_each算法:
#include <iostream>
#include <string>
#include <string_view>
#include "range/v3/view.hpp"
int main()
{
std::string str = "Somewhere down the range v3 library";
for (auto s : str | ranges::view::split(' ')
| ranges::view::transform([](auto&& sub) { return std::string_view(&*sub.begin(), ranges::distance(sub)); }
))
{
std::cout << "Substring: " << s << "\n";
}
}
谢谢@Jairo Abdiel Toribio Cisneros。它对我有效,但您的函数返回一些空元素。因此,对于没有空的返回,我编辑了以下内容:
std::vector<std::string> split(std::string str, const char* delim) {
std::vector<std::string> v;
std::string tmp;
for(std::string::const_iterator i = str.begin(); i <= str.end(); ++i) {
if(*i != *delim && i != str.end()) {
tmp += *i;
} else {
if (tmp.length() > 0) {
v.push_back(tmp);
}
tmp = "";
}
}
return v;
}
使用:
std::string s = "one:two::three";
std::string delim = ":";
std::vector<std::string> vv = split(s, delim.c_str());
作为一个业余爱好者,这是我想到的第一个解决方案。我有点好奇,为什么我还没有在这里看到类似的解决方案,是不是我的做法有根本问题?
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> split(const std::string &s, const std::string &delims)
{
std::vector<std::string> result;
std::string::size_type pos = 0;
while (std::string::npos != (pos = s.find_first_not_of(delims, pos))) {
auto pos2 = s.find_first_of(delims, pos);
result.emplace_back(s.substr(pos, std::string::npos == pos2 ? pos2 : pos2 - pos));
pos = pos2;
}
return result;
}
int main()
{
std::string text{"And then I said: \"I don't get it, why would you even do that!?\""};
std::string delims{" :;\".,?!"};
auto words = split(text, delims);
std::cout << "\nSentence:\n " << text << "\n\nWords:";
for (const auto &w : words) {
std::cout << "\n " << w;
}
return 0;
}
http://cpp.sh/7wmzy
这里有一个拆分函数:
是通用的使用标准C++(无增强)接受多个分隔符忽略空标记(可以轻松更改)模板<typename T>矢量<T>拆分(常量T&str,常量T&分隔符){向量<T>v;typename T::size_type start=0;自动位置=str.find_first_of(分隔符,开始);而(pos!=T::npos){if(pos!=开始)//忽略空标记v.template_back(str,start,pos-start);开始=位置+1;pos=str.find_first_of(分隔符,开始);}if(start<str.length())//忽略尾随分隔符v.template_back(str,start,str.length()-start);//添加字符串的剩余部分返回v;}
示例用法:
vector<string> v = split<string>("Hello, there; World", ";,");
vector<wstring> v = split<wstring>(L"Hello, there; World", L";,");