What is the difference between std::atoi() and std::stoi?
Categories:
std::atoi() vs. std::stoi(): Understanding C++ String-to-Integer Conversions

Explore the key differences between std::atoi()
and std::stoi()
in C++, including error handling, return types, and C++11 features, to make informed choices in your code.
Converting strings to integer types is a common task in C++ programming. Two primary functions often come up in this context: std::atoi()
and std::stoi()
. While both serve the purpose of converting a string representation of a number into an integer, they differ significantly in their behavior, especially concerning error handling, return types, and the C++ standard they belong to. Understanding these distinctions is crucial for writing robust and modern C++ code.
std::atoi(): The C-style Legacy
std::atoi()
is a function inherited from the C standard library (<cstdlib>
). It takes a C-style string (const char*
) as input and attempts to convert it to an int
. Its simplicity comes at a cost, particularly in error handling.
#include <cstdlib> // For std::atoi
#include <iostream>
int main() {
const char* str1 = "12345";
const char* str2 = "-678";
const char* str3 = "abc";
const char* str4 = "9876543210"; // Exceeds int range on some systems
int num1 = std::atoi(str1);
int num2 = std::atoi(str2);
int num3 = std::atoi(str3);
int num4 = std::atoi(str4);
std::cout << "str1: " << num1 << std::endl; // Output: 12345
std::cout << "str2: " << num2 << std::endl; // Output: -678
std::cout << "str3: " << num3 << std::endl; // Output: 0 (no error indication)
std::cout << "str4: " << num4 << std::endl; // Output: INT_MAX or INT_MIN (undefined behavior/overflow)
return 0;
}
Basic usage of std::atoi()
std::atoi()
is its lack of robust error handling. If the input string cannot be converted to an integer (e.g., it contains non-numeric characters), std::atoi()
returns 0
without any indication of an error. This makes it impossible to distinguish between a valid input of "0" and an invalid input. For overflow, the behavior is undefined.std::stoi(): The Modern C++ Approach
Introduced in C++11, std::stoi()
(string to integer) is part of the <string>
header and offers a more modern and safer way to convert std::string
objects to integers. It provides robust error handling through exceptions and allows for more control over the conversion process.
#include <string> // For std::stoi
#include <iostream>
int main() {
std::string str1 = "12345";
std::string str2 = "-678";
std::string str3 = "abc";
std::string str4 = "2147483647"; // Max int value
std::string str5 = "2147483648"; // Exceeds max int value
try {
int num1 = std::stoi(str1);
int num2 = std::stoi(str2);
std::cout << "str1: " << num1 << std::endl; // Output: 12345
std::cout << "str2: " << num2 << std::endl; // Output: -678
// Example of invalid argument
int num3 = std::stoi(str3);
std::cout << "str3: " << num3 << std::endl;
} catch (const std::invalid_argument& e) {
std::cerr << "Invalid argument for str3: " << e.what() << std::endl; // Output: Invalid argument...
} catch (const std::out_of_range& e) {
std::cerr << "Out of range for str3: " << e.what() << std::endl;
}
try {
int num4 = std::stoi(str4);
std::cout << "str4: " << num4 << std::endl; // Output: 2147483647
// Example of out of range
int num5 = std::stoi(str5);
std::cout << "str5: " << num5 << std::endl;
} catch (const std::invalid_argument& e) {
std::cerr << "Invalid argument for str5: " << e.what() << std::endl;
} catch (const std::out_of_range& e) {
std::cerr << "Out of range for str5: " << e.what() << std::endl; // Output: Out of range...
}
return 0;
}
Robust error handling with std::stoi()
std::stoi()
can also take an optional size_t* idx
argument to report the number of characters successfully parsed, and an optional int base
argument for specifying the numerical base (e.g., 10 for decimal, 16 for hexadecimal).Key Differences and When to Use Which
The choice between std::atoi()
and std::stoi()
largely depends on your C++ standard, error handling requirements, and the type of string you are working with (const char*
vs. std::string
).
flowchart TD A[Start] A --> B{Input String Type?} B -->|`const char*`| C[Error Handling Critical?] C -->|No| D[Use `std::atoi()`] C -->|Yes| E[Convert to `std::string` then use `std::stoi()`] B -->|`std::string`| F[Error Handling Critical?] F -->|Yes| G[Use `std::stoi()` with `try-catch`] F -->|No (e.g., guaranteed valid input)| H[Use `std::stoi()` (less common without `try-catch`)] D --> I[End] E --> I[End] G --> I[End] H --> I[End]
Decision flow for choosing between std::atoi()
and std::stoi()
Here's a summary of their main differences:

Comparison of std::atoi()
and std::stoi()
std::stoi()
is almost always the preferred choice due to its type safety, robust error handling, and ability to work directly with std::string
objects. std::atoi()
should generally be avoided unless you are working with legacy code or in environments where exceptions are strictly forbidden and you have other means of validating input.