The stream extraction operator reads formatted input into an object, commonly from std::cin or a file stream. It skips leading whitespace, converts suitable characters, and stores the result in the supplied variable. section 3.1.1 section 7.3.1
Direct extraction is convenient, but input handling needs attention:
- Invalid input sets the stream's error state and leaves unused characters available for later reads. section 3.1.1
- Check success with std::cin.fail() or the idiomatic condition !(std::cin >> number). section 3.1.1
- Recover by clearing the state with clear() and discarding the bad line with ignore(). section 3.1.1
- Choose the destination type carefully: unsuitable text, oversized values, and negative values can produce unexpected results for unsigned numbers. section 3.1.1
Reliable number input
A reusable input function loops until extraction succeeds, clears the stream, ignores the invalid line, and prompts again. The same pattern supports a number-guessing game without getting stuck on bad input. section 3.1.1
Listing 3.2 Reading a number from standard input
unsigned input()
{
unsigned number;
while (!(std::cin >> number)) #1
{
std::cin.clear(); #2
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(), '\n'); #3
std::cout << "Please enter a number.\n>";
}
return number; #4
}
Inspect the complete input() pattern, including extraction, stream-state recovery, line cleanup, prompting, and the returned number. section 3.1.1
Listing 7.10 Loading a file into a multimap
#include <fstream>
#include <iostream>
#include <map>
#include <string>
std::multimap<std::string, std::string>
load_dictionary(const std::string& filename)
{
std::multimap<std::string, std::string> dictionary;
std::ifstream infile{ filename }; #1
if (infile) #1
{
std::string line;
while (std::getline(infile, line)) #2
{
size_t position = line.find(','); #3
if (position != std::string::npos)
{
std::string key{ line.substr(0, position) }; #4
key = str_tolower(key); #4
std::string value{ line.substr(position + 1) };
dictionary.emplace(key, value); #5
}
else
{
std::cout << "***Invalid line\n" << line
<< "\nin " << filename << "***\n\n";
}
}
}
else
{
std::cout << "Failed to open " << filename << '\n';
}
return dictionary;
}
Compare formatted extraction with line-based file reading in a dictionary loader that uses std::getline to process each record. section 7.3.1
