Value stored when istream read fails

巧了我就是萌 提交于 2020-01-11 11:10:08

问题


Sample code:

#include <iostream>

int main()
{
    int x = 5;
    std::cin >> x;
    std::cout << x << '\n';
}

On one particular implementation the following behaviour occurs:

  • Input: 6; output 6
  • Input: a; output: 0
  • Input: (end-of-file); output 5
  • Input: (whitespace followed by end-of-file); output 5

So, on failure, the cin >> x is assigning 0 to x if it was a failure to convert text to int; but it is not assigning 0 if the failure was due to end-of-file.

Is this correct behaviour? If not, what is the correct behaviour, according to the C++ Standard?

I have a recollection from previously discussing on SO that all cases should write 0 since C++11, but I could not find anything using the search feature; and the iostreams section of the C++ standard is pretty heavy going.


回答1:


According to 27.7.2.2.1 [istream.formatted.reqmts] paragraph 1 the first things for the formatted input function is to construct an std::istream::senty object. Further processing depends on whether this object converts to true or false: nothing happens to the value if the sentry converts to false.

According to 27.7.2.1.3 [istream::sentry] paragraphs 5 and 7 the sentry will convert to false if the stream's flags are not std::ios_base::goodbit. That is, if either a failure happend or EOF is reached the sentry will convert to false. As a result, the value stays at 5 when EOF is reached after skipping whitespace, assuming std::ios_base::skipws is set. Unsetting std::ios_base::skipws should result in the value becoming 0 if there is, at least, one space.

Once parsing is actually done, the applies logic is defined in 22.4.2.1.2 [facet.num.get.virtuals] paragraph 3, Stage 3. The key section on the affected value is

...

The numeric value to be stored can be one of:

— zero, if the conversion function fails to convert the entire field. ios_base::failbit is assigned to err.

— the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbit is assigned to err.

— the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented in val. ios_base::failbit is assigned to err.

— the converted value, otherwise.

The resultant numeric value is stored in val.

So, the observed behavior is correct.

With pre-C++11 the value was left unchanged in all cases. It was considered desirable to tell errors apart and indicate with the value which value should be represented. The discussions on how to change the behavior went on for a rather long time and were actually quite contentious.

That the value isn't changed if EOF is reached before attempting a conversion may be considered an error. I don't recall that case to be considered while the change was discussed.




回答2:


Yes, this is the correct behaviour since C++11.

  • istream behavior change in C++ upon failure

The difference in what you're seeing is that a zero is written "when extraction fails", but extraction is not even attempted if EOF is already set on the stream… so nothing happens.



来源:https://stackoverflow.com/questions/32945923/value-stored-when-istream-read-fails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!