如何迭代由空格分隔的单词组成的字符串中的单词?
注意,我对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);
}
这是一个顶级答案的扩展。它现在支持设置返回元素的最大数量N。字符串的最后一位将在第N个元素中结束。MAXELEMENTS参数是可选的,如果设置为默认值0,它将返回无限数量的元素。:-)
.h:
class Myneatclass {
public:
static std::vector<std::string>& split(const std::string &s, char delim, std::vector<std::string> &elems, const size_t MAXELEMENTS = 0);
static std::vector<std::string> split(const std::string &s, char delim, const size_t MAXELEMENTS = 0);
};
.cpp:
std::vector<std::string>& Myneatclass::split(const std::string &s, char delim, std::vector<std::string> &elems, const size_t MAXELEMENTS) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
if (MAXELEMENTS > 0 && !ss.eof() && elems.size() + 1 >= MAXELEMENTS) {
std::getline(ss, item);
elems.push_back(item);
break;
}
}
return elems;
}
std::vector<std::string> Myneatclass::split(const std::string &s, char delim, const size_t MAXELEMENTS) {
std::vector<std::string> elems;
split(s, delim, elems, MAXELEMENTS);
return elems;
}
我对string和u32string~的一般实现,使用boost::algorithm::split签名。
template<typename CharT, typename UnaryPredicate>
void split(std::vector<std::basic_string<CharT>>& split_result,
const std::basic_string<CharT>& s,
UnaryPredicate predicate)
{
using ST = std::basic_string<CharT>;
using std::swap;
std::vector<ST> tmp_result;
auto iter = s.cbegin(),
end_iter = s.cend();
while (true)
{
/**
* edge case: empty str -> push an empty str and exit.
*/
auto find_iter = find_if(iter, end_iter, predicate);
tmp_result.emplace_back(iter, find_iter);
if (find_iter == end_iter) { break; }
iter = ++find_iter;
}
swap(tmp_result, split_result);
}
template<typename CharT>
void split(std::vector<std::basic_string<CharT>>& split_result,
const std::basic_string<CharT>& s,
const std::basic_string<CharT>& char_candidate)
{
std::unordered_set<CharT> candidate_set(char_candidate.cbegin(),
char_candidate.cend());
auto predicate = [&candidate_set](const CharT& c) {
return candidate_set.count(c) > 0U;
};
return split(split_result, s, predicate);
}
template<typename CharT>
void split(std::vector<std::basic_string<CharT>>& split_result,
const std::basic_string<CharT>& s,
const CharT* literals)
{
return split(split_result, s, std::basic_string<CharT>(literals));
}
谢谢@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());