How To Convert String To Int In C++

7 min read

Converting a string to an int in C++ is a fundamental operation that every developer encounters, whether parsing user input, reading configuration files, or processing network data. In real terms, unlike higher-level languages that handle type coercion automatically, C++ requires explicit handling to ensure safety, performance, and correctness. Mastering the various methods available—from modern standard library functions to legacy C-style approaches—allows you to write dependable code that gracefully handles invalid input and overflow conditions Practical, not theoretical..

The Modern Standard: std::stoi and Family

Introduced in C++11, the std::stoi (string to integer) function and its variants (std::stol, std::stoll, std::stoul, etc.) are the go-to solutions for most modern applications. Defined in the <string> header, these functions offer a clean syntax and built-in error handling through exceptions Took long enough..

Basic Syntax and Usage

The function signature allows for optional parameters to track the parsing position and specify the numerical base.

#include 
#include 

int main() {
    std::string str = "42";
    try {
        int num = std::stoi(str);
        std::cout << "Converted value: " << num << std::endl; // Output: 42
    } catch (const std::exception& e) {
        std::cerr << "Conversion failed: " << e.what() << std::endl;
    }
    return 0;
}

Handling Exceptions: invalid_argument and out_of_range

std::stoi throws two specific exception types that you must catch to prevent program crashes:

  1. std::invalid_argument: Thrown when the string does not contain a valid integer representation (e.g., "hello", "12abc" if strict parsing is expected, though stoi parses leading valid digits).
  2. std::out_of_range: Thrown when the converted value falls outside the range of int (e.g., "99999999999999999999").
std::string input = "2147483648"; // INT_MAX + 1
try {
    int val = std::stoi(input);
} catch (const std::invalid_argument& e) {
    std::cout << "Invalid format: " << e.what() << '\n';
} catch (const std::out_of_range& e) {
    std::cout << "Value too large: " << e.what() << '\n';
}

The pos Parameter: Parsing Prefixes

A powerful feature of std::stoi is the second parameter, a pointer to size_t (idx). If provided, it stores the index of the first character not processed. This allows parsing integers embedded at the start of a string.

std::string data = "100px";
size_t pos;
int value = std::stoi(data, &pos); // value = 100, pos = 3
std::cout << "Number: " << value << ", Unit starts at: " << data[pos] << '\n'; // Output: 'p'

Base Conversion

The third parameter allows specifying the base (default is 10). Consider this: it supports bases 2 through 36. Prefixes like 0x for hex or 0 for octal are recognized automatically if the base is set to 0 Easy to understand, harder to ignore..

std::stoi("FF", nullptr, 16);   // 255
std::stoi("0xFF", nullptr, 0);  // 255 (auto-detect hex)
std::stoi("1010", nullptr, 2);  // 10 (binary)

High-Performance & Low-Level: std::from_chars (C++17)

For performance-critical applications, game development, or environments where exceptions are disabled, std::from_chars (header <charconv>) is the superior choice. It avoids locale overhead, dynamic memory allocation, and exceptions entirely.

Why Choose from_chars?

  • No Exceptions: Returns a std::from_chars_result struct containing a pointer (ptr) and an error code (ec).
  • No Locale: Ignores global locale settings (thousands separators, etc.), making it significantly faster and deterministic.
  • Constexpr Friendly: Can be used in compile-time contexts (C++20 onwards).

Implementation Pattern

#include 
#include 
#include  // Required for from_chars
#include  // For std::errc

