Как вы делаете Cin TypeSafe? - PullRequest
0 голосов
/ 08 июня 2010

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

Ответы [ 5 ]

13 голосов
/ 08 июня 2010

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

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

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

4 голосов
/ 08 июня 2010

Общеизвестно, что cin не является типобезопасным (например, cin >> целое число, а ввод «пятьдесят пять» вызовет его переворачивание).

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

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

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

1 голос
/ 08 июня 2010

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

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

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

0 голосов
/ 08 июня 2010

Обработка исключений. Это помешает вашему примеру "перевернуть".

0 голосов
/ 08 июня 2010

У вас может быть структура с полем 'Type' и полем объединения, содержащим строку, double, bool и int.Затем вы могли бы написать перегрузку оператора >> (ostream &, youtype &), которая сначала считывает строку из ostream и пытается преобразовать ее в наиболее конкретный тип («1» становится int, «1,0» - двойным и т. Д.)....), соответственно устанавливая поле 'Тип'.

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

...