Avatar ·

Как преобразовать std::string в int в C++?

Всем привет! Я новичок в C++ и пишу простую программку, которая читает число из файла и выполняет с ним арифметические операции. У меня есть std::string, содержащая числовое значение, например, "123". Мне нужно превратить эту строку в int, чтобы я мог сложить её с другой переменной. Проблема в том, что я не могу просто написать int number = myString; — компилятор выдаёт ошибку. Я пробовал использовать stoi(), но не уверен, что это правильный способ, особенно если в строке могут быть лишние символы (например, пробелы или буквы). Также я слышал, что есть atoi(), но говорят, что он устаревший и опасный. Подскажите, пожалуйста, как правильно и безопасно конвертировать std::string в int в современном C++ (желательно C++11 и новее)? Нужен пример с обработкой ошибок, чтобы программа не падала, если строка содержит невалидные данные. Заранее спасибо! Вот мой текущий код, который не работает: ```cpp #include #include int main() { std::string s = "456"; int num = s; // ошибка компиляции std::cout << num + 10 << std::endl; return 0; } ``` <<>>

Использование std::stoi с обработкой ошибок

В современном C++ (C++11 и новее) лучший способ преобразовать std::string в int — это функция std::stoi. Она является частью заголовочного файла <string> и предоставляет встроенную обработку ошибок через исключения. В отличие от устаревшей atoi, которая просто возвращает 0 при ошибке (что не позволяет отличить "0" от ошибки), stoi генерирует исключения:

  • std::invalid_argument — если строка не содержит чисел в начале.
  • std::out_of_range — если число выходит за пределы диапазона int.

Кроме того, stoi принимает необязательный второй параметр — указатель на size_t, который сохраняет позицию первого символа, не участвующего в преобразовании. Это позволяет проверить, вся ли строка была преобразована.

Пример с полной обработкой ошибок

#include <iostream>
#include <string>
#include <stdexcept>  // для исключений

int stringToInt(const std::string& str) {
    try {
        size_t pos = 0;
        int result = std::stoi(str, &pos);
        
        // Проверяем, что вся строка была преобразована
        if (pos != str.length()) {
            throw std::invalid_argument("Строка содержит лишние символы");
        }
        return result;
    }
    catch (const std::invalid_argument& e) {
        std::cerr << "Ошибка: неверный формат строки: " << e.what() << std::endl;
        return 0; // или другое значение по умолчанию
    }
    catch (const std::out_of_range& e) {
        std::cerr << "Ошибка: число выходит за пределы диапазона int: " << e.what() << std::endl;
        return 0;
    }
}

int main() {
    std::string s1 = "456";
    std::string s2 = "123abc";   // содержит буквы
    std::string s3 = "9999999999999"; // слишком большое число
    
    int num1 = stringToInt(s1);
    std::cout << "num1 + 10 = " << num1 + 10 << std::endl; // 466
    
    int num2 = stringToInt(s2); // выведет ошибку
    std::cout << "num2 = " << num2 << std::endl; // 0
    
    int num3 = stringToInt(s3); // выведет ошибку
    std::cout << "num3 = " << num3 << std::endl; // 0
    
    return 0;
}

Как это работает

Функция stoi пропускает начальные пробелы, затем пытается преобразовать как можно больше символов в число. Параметр pos после вызова содержит индекс первого символа, который не был частью числа. Если pos < str.length(), значит, в строке есть "хвост" из нецифровых символов — это можно считать ошибкой (в зависимости от требований).

Альтернативы

  • std::stringstream — более старый, но гибкий способ. Подходит для сложных сценариев (например, когда строка содержит несколько чисел).
  • std::from_chars (C++17) — самый быстрый способ без исключений, но требует проверки кода ошибки.

Для большинства задач stoi с проверкой позиции — оптимальный выбор: он безопасный, читаемый и стандартный.

<<>>

Использование std::stringstream для преобразования

Другой популярный подход — использовать std::stringstream из заголовочного файла <sstream>. Этот метод особенно удобен, когда нужно обработать строку с несколькими числами или смешанными данными.

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string s = "456";
    std::stringstream ss(s);
    int num = 0;
    
    if (ss >> num) {
        // Проверяем, что после числа нет лишних символов
        std::string remaining;
        if (ss >> remaining) {
            std::cerr << "Ошибка: строка содержит лишние символы" << std::endl;
            return 1;
        }
        std::cout << "num + 10 = " << num + 10 << std::endl;
    } else {
        std::cerr << "Ошибка: не удалось преобразовать строку" << std::endl;
    }
    return 0;
}

Плюсы stringstream: он не использует исключения (подходит для систем, где они запрещены) и легко адаптируется для разных типов (double, float). Минусы: медленнее, чем stoi, и требует больше кода для проверки "хвостовых" символов. Для простого преобразования одного числа я рекомендую stoi, но для сложной обработки строк — stringstream.