C/C++ Arena

Step 5 of 7

Strict number parsing with from_chars

Parsing numbers from untrusted input (files, network messages, user typing) is where many programs go wrong. The older tools each have a problem:

std::from_chars from <charconv> has none of these problems: no exceptions, no locale, no allocation, and precise error reporting. It's also the fastest parser in the standard library.

#include <charconv>
#include <iostream>
#include <string_view>

void check(std::string_view s) {
    int v = 0;
    auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), v);
    std::cout << "'" << s << "': ";
    if (ec == std::errc::invalid_argument) std::cout << "no number\n";
    else if (ec == std::errc::result_out_of_range) std::cout << "too big for int\n";
    else if (ptr != s.data() + s.size()) std::cout << v << " but junk after it: '" << ptr << "'\n";
    else std::cout << "ok " << v << "\n";
}

int main() {
    check("123");
    check("-45");
    check("12abc");
    check("abc");
    check("99999999999");
    check(" 7");
}
'123': ok 123
'-45': ok -45
'12abc': 12 but junk after it: 'abc'
'abc': no number
'99999999999': too big for int
' 7': no number

How it works

(Printing ptr works in this example only because the string literals end in '\0'. A general string_view isn't guaranteed to.)

Your turn: write std::optional<int> to_int(std::string_view s) that accepts only a complete, in-range integer (optional leading -, no spaces, no junk).

Previous: Measuring time Next: Random numbers with <random>