Summary
Input is the boundary through which the world enters a program, and the world does not respect specifications. This lesson teaches how to read without trusting: how to read whole lines with std::getline and avoid the empty line that appears when it is mixed with >>; how to query the state of a stream and use it to distinguish three situations that the lesson Input, output and errors only saw jumbled together (invalid input, the number that does not fit and the end of the data); how to recover from a failed read with clear and ignore; and, as the safest approach, how to read each item as text and convert it with std::from_chars, accepting it only if the conversion consumed the whole text. It ends with a function readInt, with its contract, that the rest of the course can reuse.
Learning objectives
- Read whole lines with
std::getline, explain why agetlinethat follows a read with>>returns an empty line, and avoid it withstd::ws. - Query the state of a stream after a read with
fail()andeof(), and use it to distinguish invalid input, a number that does not fit in its type and the end of the input. - Write a reading loop that recovers from invalid input with
clearandignore, and that ends if the input runs out. - Validate a number read as text with
std::from_chars, requiring that there be no error and that the whole string be consumed, and encapsulate the validation in functions with contracts.
The boundary, once more
The lesson Input, output and errors established three facts about std::cin >> n: the read stops, without consuming it, at the first character that cannot continue the number; if it manages to read none, the stream is left in an error state and every subsequent read does nothing; and if (std::cin) tells whether something failed. The lesson Loops added that the condition while (std::cin >> value) ends both when the input runs out and when invalid input arrives. Now, with those tools a program detects that something went wrong, but it does not know what, nor can it do anything but give up.
This lesson starts from a design principle, that of defensive programming at the boundary: every item that comes in is validated before it is used, and the program that validates it distinguishes invalid input, which admits a correction (asking for it again, skipping it, reporting it), from the end of the data, which does not. If this is so, three things are needed: reading the item as it was written, that is, a line; knowing why a read failed; and giving the stream back its ability to read.
Loading the content…
Completed
Sign in to save your progress