意外的字符串流行为

Unexpected stringstream behavior

本文关键字:流行 字符串 意外      更新时间:2023-10-16

考虑以下代码:

#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 sint i的最佳方法应该是什么?应该是int i = atoi(s.c_str())吗?

当您从流中提取12时,您到达了它的末端,这使它处于不良状态。任何进一步的提取都将失败。您需要在清除ss.clear()的内容时调用它。

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

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

对于那些在这里有类似于上面的东西,但不完全是,我发现,当你有一个流在一个场景中,你需要重用它(如在一个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对象。在研究我的函数的未定义行为时,我发现这个问题有一个类似的例子。