Step 4 of 7
A Result type
optional says that something failed, but not why. When there are several ways to fail, the caller (and the user reading an error message) needs to know which one happened. A small Result type carries either a value or an error description. C++23 standardizes the idea as std::expected<T, E>; you'll often see hand-written versions like this one.
#include <iostream>
#include <optional>
#include <string>
struct AgeResult {
std::optional<int> value;
std::string error;
bool ok() const { return value.has_value(); }
};
AgeResult parse_age(const std::string& s) {
if (s.empty()) return {std::nullopt, "empty"};
int v = 0;
for (char c : s) {
if (c < '0' || c > '9') return {std::nullopt, "not a number"};
v = v * 10 + (c - '0');
if (v > 150) return {std::nullopt, "unrealistic"};
}
return {v, ""};
}
int main() {
for (const char* in : {"42", "", "4x", "999"}) {
AgeResult r = parse_age(in);
if (r.ok()) std::cout << "'" << in << "' -> " << *r.value << "\n";
else std::cout << "'" << in << "' -> error: " << r.error << "\n";
}
}
'42' -> 42
'' -> error: empty
'4x' -> error: not a number
'999' -> error: unrealistic
How it works
- Each failure returns immediately with its own message. The checks run in order, so decide which error wins when several apply. Here an empty string is reported as "empty", not "not a number".
return {v, ""};builds the struct from braces: first the optional, then the error.v > 150is checked inside the loop, as soon as the number gets too big. Checking only at the end could overflowinton a very long string of digits first.
Your task: money
The same structure, in this order: check the leading $ (also catches the empty string), then check there's at least one character after it, then check that every character after it is a digit while building the value, then compare with the cap. Checking the cap inside the loop protects you from overflow on inputs like $99999999999.
Your turn: write Result parse_money(const std::string& s) for amounts like "$2700":
- no leading
$gives error"missing quot; - nothing after the
$, or a non-digit character, gives"not a number" - more than 16000 gives
"over the cap" - otherwise the value