9
#include<iostream>;

int main()
{
    int a = 1;
    int b = 2;
    std::cin >> a >> b;
    std::cout << a << "+" << b << "=" << a+b << std::endl;
    return 0;
}

when I enter 3 4 as input,the output will be 3+4=7,well,it's strange; But when I enter a b,the output is 0+0=0(Why it is 0 and 0?); The most confusing,a 4,it will be 0+0=0(Why not '0+4=4'?????); Then i write another prog.

#include<iostream>;

int main()
{
    int a = 1;
    int b = 2;
    std::cin >> a;
    std::cin.clear();
    std::cin >> b;
    std::cout << a << "+" << b << "=" << a+b << std::endl;
    return 0;
}

When i enter a 4,why is it still 0+0=0?Shouldn't it be 0+4=4?

Thanks to all the warm-hearted!!

I write prog3,to test what will happen when i don't write int a=1;int b=2;

2

#include <iostream>
using namespace std;
int main()
{  
    int a,b;
    cin >> a  ;
    cin >> b;
    cout<< a << "+"<< b <<"="<< a+b << endl;
    return 0;
}

When a bagain,it outputs 0+-1218170892=-1218170892(Why isn't 0+0=0??)

user1668903
  • 407
  • 5
  • 11
  • the input is expected to be an integer, not a character. Entering "a", "3.141" or "whatever" simply isn't valid. If your input is "a", the program doesn't know that you've used "a" as a variable and that you want to use the default value instead. – stefan Sep 13 '12 at 14:45
  • It's obvious that it is C++11, because otherwise, the values would be 1 and 2, not 0's. – Drise Sep 13 '12 at 14:54
  • To answer your edit: You haven't removed a from the input. You need `cin.clear(); cin.ignore(1);`, so that the second extraction will succeed. – Drise Sep 13 '12 at 15:14
  • @Drise Can u help me about the prog3? – user1668903 Sep 13 '12 at 15:44
  • a and b are uninitialized. They have garbage values from the memory that was given to them. It's meaningless information. Always use int a = 0; to ensure you're going to get *usable* data. – Drise Sep 13 '12 at 15:46
  • @Drise But why zero is not written to value just as Prog1 and Prog2 do.I mean, what's the difference between garbage values and the `1` and `2` in Prog1 & Prog2. – user1668903 Sep 13 '12 at 15:51
  • You know, that's a very good question. One that I can't answer. I believe @james was trying to find a concrete answer. – Drise Sep 13 '12 at 15:54

3 Answers3

3

Like all istreams, std::cin has error bits. These bits are set when errors occur. For example, you can find the values of the error bits with functions like good(), bad(), eof(), etc. If you read bad input (fail() returns true), use clear() to clear the flags. You will also likely need an ignore(1); to remove the offending character.

See the State functions section for more information. http://en.cppreference.com/w/cpp/io/basic_ios

Drise
  • 4,310
  • 5
  • 41
  • 66
  • Thanks.But i'm sill wondering why the value of a and b both become 0 – user1668903 Sep 13 '12 at 14:45
  • If you read bad input, `bad()` will still return false; it's `fail()` which will return true. And the page you cite is misleadingly simplified, and simply wrong with regards to `good()` (which can return false even if no error has occurred). Throw it out, and find something better. – James Kanze Sep 13 '12 at 14:57
  • You seem to be using C++11: *If extraction fails, zero is written to value and failbit is set. **(since C++11)***. – Drise Sep 13 '12 at 14:57
  • OK,now i kown it;Thanks again:) – user1668903 Sep 13 '12 at 14:57
  • @user1668903 If both become 0, it is an error in the implementation. C++11 requires the first to become 0, and the second to be unchanged. Earlier versions of the standard required both to be unchanged. – James Kanze Sep 13 '12 at 14:59
  • Why? It's going to try to finish the statement (continue extracting), even if the stream has failed. Or at least that's how I was always taught. Source? – Drise Sep 13 '12 at 15:00
  • @Drise A quote from the standard for this, please. I'm looking at a very late draft (N3376), and that's not what it says. `num_get` is required to set the value to 0 for certain types of failure, but the implementation shouldn't change the value if `num_get` isn't called (because of a preceding error). – James Kanze Sep 13 '12 at 15:05
  • I don't have a quote, unfortunately. But I have always been under the impression that if you write `cin >> a >> b;`, it won't simply lop off `>> b` because extraction into `a` failed. It doesn't make sense that it would. And as far as I knew, `cin >> a >> b;` is synonymous with `cin >> a; cin >> b;`, which would then guarantee that the extraction is done twice, and both values get set to 0. – Drise Sep 13 '12 at 15:07
  • Since `cin >> a >> b` is essentially equivalent to `( cin.operator>>(a) ).operator>>(b)`, I would think that `fail()` should be true after the failed extraction into `a`, and that the extraction to `b` would then not even be attempted. The single clause quoted above by @Drise is ambiguous on this particular case - but other sections might apply to clarify it... Of course that assumes that an extraction operation checks the state bits before attempting anything and aborts if `fail()` is true (or others...), but that could be a false assumption. – twalberg Sep 13 '12 at 15:11
  • @twalberg Or not: The (1-7) versions of the operator behave as formatted input functions. That is, they construct a sentry object at the beginning that flushes the tie()'d buffers if needed, **checks for errors**, and extracts and discards all leading whitespace characters unless the ios_base::skipws flag was cleared. The input **is attempted only if** the sentry object returns **true**. Version 2 is `basic_istream& operator>>( int& value );` – Drise Sep 13 '12 at 15:16
3

The value is set to zero on an error as per C++11: If extraction fails, zero is written to value and failbit is set.

On the 'a 4' example, both values are 0 because the buffer has not been flush/cleared, so the second cin read is still reading the error, and also receives a value of 0.

Sogger
  • 15,962
  • 6
  • 43
  • 40
1

std::cin is an istream instance and thus it maintains its error state when it reads something invalid.

In order to "cure" it you must both clear its flag

std::cin.clear();

and flush its buffer.

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

What is more surprising though is that it doesn't return 1 + 2 = 3 when you input invalid characters, as I would expect a failing cin stream to have no side effects on what it is trying to update.

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • 2
    OP is using C++11: *If extraction fails, zero is written to value and failbit is set. **(since C++11)*** – Drise Sep 13 '12 at 14:52
  • Is this just the case with ints, or is it a general rule for user types that if streaming in fails, the object should revert to its default state? I always think streaming into an object is flawed logic. Factories create objects with data read from streams, objects don't get streamed into.. – CashCow Sep 14 '12 at 09:29
  • "*streaming into an object is flawed logic. Factories create objects with data read from streams, objects don't get streamed into*" - streaming with `operator<<` is necessarily into pre-existing objects (given the by-reference parameter), and although a factory creating a new object may fairly often be desirable, there are times when it wouldn't (e.g. when you want buffers and other resources the object already has re-used for the next value) and how would the "factory" create objects on the stack (highly desirable unless the objects are run-time polymorphic, need extended lifetime etc.)? – Tony Delroy Feb 17 '14 at 04:20
  • I tend to prefer classes to be non-intrusive and there is more than one way to serialise data. Of course having gained more experience with the library I do now know there is such a thing as a facet but it is complicated. In any case I have found in recent years I am more into creating straightforward "struct" objects that contain all the data members public, then having a "class" wrap the struct by containing a private instance of it. You can then "stream" into the struct without having to make anything a friend, and keep the encapsulation the members of the instance are still inaccessible. – CashCow Feb 17 '14 at 09:32