C/C++ Arena

Step 6 of 6

Challenge: operator>> for your own type

You've seen that operator<< teaches std::cout to print your types. The reverse, operator>>, teaches any input stream to read them. Once it exists, std::cin >> p, file >> p and while (in >> p) all just work.

The conventions for a good operator>>:

  1. Take the stream and the target by reference, and return the stream, so reads can be chained: in >> a >> b.
  2. Read into temporaries first, and only change the target when the whole value was read correctly.
  3. If the text is malformed, call in.setstate(std::ios::failbit). That makes the stream convert to false, which stops while (in >> x) loops, just like reading abc into an int would.
#include <iostream>
#include <sstream>

struct Time {
    int h = 0, m = 0;
};

std::istream& operator>>(std::istream& in, Time& t) {
    int h, m;
    char colon;
    if (in >> h >> colon >> m && colon == ':' && h >= 0 && h < 24 && m >= 0 && m < 60) {
        t = {h, m};
    } else {
        in.setstate(std::ios::failbit);
    }
    return in;
}

int main() {
    std::istringstream in("9:30 13:05 25:00 18:00");
    Time t;
    int total = 0;
    while (in >> t) {
        std::cout << "read " << t.h << "h" << t.m << "\n";
        total += t.h * 60 + t.m;
    }
    std::cout << "minutes " << total << ", stopped early: " << !in.eof() << "\n";
}
read 9h30
read 13h5
minutes 1355, stopped early: 1

Reading the example

The format for your task

Your Point uses the text (x,y). The same recipe applies: read into temporaries, check every piece of punctuation, and only then assign.

char open, comma, close;
int x, y;
if (in >> open >> x >> comma >> y >> close && open == '(' && comma == ',' && close == ')') {
    p = {x, y};
} else {
    in.setstate(std::ios::failbit);
}
return in;

Chars and whitespace

in >> ch for a char skips spaces first and then reads one character. So ( 3 , 4 ) with spaces would also parse with the pattern in your task, which is usually what you want. When checking punctuation, compare every character you read: accepting [3,3] as a point would be a bug.

Your turn: write operator>> for Point using the (x,y) format above. The provided main reads points until one fails, then prints the path length (sum of Manhattan distances between consecutive points) and whether the input ended cleanly.

Previous: Writing files with ofstream