简体   繁体   English

意外的字符串流行为

[英]Unexpected stringstream behavior

Consider the following code: 考虑以下代码:

#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;
}

Running the above code yields some random output: 运行上面的代码会产生一些随机输出:

12
0

At some other times, the following output is observed: 在其他时间,观察到以下输出:

12
4

I expected the output to be simply: 我希望输出很简单:

12 
30

Why did I get the unexpected results? 为什么我得到了意外的结果?

Also, what should be the best way to parse a string s to int i without necessary C++11 support? 另外,没有必要的C ++ 11支持,将string s解析为int i的最佳方法应该是什么? Should it be int i = atoi(s.c_str()) ? 应该是int i = atoi(s.c_str())吗?

When you extract 12 from the stream, you reach the end of it, which puts it in a bad state. 当从流中提取12 ,到达其末尾,这使其处于错误状态。 Any further extractions will fail. 任何进一步的提取将失败。 You need to call ss.clear() around the time you clear its contents. 您需要在清除其内容时调用ss.clear()

If you had checked the success of your extractions, you would have avoided this problem. 如果您检查了提取是否成功,则可以避免此问题。 I generally expect to see any extraction from a stream as some kind of condition. 我通常希望将任何从流中提取的内容视为某种情况。

And yes, using string streams to parse strings as integers is a perfectly reasonable way to do it pre-C++11. 是的,在C ++ 11之前,使用字符串流将字符串解析为整数是一种完全合理的方法。 I would prefer it over using atoi . 我更喜欢使用atoi For anybody who wants to know the C++11 way, use std::stoi . 对于任何想了解C ++ 11方式的人,请使用std :: stoi

For those who're here with something similar to the above but not exactly, I found that when you've got a stream in a scenario where you need to re-use it (like in a while loop), the easiest way to avoid head-aches (in addition to ss.clear ) is to create a new stream each time. 对于那些与上面类似但又不完全相同的人,我发现当您在需要重用流的场景中(例如在while循环中)获得流时,避免这种情况的最简单方法是头痛(除了ss.clear )是每次创建一个新的流。 For example: 例如:

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();
    }
}

So every time the user enters an invalid input, at the start of the while loop, I create a new stringstream object. 因此,每次用户输入无效的输入时,在while循环的开始,我都会创建一个新的stringstream对象。 While researching my function's undefined behavior, I found this question that has a similar example. 虽然研究我的函数的不确定行为,我发现这个问题,有一个类似的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM