请考虑以下代码:
#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())
吗?
答案 0 :(得分:6)
从流中提取12
时,会到达它的末尾,这会使其处于错误状态。任何进一步的提取都将失败。您需要在清除其内容时调用ss.clear()
。
如果您检查了提取的成功,您可以避免此问题。我通常希望从流中看到任何提取都是某种条件。
是的,使用字符串流将字符串解析为整数是在C ++ 11之前完成它的一种非常合理的方法。我更喜欢使用atoi
。对于任何想要了解C ++ 11方式的人,请使用std::stoi。
答案 1 :(得分:0)
对于那些在这里与上面类似但又不完全相同的人,我发现在需要重用它的场景中(例如在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问题。