A question about cin (two calls for one input?)

139 views Asked by At

I'm dealing with C++ a bit and am following an introduction in which this code snippet makes me wonder a bit:

cout << "\nPlease enter an article label: ";

// Input the label (15 characters maximum):
cin >> setw(16);       // or: cin.width(16);
cin >> label;

The authors don't tell me why for one input line I need (or can use) two times cin, one with the manipulator and one with the place to modify?

Now, in chapter 4 about streams, according to what I've read up to now, I would have expected that these are two separate instances and therefore actions performed. Therefore, at my naive stage, I would have written:

cin >> setw(16) >> label;  // according to: cout << setw(16) << label;

Could you explain to me, why two times cin result in just one input line? It seems, that the proposed similar questions here are not similar enough - after checking them.

I can simply accept and reproduce it. But I would like to understand it.

Is it just because in the first line with cin there is no place to write the input two thus it creates the field and which then is "used" from the cin in the second line? And if so, is there a good reason for splitting it in two lines like this?

2

There are 2 answers

7
Ted Lyngmo On
cin >> setw(16);
cin >> label;

Performs the same as:

cin >> setw(16) >> label;

It works like this:

  • cin >> setw(16) is performed first.

    setw(16) creates an implementation-defined object that holds the value 16. This object is then passed to an overloaded operator>> that takes in cin and that object, assigns the object's value to istream::width(), and then returns the istream& that was passed in, which is our cin.

    Something to the effect of this:

    struct _setw_type { int value; }
    
    _setw_type std::setw(int value) { return {value}; }
    
    std::istream& operator>>(std::istream& stream, const _setw_type &obj) {
        stream.width(obj.value);
        return stream;
    } 
    
    // cin >> setw(16) is the same as
    // operator>>(cin, setw(16))
    
  • After that, the next operation to deal with is label, and since cin was returned from the first operation, what's left is simply:

    cin >> label
    
0
Clifford On

The "two calls" are to std::ifstream::operator>> (in fact two different overloads of that function name). cin is not a "call" it is an istream object upon which the >> operation is performed twice.

Both the two statement and single statement form have the same ultimate effect on the cin object. >> is an operator and splitting the expression into two statements is no different than say transforming:

a += b + c ;

to

a += b ;
a += c ;

in that any expression involving more than one operator can be split into sub-expressions.