Output Operations and Chaining in C++
A single statement such as cin >> i >> d; reads several values in order, with each >> filling the variable on its right.
One Statement, Two Values
A single statement can read more than one value from the keyboard. The statement cin >> i >> d; reads two values in order, and each >> operator fills the variable on its right. In this statement, i is an int and d is a double. The question this article answers is simple to state: how does one statement with two >> operators decide which input goes where?
What do you think happens?
If the keyboard delivers the input 42 7 and the program runs cin >> i >> d;, what does i hold and what does d hold?
Reveal answer
i holds 42 and d holds 7
The chain reads from left to right. The first >> fills i with the first value, 42, and the second >> fills d with the next value, 7. Spaces between values are skipped, so they do not become part of either value.
Keep the guess you just made in mind. The rest of this article traces the read step by step, so you can check whether your expectation about the order of the values was right.
Tracing the Read Cursor Through cin >> i >> d
Think of the input as a stream of characters with a read cursor that moves forward. The chain reads from left to right, and each read begins where the previous read stopped. The first >> starts at the beginning of the input, extracts a value for i, and leaves the cursor just past that value. The second >> then starts from that position, not from the beginning again.
Skipping Whitespace Between Values
By default, >> skips initial whitespace before it reads a value. This is why spaces between values do not become part of them. Whether the input is written as 42 7, as 42 7, or with the values on separate lines, each >> first moves past the whitespace and then reads the next value.
Input: 42 7
i = 42
d = 7- std::cin >> i >> d; is one statement with two extractions, applied in order
- The first >> fills i, the second >> fills d
- Spaces between 42 and 7 are skipped and are not stored in either variable
Where an Integer Read Stops
An integer read keeps going only while the characters are digits. It is terminated by any character that is not a digit, so a period or a letter ends it. The character that ends the read is not consumed as part of the integer. It stays in the stream, and the next >> starts from that character.
The same rule applies to a decimal point. In an input such as 3.5 for an int, the integer read ends at the period, so the period is the first character left for the next operator to examine. Reading the period as a digit is not something an integer extraction does, which is why the position where an integer read ended is the key to predicting what the next value will be.
Tracing a Chained Read Step by Step
Reading three tokens with two extractions
The input is 42 7 abc, and the program runs cin >> i >> d; with i an int and d a double. What does each variable hold, and what is left in the stream?
- 1Start of the input
The cursor is at the beginning of 42 7 abc. The first >> skips any leading whitespace, and there is none here.
- 2First >> reads an int
The integer read collects 4 and 2 and stops at the space, which is not a digit. i becomes 42 and the cursor sits at the space.
- 3Second >> skips whitespace and reads a double
The second >> begins at the space from the previous step, skips it, and reads 7. d becomes 7 and the cursor sits at the space before abc.
- 4What remains
The text abc is not read by this statement. It stays in the stream for any later read.
i holds 42, d holds 7, and abc remains unread in the stream.
Finding Where a Result Diverges
When a chained read gives an unexpected value, the useful question is which >> operator produced it. Each operator in the chain has one job: it skips whitespace, reads one value, and leaves the stream positioned for the next operator. Work backward from the variable that looks wrong.
Suppose the first variable is correct but the second is wrong. Then the first read worked, and the problem lies in what the second read found after the first one stopped. Look at the characters that remained after the first integer ended. If the first variable is already wrong, look at the start of the input and at the first run of digits, because that is where the first read began.
Mistakes Beginners Make With Chained Reads
Common mistake Assuming the second value is read from the start of the input
What it looks likeAfter cin >> i >> d; with input 42 7, expecting d to read 42 again.
Why it failsEach >> begins where the previous read stopped, so the chain moves forward through the input.
Do this insteadTrace the cursor forward: the first read consumes 42, and the second read starts after it.
Common mistake Expecting a digit-run to include a following letter or period
What it looks likeReading 42x7 into an int and expecting i to hold 427.
Why it failsAn integer read is terminated by any character that is not a digit, so the x ends the read.
Do this insteadRead digits up to the first non-digit only, and leave the terminating character in the stream.
Common mistake Thinking spaces between values become part of the values
What it looks likeBelieving the input 42 7 gives i a value containing a space.
Why it failsBy default >> skips initial whitespace, so spaces between values are not stored.
Do this insteadTreat whitespace as a separator that each >> skips before reading.
Common mistake Forgetting that unread characters remain in the stream for later reads
Practice: Predicting the Split
The program declares int i; and double d; and runs cin >> i >> d; The keyboard delivers the input 15 2.5 extra. Before you check, predict the value of i and the value of d, and say where the read cursor sits after the statement finishes.
Hints
- Trace the first >> from the start of the input, stopping at the first character that is not a digit.
- The second >> begins at the character where the first read stopped.
- The text extra is never read by this statement.
Key Takeaways
- A statement such as cin >> i >> d; reads several values in order, with each >> filling the variable on its right.
- The chain reads from left to right, and each read begins where the previous read stopped.
- An integer read is terminated by any character that is not a digit, such as a period or a letter, and that character stays in the stream.
- By default >> skips initial whitespace, so spaces between values do not become part of the values.
- When a result is wrong, identify which >> produced it: a wrong first variable points to the start of the input, while a wrong second variable points to what remained after the first read.