协慌网

登录 贡献 社区

迭代字符串单词的最优雅方式

迭代字符串的最优雅的方法是什么?可以假设该字符串由用空格分隔的单词组成。

请注意,我对 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);
}

答案

我用它来分隔字符串。第一个将结果放在预先构造的向量中,第二个返回一个新向量。

#include <string>
#include <sstream>
#include <vector>
#include <iterator>

template<typename Out>
void split(const std::string &s, char delim, Out result) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, 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", ':');

对于它的价值,这是从输入字符串中提取标记的另一种方法,仅依赖于标准库设施。这是 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>{}};

使用 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)。

有关详细信息,请参阅文档