Хорошо известно, что cin не является типобезопасным (например, cin >> integer; и ввод «пятьдесят пять» приведет к его переворачиванию). Я видел много не очень элегантных способов справиться с этим, таких как получение строки и использование sstream для преобразования ее в число, или цикл с cin.fail() и очистка потока и повторный ввод его и т. д. Есть ли какие-либо библиотеку или в любом случае перегрузить оператор извлечения, чтобы сделать cin автоматически типобезопасным?
Как сделать cin типобезопасным?
Ответы (5)
например
cin >> integer;
и ввод "пятьдесят пять" приведет к тому, что он перевернется
Нет, это не заставит его «вывернуться»; это приведет к установке состояния отказа потока, как и для любого другого потока. Это не означает, что std::cin
не является типобезопасным.
Одним из вариантов обработки ошибок при чтении из потока может быть написание шаблона функции, который выполняет извлечение, проверяет, удалось ли оно, сбрасывает состояние ошибки в потоке, если это необходимо, и возвращает информацию об успешности извлечения вместе с результатом.
Хорошо известно, что cin не является типобезопасным (например, cin >> integer; и ввод «пятьдесят пять» приведет к его переворачиванию).
Безопасность типов означает не то, что вы, кажется, думаете. «пятьдесят пять» — это строка. Безопасное преобразование его в число — сложная задача, если вы действительно хотите иметь универсальную/переносимую реализацию (что, если это «cinquante-cinq» [французский] или «femtifem» [норвежский])? Вам придется учитывать язык, лексический анализ, грамматическую правильность и так далее. Это выходит за рамки STL.
std::istream
безопасен для типов в том смысле, что если вы попробуете приведенный вами пример, поток распознает ошибку ("знает", что он не может интерпретировать поток как целое число) и сообщит вашему клиентскому коду об ошибке таким образом, чтобы его можно было проверить и обработать в клиентском коде.
Для сравнения, если вы используете int i; sscanf("fifty five", "%s", &i);
, это, вероятно, не вызовет никакой ошибки, заполнит ваш i
мусором, и ваша программа может рухнуть позже, если она зависит от i
, имеющего допустимое значение (я могу ошибаться в этом - я не использовал sscanf
со средней школы или около того). С другой стороны, это может привести к повреждению памяти вашей программы, если у вас есть запрос формата, который не соответствует содержимому вашей входной строки.
например cin >> целое число; и ввод «пятидесяти пяти» приведет к тому, что он перевернется
[...]
Есть ли какая-нибудь библиотека или в любом случае, чтобы перегрузить оператор извлечения, чтобы сделать cin автоматически типобезопасным?
Таким образом, std::cin
терпит неудачу, когда вы хотите прочитать из него неправильный объект.
Забавно, здесь я всегда думал, что тот факт, что чтение завершается ошибкой, если вы пытаетесь прочитать неправильный тип, делает его типобезопасным< /эм>сильный>.
В любом случае, поскольку вы не согласны, какое поведение вы бы предложили вместо этого?
У вас может быть структура с полем «Тип» и полем объединения, содержащим строку, двойное число, логическое значение и целое число. Затем вы можете написать перегрузку operator>> (ostream &, youtype &), которая сначала считывает строку из ostream и пытается преобразовать ее в наиболее конкретный тип ("1" становится int, "1.0" double и т.д. ... ), соответствующим образом установив поле «Тип».
Это не было бы идеальным решением, но его должно быть достаточно легко повторно использовать в других проектах.
Обработка исключений. Это предотвратит "переворачивание [ping]" вашего примера.