Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Parse decimal from stream into uint8_t

Tags:

c++

iostream

Is there a way to do the following directly using stream operators?

uint8_t actual;
uint32_t temporary;
std::cin >> std::dec >> temporary;
if (temporary > UINT8_MAX) {
  // error
}
actual = static_cast<uint8_t>(temporary);

In particular, I would like to parse a sufficiently small decimal number into a uint8_t without resorting to a larger temporary variable.

like image 585
Franz Miltz Avatar asked Feb 03 '26 11:02

Franz Miltz


1 Answers

No, I don't think there is a way to read a number directly into unsigned char with a std::istream (std::num_get::get doesn't support unsigned char)

You could encapsulate it into a function:

inline std::uint8_t read_uint8(std::istream& is) {
    unsigned short temporary;
    is >> temporary;
    if (!is) return -1;
    if (temporary > UINT8_MAX) {
        is.setstate(std::ios_base::failbit);
        return -1;
    }
    return std::uint8_t(temporary);
}


int main() {
    std::uint8_t actual = read_uint8(std::cin);
    if (!std::cin) {
        // error
    }
}

Or you can do something like what std::put_money or std::osyncstream does and wrap one of the arguments to call a custom operator>>:

struct read_uint8 {
    std::uint8_t& v;
    read_uint8(std::uint8_t& v) : v(v) {}
};

inline std::istream& operator>>(std::istream& is, read_uint8 v) {
    unsigned short temporary;
    is >> temporary;
    if (is) {
        if (temporary > UINT8_MAX) {
            is.setstate(std::ios_base::failbit);
        } else {
            v.v = std::uint8_t(temporary);
        }
    }
    return is;
}

int main() {
    std::uint8_t actual;
    if (!(std::cin >> read_uint8(actual))) {
        // error
    }
}
like image 177
Artyer Avatar answered Feb 06 '26 01:02

Artyer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!