Как да направите cin typesafe?

Добре известно е, че cin не е безопасен за тип (напр. cin >> цяло число; и въвеждането на "петдесет и пет" ще доведе до прелитане). Виждал съм много не толкова елегантни начини за предаване на това, като getlining на низ и използване на 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 >> цяло число; и въвеждането на "петдесет и пет" ще доведе до изключване).

Типовата безопасност не означава това, което си мислите, че означава. "петдесет и пет" е низ. Да го конвертирате безопасно в число е сложен проблем, ако наистина искате да имате обща/преносима реализация (ами ако е „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 се проваля, когато искате да прочетете грешен обект от него.
Странно, тук винаги съм смятал, че фактът, че четенето се проваля, ако се опитате да прочетете грешен тип, е това, което го прави безопасен за тип< /em>.

Както и да е, тъй като случайно не сте съгласни, какво поведение бихте предложили вместо това?

person sbi    schedule 08.06.2010

Можете да имате структура с поле „Тип“ и поле за обединение, съдържащо низ, double, bool и int. След това можете да напишете оператор >> (ostream &, youtype &) overload, който първо чете низа от ostream и се опитва да го преобразува в най-специфичния тип ("1" става int, "1.0" двойно и т.н. ... ), като зададете полето „Тип“ съответно.

Това не би било идеално решение, но трябва да бъде сравнително лесно за повторно използване в други проекти.

person sanjoyd    schedule 08.06.2010

Обработка на изключения. Това ще попречи на примера ви да се „обърне [ping] out“.

person Community    schedule 08.06.2010