如何迭代由空格分隔的单词组成的字符串中的单词?
注意,我对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++11和STL的解决方案。它应该是合理有效的:
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
std::vector<std::string> split(const std::string& s)
{
std::vector<std::string> v;
const auto end = s.end();
auto to = s.begin();
decltype(to) from;
while((from = std::find_if(to, end,
[](char c){ return !std::isspace(c); })) != end)
{
to = std::find_if(from, end, [](char c){ return std::isspace(c); });
v.emplace_back(from, to);
}
return v;
}
int main()
{
std::string s = "this is the string to split";
auto v = split(s);
for(auto&& s: v)
std::cout << s << '\n';
}
输出:
this
is
the
string
to
split
这是我的版本
#include <vector>
inline std::vector<std::string> Split(const std::string &str, const std::string &delim = " ")
{
std::vector<std::string> tokens;
if (str.size() > 0)
{
if (delim.size() > 0)
{
std::string::size_type currPos = 0, prevPos = 0;
while ((currPos = str.find(delim, prevPos)) != std::string::npos)
{
std::string item = str.substr(prevPos, currPos - prevPos);
if (item.size() > 0)
{
tokens.push_back(item);
}
prevPos = currPos + 1;
}
tokens.push_back(str.substr(prevPos));
}
else
{
tokens.push_back(str);
}
}
return tokens;
}
它适用于多字符分隔符。它防止空令牌进入结果。它使用单个标头。当您不提供分隔符时,它将字符串作为一个标记返回。如果字符串为空,它还会返回一个空结果。不幸的是,它的效率很低,因为存在巨大的std::vector副本,除非您使用C++11进行编译,否则应该使用移动示意图。在C++11中,这段代码应该很快。
每个人都回答了预定义的字符串输入。我认为这个答案将帮助某人进行扫描输入。
我使用令牌向量来保存字符串令牌。这是可选的。
#include <bits/stdc++.h>
using namespace std ;
int main()
{
string str, token ;
getline(cin, str) ; // get the string as input
istringstream ss(str); // insert the string into tokenizer
vector<string> tokens; // vector tokens holds the tokens
while (ss >> token) tokens.push_back(token); // splits the tokens
for(auto x : tokens) cout << x << endl ; // prints the tokens
return 0;
}
样本输入:
port city international university
样本输出:
port
city
international
university
注意,默认情况下,这将仅适用于空格作为分隔符。您可以使用自定义分隔符。为此,您定制了代码。让分隔符为“,”。所以使用
char delimiter = ',' ;
while(getline(ss, token, delimiter)) tokens.push_back(token) ;
而不是
while (ss >> token) tokens.push_back(token);
我相信还没有人发布这个解决方案。与其直接使用分隔符,它基本上与boost::split()相同,即它允许您传递一个谓词,如果字符是分隔符,则返回true,否则返回false。我认为这给了程序员更多的控制,最棒的是你不需要提升。
template <class Container, class String, class Predicate>
void split(Container& output, const String& input,
const Predicate& pred, bool trimEmpty = false) {
auto it = begin(input);
auto itLast = it;
while (it = find_if(it, end(input), pred), it != end(input)) {
if (not (trimEmpty and it == itLast)) {
output.emplace_back(itLast, it);
}
++it;
itLast = it;
}
}
然后可以这样使用:
struct Delim {
bool operator()(char c) {
return not isalpha(c);
}
};
int main() {
string s("#include<iostream>\n"
"int main() { std::cout << \"Hello world!\" << std::endl; }");
vector<string> v;
split(v, s, Delim(), true);
/* Which is also the same as */
split(v, s, [](char c) { return not isalpha(c); }, true);
for (const auto& i : v) {
cout << i << endl;
}
}