Understanding std::strtoumax for String-to-Unsigned Integer Conversion in C++


What it does

  • It interprets the characters in the string according to a specified base (radix).
  • std::strtoumax is a function in the C++ standard library (<cinttypes>) that converts a string representation of a number to an unsigned integer of the maximum width (uintmax_t).

Syntax

uintmax_t std::strtoumax(const char* str, char** endptr, int base);

Parameters

  • base (optional): The base (radix) in which the string is represented. If not provided, it defaults to 10 (decimal). Valid bases are from 2 to 36.
  • endptr (optional): A pointer to a character pointer. Upon successful conversion, endptr will point to the first character in the string that was not part of the valid number representation. If endptr is nullptr, it's ignored.
  • str: A null-terminated character array containing the string to be converted.

Return value

  • If an error occurs (e.g., invalid characters, out-of-range value), it returns zero (0) and sets errno to indicate the specific error.
  • If the conversion is successful, it returns the converted unsigned integer value.

Key points

  • If the string is empty or contains only non-numeric characters, std::strtoumax returns zero and sets errno to EINVAL (invalid argument).
  • Leading whitespace (spaces, tabs, newlines) is skipped before conversion begins.
  • Valid digits depend on the base:
    • For bases 2 to 10, digits are 0 to 9.
    • For bases 11 to 36, digits include 0 to 9 and uppercase or lowercase letters from A to Z (depending on the implementation).
  • The string can optionally start with a plus (+) or minus (-) sign, but std::strtoumax only handles unsigned integers, so the sign is ignored.

Example

#include <iostream>
#include <cinttypes>

int main() {
    char str[] = "1234";
    uintmax_t value;
    char* endptr;

    value = std::strtoumax(str, &endptr, 10); // Convert to decimal (base 10)

    if (value != 0) {
        std::cout << "Converted value (decimal): " << value << std::endl;
        std::cout << "Character after parsed number: " << *endptr << std::endl;
    } else {
        std::cerr << "Error: Conversion failed." << std::endl;
    }

    return 0;
}

This code will output:

Converted value (decimal): 1234
Character after parsed number: 
  • Consider using a wrapper function that throws an exception (std::invalid_argument) on error for better error handling practices.
  • Always check the return value and errno to ensure successful conversion.


Converting a hexadecimal string

#include <iostream>
#include <cinttypes>

int main() {
    char str[] = "FF0A";
    uintmax_t value;
    char* endptr;

    value = std::strtoumax(str, &endptr, 16); // Convert to hexadecimal (base 16)

    if (value != 0) {
        std::cout << "Converted value (hexadecimal): 0x" << std::hex << value << std::endl;
        std::cout << "Character after parsed number: " << *endptr << std::endl;
    } else {
        std::cerr << "Error: Conversion failed (invalid hexadecimal string)." << std::endl;
    }

    return 0;
}

This code converts the string "FF0A" (hexadecimal for 65226) and prints the result in both decimal and hexadecimal format.

Handling conversion errors

#include <iostream>
#include <cinttypes>
#include <cerrno>

int main() {
    char str1[] = "1234";
    char str2[] = "invalid_string";
    uintmax_t value;
    char* endptr;

    // Successful conversion
    value = std::strtoumax(str1, &endptr, 10);
    if (value != 0) {
        std::cout << "Converted value (decimal): " << value << std::endl;
    }

    // Error handling (invalid string)
    value = std::strtoumax(str2, &endptr, 10);
    if (value == 0 && errno == EINVAL) {
        std::cerr << "Error: Invalid string for conversion." << std::endl;
    } else {
        std::cerr << "Unexpected error during conversion." << std::endl;
    }

    return 0;
}

This code demonstrates how to check for specific errors using errno. It shows successful conversion and then handles the case where the string "invalid_string" cannot be converted to a number.

#include <iostream>
#include <cinttypes>

int main() {
    char str[] = "4294967295"; // Maximum value for a 32-bit unsigned integer
    uintmax_t value;

    value = std::strtoumax(str, nullptr, 10); // Ignore endptr

    if (value != 0) {
        std::cout << "Converted value (decimal): " << value << std::endl;
    } else {
        std::cerr << "Error: Conversion failed (potentially out-of-range value)." << std::endl;
    }

    return 0;
}


std::stoul (C++11 and later)

  • Syntax: unsigned int value = std::stoul(str, &endptr, base);
  • It offers similar functionality to std::strtoumax but provides more type flexibility.
  • Introduced in C++11, std::stoul is a more generic function that can convert strings to various unsigned integer types (unsigned int, unsigned long, etc.) based on the size of the result.

Custom string parsing

  • This involves iterating through the string, checking each character for validity based on the desired base, and accumulating the result into the desired unsigned integer type.
  • If you need more control over the conversion process or have specific validation requirements, you can write your own string parsing function.

Third-party libraries

  • For complex parsing requirements or custom validation, a custom parsing function or a third-party library might be more suitable.
  • For basic conversion with flexibility in result type, std::stoul is a good choice.
AlternativeDescriptionAdvantagesDisadvantages
std::stoul (C++11+)More generic conversion to various unsigned typesType flexibility, simpler to use than custom parsingLess control over parsing process compared to custom
Custom parsingUser-defined logic for string parsingHighly customizable, can perform specific validationMore complex to implement, requires careful error handling
Third-party librariesLibraries offering parsing functionalitiesAdditional features like error handling, advanced parsingMight introduce additional dependencies