Step 1 of 6
Parsing with istringstream
std::cin reads from the keyboard (or piped input). But a lot of text you need to parse is already sitting in a std::string: a line you just read, a command, a config value. A std::istringstream (from <sstream>) wraps a string so you can read from it exactly like std::cin.
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string line;
while (std::getline(std::cin, line)) {
std::istringstream in(line);
std::string item;
int qty;
double price;
if (!(in >> item >> qty >> price)) {
std::cout << "skipping bad line: [" << line << "]\n";
continue;
}
std::cout << item << " costs " << qty * price << "\n";
}
}
pen 3 1.5
oops
book 2 12
pen costs 4.5
skipping bad line: [oops]
book costs 24
Why read a line first?
std::cin >> x skips over newlines, so it can't tell where one line ends and the next begins. When the line structure matters (one record per line, a variable number of values per line), use this two-step pattern:
std::getline(std::cin, line)reads one whole line into a string (without the newline).- A fresh
std::istringstream in(line)parses just that line. When it runs out, you know the line is done.
Reading until the data runs out
A stream converts to false once a read fails. So this loop reads every number on a line, however many there are, including zero:
int x;
while (in >> x) { /* use x */ }
The loop also stops at something that isn't a number, like the word abc.
Common mistakes
- Reusing one
istringstreamfor several lines. After it hits the end, it's in a failed state. Create a new one inside the loop, as above. - Mixing
std::cin >> nwithstd::getline. The>>leaves the newline behind, so the nextgetlinereturns an empty line.
Your turn: each input line holds a player name followed by some round scores (possibly none). For each line print NAME TOTAL.