【问题标题】:How to split a space separated string into multiple strings in C++?如何在 C++ 中将空格分隔的字符串拆分为多个字符串?
【发布时间】:2012-01-30 18:47:28
【问题描述】:

我的代码如下所示:

static int myfunc(const string& stringInput)
{
    string word;
    stringstream ss;

    ss << stringInput;
    while(ss >> word)
    {
        ++counters[word];
    }
    ...
}

这里的目的是获取一个输入字符串(用空格''分隔)到字符串变量word中,但是这里的代码似乎有很多开销——将输入字符串转换为字符串流和从字符串流中读取到目标字符串中。

有没有更优雅的方式来实现同样的目的?

【问题讨论】:

标签: c++ string stream


【解决方案1】:
Code in c++
#include<sstream>
#include<vector>
using namespace std;    
string diskNames="vbbc anmnsa mansdmns";
string temp;
vector <string> cds;
stringstream s (diskNames);
while(s>> temp)
cds.push_back(temp);

【讨论】:

    【解决方案2】:

    在 Visual C++ 11 中,您可以使用 TR1 中的 regex_token_iterator。

    sregex_token_iterator::regex_type white_space_separators("[[:space:]]+",regex_constants::optimize);
    
    for(sregex_token_iterator i(s.begin(),s.()end,white_space_separators,-1),end; i!=end; i++)
    {
     cout << *i << endl;
     // or use i.start, i.end which is faster access
    }
    

    如果您担心性能(以及字符串复制等开销),您可以编写自己的例程:

    #include <ctype.h>
    
    #include <string>
    #include <iostream>
    using namespace std;
    
    int main()
    {
     string s = "Text for tokenization  ";
    
     const char *start = s.c_str();
     const char *end = start + s.size();
     const char *token = start;
    
     while (start!=end)
     {
       if(isspace(*start))
       {
        if (token < start)
        {
          // Instead of constructing string, you can 
          // just use [token,start] part of the input buffer
          cout << string(token,start) << ' ';
        }
    
        start++;
        token = start;
       }
       else
       {
        start++;
       }
     } 
    
     if (token < start)
     {
        cout << string(token,start) << ' ';
     }
    
    }
    

    【讨论】:

    • 谢谢你,佩特罗。您的拆分例程与 Andrew Koenig 在他的“Accelerated C++”中的非常相似。两者都是不错的功能。
    【解决方案3】:

    使用流迭代器和标准函数:

    static int myfunc(std::string const& stringInput)
    {
        std::stringstream ss(stringInput);
    
        std::for_each(std::istream_iterator<std::string>(ss),
                      std::istream_iterator<std::string>(),
                      [&counters](std::string const& word) { ++counters[word];}
                     )
        ...
    }
    

    如果你没有 lambda 那么:

    struct Helper
    {
         void operator()(std::string const& word) const {++counters[word];}
         Helper(CounterType& c) : counters(c) {}
         CounterType& counters;
    };
    
    static int myfunc(std::string const& stringInput)
    {
        std::stringstream ss(stringInput);
    
        std::for_each(std::istream_iterator<std::string>(ss),
                      std::istream_iterator<std::string>(),
                      Helper(counters)
                     )
        ...
    }
    

    【讨论】:

    • 谢谢你,洛基。你的代码看起来很棒。不过,我更喜欢不涉及流的方式。 :-)
    【解决方案4】:

    您在问如何拆分字符串。 Boost 有一个有用的实用程序 boost::split()

    http://www.boost.org/doc/libs/1_48_0/doc/html/string_algo/usage.html#id3115768

    这是一个将结果词放入向量的示例:

    #include <boost/algorithm/string.hpp>
    std::vector<std::string> strs;
    boost::split(strs, "string to split", boost::is_any_of("\t "));
    

    【讨论】:

    • 谢谢,但如果可能的话,我打算放弃使用流。
    • 谢谢你,亚历克斯。是的,这就是我想要的。但是我不确定我的g++编译器是否带有boost库,如何检查boost是否存在?顺便说一句,在编译源代码时使用任何额外的 -l 命令吗?如果没有可用的 boost,STL 中是否有类似的实用功能?
    • 抱歉这里的忍者编辑。一开始我误解了你的问题。
    • 顺便说一句,亚历克斯。只需在 Andrew Koenig 的经典“加速 C++”中找到另一个 split() 的实现。第 5 章的第 5.6 节(将字符串分开)中提供了实现。
    • @Qiang :您标记了自己的问题stream,但您试图避免流?这有点误导。
    【解决方案5】:

    使用ostringstream,也许

    istringstream(stringInput); // initialize with the string
    

    【讨论】:

    • 是的,这样可以节省一点。但是基本思路还是一样的:构造一个stringstream,然后从这个stream中读取。我们可以不使用streamstream吗?并且仍然将空格分隔的字符串读入word?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    相关资源
    最近更新 更多