使用istringstream转换的不当行为

时间:2014-12-11 11:17:40

标签: c++ sstream

当我尝试使用istringstream从输入中提取有效数字时,我从istringstream获得了以下不当行为:
例如:

void extract(void)
{
double x;
string line, temp;

getline(cin, line);
istringstream is(line);
while(is >>temp)
{
    if(istringstream(temp) >>x)
        {std::cout<<"number read: "<<x<<endl;}
}

}

输入: 1 2 3rd 4th

输出:

number read: 1
number read: 2
number read: 3
number read: 4

错误行为是istringstream将字符串3rd转换为数字3 为什么istringstream会这样做?如何避免这种情况?

2 个答案:

答案 0 :(得分:3)

这是因为您从流中读取数字

>>运算符从流中提取"3rd",并尝试将其转换为double,但由于只有字符串的第一个字符是数字,因此它只能解析"3"并简单地丢弃非数字字符。

如果你想要"3rd",那么你需要把它作为一个字符串来读。

答案 1 :(得分:0)

>>运算符只能在流中读取尽可能多的内容, 留下任何剩余的角色。因此:

std::istringstream( temp ) >> x
如果3包含temp,则

仅会提取3rd rd。为了确保整个字段已被读取, 你需要确保你到最后:

std::istringstream fieldParser( temp );
if ( fieldParser >> x && fieldParser.peek() == EOF ) {
    // ...
}
例如,

。 (更一般地说,您需要附加>> std::ws 到输入链的末尾,跳过任何尾随的空格。 但是,在您的情况下,因为temp使用>> 运算符,保证它不包含空格。)

FWIW:在这个特殊情况下,我会使用strtod

errno = 0;
const char* end;
x = strtod( temp.c_str(), &end );
if ( errno != 0 || *end != '\0' ) {
    //  Error occured...
}

但是,无论哪种方式,你都不能在一个if中完成;你会 之前需要额外的代码。