Как сделать cin типобезопасным?

Хорошо известно, что cin не является типобезопасным (например, cin >> integer; и ввод «пятьдесят пять» приведет к его переворачиванию). Я видел много не очень элегантных способов справиться с этим, таких как получение строки и использование sstream для преобразования ее в число, или цикл с cin.fail() и очистка потока и повторный ввод его и т. д. Есть ли какие-либо библиотеку или в любом случае перегрузить оператор извлечения, чтобы сделать cin автоматически типобезопасным?


person cactusbin    schedule 08.06.2010    source источник
comment
Я полагаю, вы могли бы попробовать ввести проверку того, что предоставляет символы. О... это пользователь? Неважно :-)   -  person Stephen C    schedule 08.06.2010
comment
Этот вопрос реален? Похоже, все, что он собирается сделать, это спровоцировать пламенную войну.   -  person Konrad Rudolph    schedule 08.06.2010


Ответы (5)


например cin >> integer; и ввод "пятьдесят пять" приведет к тому, что он перевернется

Нет, это не заставит его «вывернуться»; это приведет к установке состояния отказа потока, как и для любого другого потока. Это не означает, что std::cin не является типобезопасным.

Одним из вариантов обработки ошибок при чтении из потока может быть написание шаблона функции, который выполняет извлечение, проверяет, удалось ли оно, сбрасывает состояние ошибки в потоке, если это необходимо, и возвращает информацию об успешности извлечения вместе с результатом.

person James McNellis    schedule 08.06.2010

Хорошо известно, что cin не является типобезопасным (например, cin >> integer; и ввод «пятьдесят пять» приведет к его переворачиванию).

Безопасность типов означает не то, что вы, кажется, думаете. «пятьдесят пять» — это строка. Безопасное преобразование его в число — сложная задача, если вы действительно хотите иметь универсальную/переносимую реализацию (что, если это «cinquante-cinq» [французский] или «femtifem» [норвежский])? Вам придется учитывать язык, лексический анализ, грамматическую правильность и так далее. Это выходит за рамки STL.

std::istream безопасен для типов в том смысле, что если вы попробуете приведенный вами пример, поток распознает ошибку ("знает", что он не может интерпретировать поток как целое число) и сообщит вашему клиентскому коду об ошибке таким образом, чтобы его можно было проверить и обработать в клиентском коде.

Для сравнения, если вы используете int i; sscanf("fifty five", "%s", &i);, это, вероятно, не вызовет никакой ошибки, заполнит ваш i мусором, и ваша программа может рухнуть позже, если она зависит от i, имеющего допустимое значение (я могу ошибаться в этом - я не использовал sscanf со средней школы или около того). С другой стороны, это может привести к повреждению памяти вашей программы, если у вас есть запрос формата, который не соответствует содержимому вашей входной строки.

person utnapistim    schedule 08.06.2010

например cin >> целое число; и ввод «пятидесяти пяти» приведет к тому, что он перевернется
[...]
Есть ли какая-нибудь библиотека или в любом случае, чтобы перегрузить оператор извлечения, чтобы сделать cin автоматически типобезопасным?

Таким образом, std::cin терпит неудачу, когда вы хотите прочитать из него неправильный объект.
Забавно, здесь я всегда думал, что тот факт, что чтение завершается ошибкой, если вы пытаетесь прочитать неправильный тип, делает его типобезопасным< /эм>.

В любом случае, поскольку вы не согласны, какое поведение вы бы предложили вместо этого?

person sbi    schedule 08.06.2010

У вас может быть структура с полем «Тип» и полем объединения, содержащим строку, двойное число, логическое значение и целое число. Затем вы можете написать перегрузку operator>> (ostream &, youtype &), которая сначала считывает строку из ostream и пытается преобразовать ее в наиболее конкретный тип ("1" становится int, "1.0" double и т.д. ... ), соответствующим образом установив поле «Тип».

Это не было бы идеальным решением, но его должно быть достаточно легко повторно использовать в других проектах.

person sanjoyd    schedule 08.06.2010

Обработка исключений. Это предотвратит "переворачивание [ping]" вашего примера.

person Community    schedule 08.06.2010