When you use >>
to extract a value from an istream
, the original stream is returned from the expression. This mean you can replace this code ...
std::cin >> i1;
std::cin >> i2;
with this code:
std::cin >> i1 >> i2;
The result of that expression is again the original istream
, and when used in a boolean context, returns false
if the stream is in a “fail” state. Thus, we can read the two integers and test if that was successful in one simple construct:
if( std::cin >> i1 >> i2 ) {
std::cout << i1 << "\n" << i2 << "\n";
} else {
The above stream will enter a fail state, when it is trying to read an integer and encounters a non-integer character, such as the vertical pipe. To test for this, we need to first clear the error state, then see what character was in the stream that caused the integer read to fail. We can do this by peeking at what the next character is.
} else {
std::cin.clear(); // reset the fail state
if (std::cin.peek() == '|') {
std::cout << "Found end of input marker (|)\n";
} else {
std::cout << "Invalid input!";
}
After determining whether it was the vertical pipe or not, it is wise to clear out all characters in the stream up to the end of the input line.
// skip all characters in the stream up to the end of the current line.
std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
}
Put the above code in a loop, add a break
statement when the vertical pipe is found, and you will be looping, reading integer values in pairs, until you type in the |
.
while ( !std::cin.eof() ) {
if( std::cin >> i1 >> i2 ) {
std::cout << i1 << "\n" << i2 << "\n";
} else {
std::cin.clear(); // reset the fail state
if (std::cin.peek() == '|') {
std::cout << "Found end of input marker (|)\n";
break;
} else {
std::cout << "Invalid input!";
}
// skip all characters in the stream up to the end of the current line.
std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
}
}