【问题标题】:Unexpected stringstream behavior意外的字符串流行为
【发布时间】:2014-08-07 18:46:00
【问题描述】:

考虑以下代码:

#include <sstream>
#include <iostream>

using namespace std;

int main()
{
    stringstream ss;

    ss << string("12");
    int h;
    ss >> h;
    cout << h << endl;

    ss.str(string("")); // clear the content of ss

    ss << string("30");
    int m;
    ss >> m;
    cout << m << endl;

    return 0;
}

运行上述代码会产生一些随机输出:

12
0

在其他一些时候,观察到以下输出:

12
4

我希望输出很简单:

12 
30

为什么我得到了意想不到的结果?

另外,在没有必要的 C++11 支持的情况下,将 string s 解析为 int i 的最佳方法应该是什么?应该是int i = atoi(s.c_str())吗?

【问题讨论】:

  • '另外,最好的解析方式应该是什么......'使用std::istringstream
  • 你没有适当地清除流,使用ss.clear()

标签: c++ iostream stringstream istream


【解决方案1】:

当您从流中提取12 时,您会到达它的末尾,这会使它处于错误状态。任何进一步的提取都将失败。您需要在清除其内容时致电ss.clear()

如果您检查了提取是否成功,您就可以避免这个问题。我通常希望将从流中提取的任何内容视为某种条件。

是的,在 C++11 之前,使用字符串流将字符串解析为整数是一种非常合理的方法。我更喜欢使用atoi。对于任何想了解 C++11 方式的人,请使用 std::stoi

【讨论】:

  • 谢谢!将string s 解析为int i 的最佳方法应该是什么? stringstream 是个好主意吗?
  • @lwxted 是的,我更愿意看到atoi
  • @lwxted 使用istringstream s("123"); s &gt;&gt; valueostringstream s; s &lt;&lt; value; s.str() 应该可以避免问题中的问题(避免使用字符串流)。
  • @lwxted, std::stoi(str)
【解决方案2】:

对于那些与上面类似但不完全一样的人,我发现当您在需要重用它的场景中获得流时(例如在 while 循环中),最简单的避免头痛的方法(除了ss.clear)是每次都创建一个新流。例如:

int GetInteger(){
    cout << "Enter an int: " << endl;
    string userInput;
    while (true){
        stringstream ss;
        getline(cin,userInput);
        ss << userInput;
        //Making sure that an int was passed
        int result;
        if (ss >> result){
            //Making sure that there is no extra stuff after
            string extra;
            if (ss >> extra){
                cout << "Unexpected stuff at end of input: " << extra << endl;
            } else{
                return result;
            }
        } else {
            cout << "Number you entered is not an INT. Please enter an integer" << endl;
        }
        cout << "Retry: " << endl;
        // ss.clear();
    }
}

因此,每次用户输入无效输入时,在 while 循环开始时,我都会创建一个新的 stringstream 对象。在研究我的函数的未定义行为时,我发现this 问题有一个类似的例子。

【讨论】:

    猜你喜欢
    • 2021-06-13
    • 2023-03-26
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    相关资源
    最近更新 更多