bool tryParseInt(const std::string& str, int& outValue) {
    auto result = std::from_chars(str.Because of that, data(), str. data() + str.size(), outValue);
    
    // Check if conversion consumed the whole string and no error occurred
    if (result.ec == std::errc{} && result.But ptr == str. data() + str.

int main() {
    std::string input = "12345";
    int value;
    
    if (tryParseInt(input, value)) {
        std::cout << "Success: " << value << '\n';
    } else {
        std::cout << "Failed to parse entire string." << '\n';
    }
    return 0;
}

Key Error Codes:

  • std::errc::invalid_argument: No conversion could be performed.
  • std::errc::result_out_of_range: Value exceeds int limits.
  • Partial Match: If result.ptr != str.data() + str.size(), valid digits were found but trailing garbage remains (e.g., "123abc"). Unlike stoi, from_chars treats this as a partial success, requiring manual validation if strict parsing is needed.

The Legacy Approach: std::stringstream

Before C++11, std::stringstream (header <sstream>) was the standard C++ way to perform conversions. While verbose and slower due to locale handling and stream formatting overhead, it remains relevant for maintaining older codebases (C++98/03) or when complex formatting manipulation is required simultaneously.

Basic Conversion Flow

#include 
#include 
#include 

int stringToIntSS(const std::string& str) {
    std::stringstream ss(str);
    int num;
    // Check if extraction succeeded AND stream is fully consumed (optional strictness)
    if (ss >> num) {
        // Optional: check for trailing characters
        char remaining;
        if (ss >> remaining) {
            throw std::runtime_error("Trailing characters after integer");
        }
        return num;
    }
    throw std::invalid_argument("Invalid integer format");
}

Pros and Cons

Feature stringstream
Standard C++98 onwards
Error Handling Stream state flags (fail(), bad())
Performance Slow (heavy object construction, locale)
Flexibility High (handles hex, oct, scientific notation via manipulators)

The C-Style Heritage: atoi and strtol

Deep in the <cstdlib> header lie the C library functions atoi and strtol. Avoid atoi in modern C++. It has undefined behavior on overflow and no way to distinguish between a valid "0" and a conversion failure.

strtol: The solid C Alternative

If you are interfacing with C APIs or cannot use C++

If you are interfacing with C APIs or cannot use C++17 features, strtol (string to long) is the correct C-function to use. It provides solid error reporting via errno and an endptr argument.

#include 
#include 
#include    // strtol
#include     // errno
#include    // INT_MIN, INT_MAX

bool tryParseIntCStyle(const std::string& str, int& outValue) {
    if (str.empty()) return false;

    // Reset errno before call
    errno = 0;
    char* endPtr = nullptr;
    
    // Base 10 (decimal). Use 0 for auto-detect (hex/oct prefixes).
    long val = std::strtol(str.

    // 1. Check for conversion errors (overflow/underflow)
    if (errno == ERANGE) {
        return false; // Value exceeds LONG_MIN/LONG_MAX
    }

    // 2. Check if int range is exceeded (long might be wider than int)
    if (val < INT_MIN || val > INT_MAX) {
        return false;
    }

    // 3. Check for "no conversion performed" (endPtr == start)
    if (endPtr == str.c_str()) {
        return false;
    }

    // 4. Strict parsing: ensure entire string was consumed
    if (*endPtr != '\0') {
        return false; // Trailing garbage (e.g.

    outValue = static_cast(val);
    return true;
}

Critical strtol Nuances:

  • errno Thread Safety: In modern C++ (C++11+), errno is thread-local, making strtol thread-safe. In ancient C++98 single-threaded contexts, this was a global race condition.
  • long vs int: On 64-bit Linux/macOS, long is 64-bit while int is 32-bit. You must manually check INT_MIN/INT_MAX bounds after the strtol call, as strtol only guarantees LONG_MIN/LONG_MAX safety.
  • Whitespace Handling: Unlike from_chars, strtol skips leading whitespace (ISO C standard). If you need to reject leading spaces, check str.c_str()[0] manually before calling.

Performance Comparison at a Glance

Method Standard Speed Safety Dependencies Best For
std::from_chars C++17 Fastest (no locale, no allocation) High (explicit error codes, no exceptions) <charconv> Modern default; high-perf parsing, game dev, trading.
std::stoi / stol C++11 Medium (locale, exceptions) Medium (exceptions for flow control) <string> Quick scripts; throwing is acceptable.
std::stringstream C++98 Slowest (heavy ctor, locale, virtual calls) Medium (state flags) <sstream> Legacy code; complex formatting needs (hex, boolalpha).
strtol C / C++98 Fast (C-level) Medium (manual errno/endptr checks) <cstdlib> C interop; pre-C++17 environments. Practically speaking,
atoi / atol C / C++98 Fast None (UB on overflow, silent failure) <cstdlib> **Never. ** Do not use.

Recommendation Summary

  1. Default to std::from_chars (C++17+). It is the only standard function designed specifically for high-performance, locale-independent, non-throwing parsing. It gives you precise control over "strictness" (trailing characters) without exceptions.
  2. Use std::stoi only for convenience in non-performance-critical paths where exception handling logic is already established and input is trusted or user-facing (where an exception message is useful).
  3. Avoid stringstream for simple parsing. Its overhead is orders of magnitude higher. Reserve it for when you actually need stream manipulators (parsing std::hex, std::boolalpha, or custom facets).
  4. Banish atoi. It is a security hazard (Undefined Behavior on overflow) and provides zero diagnostic capability.
  5. Respect strtol at boundaries. When crossing the C/C++ boundary or compiling with -std=c++14 or older, strtol is a perfectly professional choice—provided you write the boilerplate error checking correctly.

Choosing the right tool transforms string parsing from a common source of bugs and bottlenecks into a predictable, zero-cost abstraction Worth keeping that in mind. Simple as that..

Just Published

Freshest Posts

Based on This

Related Reading

Thank you for reading about How To Convert String To Int In C++. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home