1. std::stoi: базовая идея
Иногда кажется, что ввод числа — это всегда std::cin >> x; и готово. Но как только вы захотите прочитать строку целиком (например, «Имя Фамилия», адрес, комментарий, фразу с пробелами), вы почти автоматически переходите на std::getline. А дальше возникает бытовая задача: «Окей, я прочитал строку, но там же число, как мне сделать из неё int?».
Представьте консольную анкету: имя — строка, год рождения — вроде бы число, но вы хотите читать всё через getline, чтобы ввод был единообразным и без сюрпризов. Или пользователь вводит сумму 1500, но вы хотите сначала прочитать её как текст (строка), а потом уже интерпретировать как число. Вот тут и появляется std::stoi.
std::stoi — это функция стандартной библиотеки C++, которая пытается интерпретировать строку как целое число типа int. Если всё хорошо, вы получаете int и можете делать арифметику, сравнения и т.д.
Но практический вывод один: stoi — мостик между миром текста и миром чисел.
Минимальный синтаксис: строка → int
В минимальном виде stoi выглядит так: берём std::string, получаем int. Главное — подключить <string>, потому что и std::string, и std::stoi находятся именно там.
#include <iostream>
#include <string>
int main() {
std::string text = "42";
int value = std::stoi(text);
std::cout << value << '\n'; // 42
}
В этом примере строка "42" идеально подходит для превращения в число. Поэтому std::stoi отрабатывает «без драмы»: вы получаете 42.
Встраиваем stoi в «живой» ввод через getline
Следующий шаг — сделать то, ради чего обычно и нужен stoi: прочитать строку (чаще всего через getline) и превратить её в число.
Здесь важно не торопиться. Мы читаем строку как текст, и только затем говорим: «А теперь попробуем превратить ее в число».
#include <iostream>
#include <string>
int main() {
std::string line;
std::getline(std::cin, line);
int n = std::stoi(line);
std::cout << "n = " << n << '\n'; // например: n = 15
}
Обратите внимание на психологический момент: программа как будто «вежливо» сначала берёт ввод в безопасном формате (строка), а потом делает шаг интерпретации. Это часто удобнее, чем пытаться читать сразу int, особенно если формат ввода сложнее, чем «одно число без пробелов».
3. Практический пример: мини-анкета
Давайте продолжим условное учебное приложение — консольную анкету. До этого вы уже могли печатать вопросы через std::cout, читать имя через getline, а теперь добавим ввод числа как строки и преобразование через stoi.
Идея простая: спросим имя (строка), спросим год рождения (строка), превратим год рождения в int и посчитаем возраст относительно фиксированного года (пусть будет 2026 — чисто для примера; да, календарь у программы пока «на батарейках»).
#include <iostream>
#include <string>
int main() {
std::string fullName;
std::string birthYearText;
std::cout << "Введите имя и фамилию: ";
std::getline(std::cin, fullName);
std::cout << "Введите год рождения (например, 2005): ";
std::getline(std::cin, birthYearText);
int birthYear = std::stoi(birthYearText);
int age = 2026 - birthYear;
std::cout << "Привет, " << fullName << "!\n";
std::cout << "Тебе примерно " << age << " лет.\n";
}
Заметьте, как аккуратно мы обошлись без смешивания >> и getline: всё читаем через getline, и это делает поведение ввода предсказуемым. Пока вы новичок, «предсказуемость» обычно важнее, чем «я могу ввести число одной командой cin >>».
4. Поведение stoi: что «прощает» и что делает коварно
Ведущие пробелы и знак числа
Иногда пользователи вводят не идеально. Например, ставят пробелы в начале. Хорошая новость: std::stoi умеет пропускать ведущие пробелы. Плохая новость: это может создать ощущение, что она «всё прощает», а это уже опасная иллюзия.
#include <iostream>
#include <string>
int main() {
std::string text = " 15";
int value = std::stoi(text);
std::cout << value << '\n'; // 15
}
Пробелы в начале не помешали. Это удобно, но одновременно это намекает: stoi — не строгий «парсер по ГОСТу», а скорее алгоритм “попробую понять, что вы имели в виду”.
Частичное преобразование: число в начале, мусор дальше
Вот здесь начинается самое интересное (и самое коварное). Строка может содержать число в начале, а дальше — мусор. И std::stoi часто берёт число из начала и останавливается на первом неподходящем символе.
То есть строка "12kg" вполне может превратиться в число 12.
#include <iostream>
#include <string>
int main() {
std::string text = "12kg";
int value = std::stoi(text);
std::cout << value << '\n'; // 12
}
Почему это важно? Потому что по смыслу "12kg" — это не число, это “число + единица измерения”. Иногда такое поведение полезно (например, вы заранее знаете, что формат именно такой: число в начале, потом суффикс). Но чаще новичок ожидает строгость: «Если там не чистое число — значит ошибка». А stoi может «молча согласиться» и дать вам половинку правды.
Чтобы было наглядно:
| Строка ввода | Что вы могли ожидать | Что часто делает stoi |
|---|---|---|
|
|
|
|
ошибка или 42 | |
|
ошибка | |
|
ошибка | ошибка выполнения (часто) |
|
ошибка | ошибка выполнения (часто) |
Слово «часто» здесь не для ухода от ответственности, а как напоминание: точное поведение в деталях — это уже уровень чтения спецификаций и осознанной обработки ошибок. Мы пока на уровне «понимаю идею и вижу ограничения».
5. Ограничения stoi: почему возможна ошибка выполнения
Важный момент: std::stoi — это не магия, а функция, которая может «не справиться».
Если строка не похожа на число (например, "hello", пустая строка "", или что-то слишком большое по модулю для int), то при вызове stoi программа может завершиться с ошибкой выполнения. На уровне ощущений это выглядит так: вы запускаете программу, вводите что-то «не то», и она внезапно прекращает работу (иногда с сообщением, иногда — просто “Runtime error”).
И здесь важно не впасть в крайности.
Первая крайность — паника: «Всё, stoi нельзя использовать». Можно, просто нужно понимать рамку: в этой лекции мы используем stoi как демонстрацию конвертации при корректном вводе.
Вторая крайность — самоуверенность: «Ну раз оно иногда работает даже с "12kg", значит оно умное и само разберётся». Нет. Оно не “поймёт смысл”, оно просто применит свой алгоритм, и если вход выходит за рамки — получите ошибку выполнения.
Особенно часто новички ловят ошибку выполнения в такой ситуации: после std::getline получили пустую строку (например, из-за остатка '\n' после >>), а потом сделали stoi от пустой строки. Пустая строка — не число, и stoi на ней обычно “падает”.
6. Связка getline и оператора >>
Сейчас будет маленький мостик к теме про «остаток '\n'», но без полного повтора. Покажем, почему это важно именно для stoi.
Если вы сначала читаете число через std::cin >>, а потом хотите читать строку через getline, то часто первый getline получает пустую строку. А если после этого вы передадите эту пустую строку в stoi, будет очень грустно.
Поэтому, если формат ввода у вас смешанный, используйте «переходный getline», чтобы съесть остаток строки.
#include <iostream>
#include <string>
int main() {
int a = 0;
std::string dummy;
std::string numberLine;
std::cin >> a;
std::getline(std::cin, dummy); // съели остаток '\n'
std::getline(std::cin, numberLine); // читаем строку
int b = std::stoi(numberLine);
std::cout << (a + b) << '\n';
}
В рамках нашего уровня это выглядит как правило гигиены: раз уж вы решили конвертировать строку в число через stoi, сначала убедитесь, что вы реально прочитали не пустую и не случайную строку.
7. Конвертация и валидация: не путать
Очень полезно заранее разделить два понятия.
Конвертация — это “у меня уже есть корректная строка с числом, преврати её в int”. Именно это делает stoi в нашем сегодняшнем использовании.
Валидация — это “проверь, что строка действительно является корректным числом, и аккуратно обработай ошибки”. Это отдельная инженерная задача, которая потребует либо более продвинутого ввода, либо обработки ошибок, либо других инструментов стандартной библиотеки. Мы туда пока не лезем: не потому что это «запрещено», а потому что в курсе есть порядок тем, и мы не хотим превращать ранние занятия в «марафон боли».
Поэтому честная рамка лекции такая: std::stoi здесь — демонстрация механики “строка → int” и знакомство с ограничениями.
8. Типичные ошибки при работе со std::stoi
Ошибка №1: воспринимать stoi как «проверку корректности».
Новичок часто думает: «Если stoi вернул число — значит строка корректна». Но строка "12kg" может дать 12, и программа продолжит работать, как будто всё нормально. Это не валидация, это попытка извлечь число из начала строки.
Ошибка №2: передавать в stoi пустую строку после getline.
Пустая строка — нормальный результат getline (пользователь мог нажать Enter, или вы могли случайно прочитать остаток '\n'). Но для stoi пустая строка обычно означает ошибку выполнения. Поэтому “прочитал строку” и “прочитал строку с числом” — это не одно и то же.
Ошибка №3: забыть, что stoi работает с int, а int не бесконечен.
Даже если строка выглядит как число, оно может быть слишком большим по модулю для int. Тогда stoi может привести к ошибке выполнения. На этом этапе достаточно помнить простую мысль: у типов есть диапазоны, и ввод может быть «слишком большим».
Ошибка №4: смешать std::cin >> и std::getline без “переходной строки”, а потом обвинить stoi.
Очень легко перепутать причину и следствие: программа падает на stoi, но настоящая причина в том, что getline прочитал пустую строку из-за оставшегося '\n'. В итоге кажется, что «stoi сломан», хотя сломалась логика ввода.
Ошибка №5: забыть подключить <string>.
Иногда код компилируется в одной среде и не компилируется в другой, и студент начинает подозревать заговор компилятора. На деле std::string и std::stoi живут в заголовке <string>, и лучше подключать его явно, чтобы код был переносимым и понятным.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