На C++ преобразование строк в целые числа — это обычная задача, благодаря std::stoi она упрощается. Изучим, как эффективно применять эту функцию и справляться со всеми пограничными случаями в реальных приложениях.
Базовое применение std::stoi
Вот основной синтаксис:
#include <string>
#include <iostream>
int main() {
std::string number_str = "42";
int number = std::stoi(number_str);
std::cout << "Converted number: " << number << '\n'; // Выводится: 42
// Также для работы со строковыми литералами
int another_number = std::stoi("123");
std::cout << "Another number: " << another_number << '\n'; // Выводится: 123
}
Работа с различными числовыми форматами
std::stoi справляется с разными числовыми форматами:
#include <string>
#include <iostream>
void demonstrate_formats() {
// Десятичные числа с основанием «10»
int regular = std::stoi("123"); // 123
// Шестнадцатеричные числа с основанием «16»
int hex = std::stoi("0x1A", nullptr, 16); // 26
int hex2 = std::stoi("1A", nullptr, 16); // 26 с необязательным префиксом «0x»
// Восьмеричные числа с основанием «8»
int octal = std::stoi("073", nullptr, 8); // 59
// Двоичные числа с основанием «2»
int binary = std::stoi("1010", nullptr, 2); // 10
std::cout << "Regular: " << regular << '\n'
<< "Hex: " << hex << '\n'
<< "Octal: " << octal << '\n'
<< "Binary: " << binary << '\n';
}
Обработка ошибок в реальных приложениях
Вот корректная обработка ошибок преобразования:
#include <string>
#include <stdexcept>
class NumberConverter {
public:
static int safe_string_to_int(const std::string& str, int default_value = 0) {
try {
size_t pos;
int result = std::stoi(str, &pos);
// Проверяется, вся ли строка преобразована
if (pos != str.length()) {
std::cout << "Warning: Only converted part of the string\n";
}
return result;
}
catch (const std::invalid_argument&) {
std::cout << "Error: String '" << str << "' is not a valid number\n";
return default_value;
}
catch (const std::out_of_range&) {
std::cout << "Error: Number '" << str << "' is too large or small\n";
return default_value;
}
}
};
// Пример использования
void process_user_input() {
std::string inputs[] = {
"123", // Валидное число
"abc", // Невалидное
"12345678901234567890", // Слишком большое
"123abc", // Частичное число
"-456" // Отрицательное число
};
for (const auto& input : inputs) {
int result = NumberConverter::safe_string_to_int(input);
std::cout << "Input: " << input << " -> Result: " << result << '\n';
}
}
Реальный пример: синтаксический анализатор конфигурационных файлов
Вот практический пример использования std::stoi в синтаксическом анализаторе конфигурации:
#include <string>
#include <fstream>
#include <map>
class ConfigParser {
private:
std::map<std::string, int> settings_;
public:
bool load_config(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
return false;
}
std::string line;
while (std::getline(file, line)) {
// Пустые строки и комментарии пропускаются
if (line.empty() || line[0] == '#') {
continue;
}
// Находится знак равенства
size_t pos = line.find('=');
if (pos == std::string::npos) {
continue;
}
std::string key = line.substr(0, pos);
std::string value = line.substr(pos + 1);
// Пробел удаляется
key.erase(0, key.find_first_not_of(" \t"));
key.erase(key.find_last_not_of(" \t") + 1);
value.erase(0, value.find_first_not_of(" \t"));
value.erase(value.find_last_not_of(" \t") + 1);
try {
settings_[key] = std::stoi(value);
}
catch (const std::exception& e) {
std::cout << "Warning: Invalid value for " << key << ": " << value << '\n';
}
}
return true;
}
int get_setting(const std::string& key, int default_value = 0) const {
auto it = settings_.find(key);
return (it != settings_.end()) ? it->second : default_value;
}
};
// Пример использования
void handle_config() {
ConfigParser parser;
if (parser.load_config("settings.conf")) {
int port = parser.get_setting("port", 8080);
int max_connections = parser.get_setting("max_connections", 100);
int timeout = parser.get_setting("timeout", 30);
std::cout << "Port: " << port << '\n'
<< "Max connections: " << max_connections << '\n'
<< "Timeout: " << timeout << '\n';
}
}
Обработка аргументов командной строки
А так std::stoi используется с аргументами командной строки:
#include <string>
#include <vector>
class ArgumentParser {
private:
std::vector<std::string> args_;
public:
ArgumentParser(int argc, char* argv[]) {
for (int i = 1; i < argc; ++i) {
args_.push_back(argv[i]);
}
}
int get_int_option(const std::string& option, int default_value = 0) const {
for (size_t i = 0; i < args_.size() - 1; ++i) {
if (args_[i] == option) {
try {
return std::stoi(args_[i + 1]);
}
catch (const std::exception& e) {
std::cout << "Warning: Invalid value for " << option << '\n';
return default_value;
}
}
}
return default_value;
}
};
// Пример использования
int main(int argc, char* argv[]) {
ArgumentParser parser(argc, argv);
int count = parser.get_int_option("--count", 1);
int delay = parser.get_int_option("--delay", 500);
std::cout << "Count: " << count << '\n'
<< "Delay: " << delay << '\n';
return 0;
}
Работа с целочисленными типами
std::stoi — не единственная функция преобразования строки в число:
#include <string>
#include <limits>
void number_type_conversion() {
std::string num = "42";
// Различные целочисленные типы
int i = std::stoi(num); // «int»
long l = std::stol(num); // «long»
long long ll = std::stoll(num); // «long long»
// Беззнаковые версии
unsigned long ul = std::stoul(num); // беззнаковый «long»
unsigned long long ull = std::stoull(num); // беззнаковый «long long»
// Пример проверки диапазона
try {
std::string large_num = "999999999999999999999";
int val = std::stoi(large_num); // Выбросится «out_of_range»
}
catch (const std::out_of_range&) {
std::cout << "Number too large for int, try using stoll\n";
long long val = std::stoll(large_num); // Возможна работа с «long long»
}
}
Типичные проблемы и их решения
- Начальный/конечный пробел:
std::string str = " 42 ";
size_t pos;
int num = std::stoi(str, &pos); // Беспроблемная работа, начальный пробел игнорируется
std::cout << "Number: " << num << ", Position: " << pos << '\n';
2. Частичное преобразование:
bool is_valid_integer(const std::string& str) {
try {
size_t pos;
std::stoi(str, &pos);
return pos == str.length(); // «True», если преобразована вся строка
}
catch (const std::exception&) {
return false;
}
}
3. Выявление основания:
int detect_and_convert(const std::string& str) {
try {
if (str.substr(0, 2) == "0x" || str.substr(0, 2) == "0X") {
return std::stoi(str, nullptr, 16);
}
if (str[0] == '0') {
return std::stoi(str, nullptr, 8);
}
return std::stoi(str);
}
catch (const std::exception& e) {
std::cout << "Conversion error: " << e.what() << '\n';
return 0;
}
}
Не забывайте, что std::stoi является частью стандарта C++11 и более поздних версий. Для более старых кодовых баз понадобятся альтернативы вроде std::atoi или std::stringstream, но в современном C++ благодаря обработке ошибок и гибкости std::stoi в целом предпочтительнее.
Читайте также:
- C++: полное руководство по memset
- C++: полное руководство по explicit
- Спецификатор constexpr в C++: зачем он нужен и как работает
Читайте нас в Telegram, VK и Дзен
Перевод статьи ryan: std::stoi in C++: Complete Guide




