【问题标题】:Stringstream to vector<int>字符串流到向量<int>
【发布时间】:2012-02-04 07:44:50
【问题描述】:

我想知道将std::stringstream 写入vector&lt;int&gt; 的最佳方式是什么。

下面是stringstream 中的示例: "31 #00 532 53 803 33 534 23 37"

这是我得到的:

int buffer = 0;
vector<int> analogueReadings;
stringstream output;

 while(output >> buffer)
     analogueReadings.push_back(buffer);

然而似乎发生的事情是,它读取第一件事,然后到达#00 并返回0,因为它不是一个数字。

理想情况下,我想要的是,它到达#,然后跳过所有字符,直到下一个空格。这可以用标志或其他东西吗?

谢谢。

【问题讨论】:

    标签: c++ visual-studio-2010 stringstream lexical-cast


    【解决方案1】:
    #include <iostream>
    #include <sstream>
    #include <vector>
    
    int main ( int, char ** )
    {
        std::istringstream reader("31 #00 532 53 803 33 534 23 37");
        std::vector<int> numbers;
        do
        {
            // read as many numbers as possible.
            for (int number; reader >> number;) {
                numbers.push_back(number);
            }
            // consume and discard token from stream.
            if (reader.fail())
            {
                reader.clear();
                std::string token;
                reader >> token;
            }
        }
        while (!reader.eof());
    
        for (std::size_t i=0; i < numbers.size(); ++i) {
            std::cout << numbers[i] << std::endl;
        }
    }
    

    【讨论】:

    • 如果您不想一次读取整个序列,可以删除外部 do-while 循环。在这种情况下,您可以读取由非数字标记分隔的一系列数字。
    • 运行代码。它打印 31、532、53、803、33、534、23、37。没有插入 0。
    • 谢谢安德烈。我喜欢你的算法。我不知道失败的部分和东西。感谢您的宝贵时间。
    • +1。这是做到这一点的方法。但前提是您可以将例如 0x2A 解释为 0 并将 55bla 解释为 55。否则请参阅我的答案或类似的内容。
    • 另请注意,当转换例如 25 10000000000 77 0 0 由于不受控制的溢出时,使用此方法会发生灾难性的失败。在我的系统上,结果是 25 0 0(请注意,也缺少 77)。
    【解决方案2】:

    你需要测试你是否有一个数字。使用这里的答案:

    How to determine if a string is a number with C++?

    #include <iostream>
    #include <sstream>
    #include <vector>
    using namespace std;
    
    bool is_number(const std::string& s){
       std::string::const_iterator it = s.begin();
       while (it != s.end() && std::isdigit(*it)) ++it;
       return !s.empty() && it == s.end();
    }
    int main ()
    {
        vector<int> analogueReadings;
        std::istringstream output("31 #00 532 04hello 099 53 803 33 534 23 37");
    
        std::string tmpbuff;
        while(output >> tmpbuff){
          if (is_number(tmpbuff)){
             int num;
             stringstream(tmpbuff)>>num;
             analogueReadings.push_back(num);
           }
        }
    }
    

    结果是 31 532 99 53 803 33 534 23 37

    此外,此处描述了使用这样的词法转换的重要缺点: How to parse a string to an int in C++? ,其中给出了tringstream(tmpbuff)&gt;&gt;num 的替代方案。

    例如 04hello 变成 4 和 7.4e55 变成 7。下溢和下溢也有可怕的问题。 André Caron 的清洁解决方案转化了

    25 10000000000 77 0 0
    

    进入

    25 0 0 
    

    在我的系统上。请注意,也缺少 77!

    【讨论】:

    • output &gt;&gt; buffer 类型为bufferint 表达式已经测试了它是否是一个数字。诀窍在于 OP 的循环条件测试是模棱两可的:它不区分流结束和读取数字失败。
    • 顺便说一句,这是一个糟糕的算法。一般情况下(token是一个数字),token的字符会被处理3次:一次将token读入字符串,一次执行“是数字”测试,一次解析数字。
    • 我相信如果stringstream中的第一项是NAN,那么while循环就永远不会再运行了。我认为这就是 André Caron 使用 DO-WHILE 循环的原因。
    • 我的方法适用于所有以 10 为基数的整数情况,忽略其他任何内容。另请参阅编辑说明。在这种情况下,我不明白您所说的 NAN 是什么意思,因为我们处理的是字符串和整数,而不是浮点数。如果第一项不是整数,则应忽略它。
    【解决方案3】:

    无循环版本:

    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <algorithm>
    #include <sstream>
    
    using namespace std;
    
    class IntegerFiller
    {
        vector<int> &m_vec;
    public:
        IntegerFiller(vector<int> &vec): m_vec(vec) {}
    
        void operator()(const std::string &str)
        {
            stringstream ss(str);
            int n;
            ss >> n;
            if ( !ss.fail() )
                m_vec.push_back(n);
        }
    };
    
    int main()
    {
        vector<int> numbers;
        IntegerFiller filler(numbers);
        for_each(istream_iterator<string>(cin), istream_iterator<string>(), filler);
        copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " "));
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      我认为最好的方法是

      #include <string>
      #include <sstream>
      #include <vector>
      
      using namespace std;   
      
      int main()
      {   
        string numbers = "23,24,27,28";   
        vector<int> integers;   
        stringstream s(numbers);   
        char ch;   
        int a;   
        while(s>>a>>ch) integers.push_back(a);   //s >> reads int char pair 
        s>>a;                                    // reads the last int
        integers.push_back(a); 
      
        for(int i = 0; i < integers.size(); i++) cout << integers[i] << "\n";
      }
      

      【讨论】:

        猜你喜欢
        • 2010-10-02
        • 2011-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-22
        • 2014-01-06
        相关资源
        最近更新 更多