Безопасный ввод через функцию-шаблон
Запись от -=ЮрА=- размещена 02.01.2013 в 19:01
Показов 5686
Комментарии 22
К моему сожалению уже не первый раз встречаю банальное неумение начинающих вводить в свои программы так называемую "защиту от дурака". Собственно углубляться в теорию не буду - ниже простой код, который без особых усилий позволяет оснастить консоль указанной защитой
| |||||
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 22
Комментарии
-
-=ЮрА=- огромное спасибо, как всегда на высоте.Запись от isaak размещена 29.01.2013 в 22:42
-
Запись от SatanaXIII размещена 30.01.2013 в 10:26
-
А не проще и понятней проверить биты ошибок?
Ведь если мы через cin>>a; требуем ввод int, а пользователь подсунул что-то другое, выставляется соответствующий бит.
можно написатьC++ (Qt) 1 2 3 4 5 6 7
if(!(cin>>val) || cin.get() != '\n') bOk = false; if(!bOk) { cin.clear();//Сброс флагов ошибок cin.sync();//Очистка буфера ввода }
C++ (Qt) 1 2 3 4 5 6 7
cin>>val; bOk = cin.good(); if(!bOk) { cin.clear();//Сброс флагов ошибок cin.sync();//Очистка буфера ввода }
Запись от Dmitriy_M размещена 10.02.2013 в 21:39
-
Запись от -=ЮрА=- размещена 11.02.2013 в 00:18
-
зачем там \n в принципе понятно.
Пользователь может вести "1213 бла бла бла\n".
тогда на этот случай сократим до
C++ (Qt) 1 2 3 4 5
cin>>val; bOk = cin.good(); cin.clear(); cin.sync(); return bOk;
Запись от Dmitriy_M размещена 11.02.2013 в 10:48
-
Dmitriy_M. прости но напишу как есть - чертовски угнетает когда какой-нибудь начинающий, не разобравшись и не понимая ввсего лезет со своими глупостями. Для тебя, да и для всех читающих полный расклад того некорректа который предлагаешь. Больше возвращаться не хочу!
ОтработкаC++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
#include <iostream> using namespace std; template <class T> bool SafeInput ( const char * msg,//сообщение которое будет сопутствовать вводу T &val ); int main() { double val = 0; while(true) { if(!SafeInput("Enter double : ", val)) cout<<"Incorrect input"<<endl; else cout<<"Your input : "<<val<<endl; } return 0; } template <class T> bool SafeInput ( const char * msg,//сообщение которое будет сопутствовать вводу T &val ) { cout<<msg; cin>>val; bool bOk = cin.good(); cin.clear(); cin.sync(); return bOk; }
Как думаешь ввод 25.vot naglyadni primer должен восприниматься как корректный или же выдать ошибку, м???!
Попробуй в моем коде сделать аналогичный ввод дабла: цифра точка и пару слов сзади, что удивлён?Вот потому и нужна проверка \n. Поэтому предложенное вверху условие
- с одной стороны обеспечивает максимальную лаконичность кода, с другой максимальную функциональность и проверку.C++ 1
if(!(cin>>val) || cin.get() != '\n')
Впредь прошу постить с реальными предложениями, а не гдаить мой блог непродуманными конструкциями.
(У меня было время подумать над кодом, потому то что есть в коде поста1 - это минимально необходимый и максимально лаконичный отточенный вариант безопасного ввода - лучше никак другими словами...)Запись от -=ЮрА=- размещена 11.02.2013 в 12:19
-
Что за бред? Т.е. я делаю отступ(пробел ставлю) и входные данные не корректны?
Сообщение от -=ЮрА=-
Запись от go размещена 22.03.2013 в 21:22
-
Запись от programina размещена 08.05.2013 в 09:16
-
Запись от -=ЮрА=- размещена 08.05.2013 в 22:01
-
Таки ругается, ведь cin не заберет из потока следующие за числом пробелы.
Сообщение от -=ЮрА=-
Запись от Hrobak размещена 21.05.2013 в 16:39
-
О пробелах за числом речь и не идёт если после числа будут пробелы то ввод будет расценен как корректный. Речь о пробелах завёл go (который даже стёр свой пост, видимо стыдно стало). Вот цитата его реплики
Суть была в том, что он закинул леща якобы ввод не пропустит число как корректное если после него сделать пробел.
Нет - это не так, пробел(ы) после числа на отработку никак не влияют.Запись от -=ЮрА=- размещена 21.05.2013 в 23:02
-
Попытаюсь хоть как-то разжевать. Бывает, что данные вводятся через пробел. Таким образом, если использовать Ваш "великолепный" алгоритм, то он будет давать сбой при вводе пробела до числа, хотя входные данные корректны. Плохо покрыли тестами свой код, скорее всего из-за неопытности.
Чистить топик это Ваша прерогатива.Запись от go размещена 22.05.2013 в 10:04
-
Так речь то о том, что не будет. Пример. В первой строке 2 лишних пробела, во второй строке 1 лишний пробел, в третьей строке ничего лишнего, а четвертая не оканчивается '\n'.
Сообщение от -=ЮрА=-
Запись от Hrobak размещена 23.05.2013 в 00:10
-
Как всегда находим какой-то полу-про онлайн ресурс и и начинаем возводить его в ранг догмы. Лично Я не уверен на 100% в начинке того онлайн компилятора, который даже на 14 без пробелов и '\n' ругался http://ideone.com/AVpwHV (что само по себе уже говорит о недоработанности Ideone)
- продолжая тему 14-ти - ввод без '\n' в настоящей консольке невозможен т.к ввод подразумевает нажатие Enter, которая хочешь не хочешь вставит в буфер '\n'.
Вывод один - не пиcать и не тестировать в дерьме и не ориентироваться на компиляторы из под полы.
- а бывает данные ещё вводятся в этит бокс, где уже автоматом защита стоит. Каждой задаче своя реализация.
https://www.cyberforum.ru/blogs/34326/blog279.html
Запись от -=ЮрА=- размещена 23.05.2013 в 04:00
-
Таки без '\n' (смотрите свою ссылку - ).
Сообщение от -=ЮрА=-
А вдруг глупый пользователь Ctrl+D нажмет (EOF).
Сообщение от -=ЮрА=-
Бывает, но это уже совсем другая история. В некоторых случаях вообще SpinBox-ом лучше обойтись. Здесь уже действительно от задачи зависит.
Сообщение от -=ЮрА=-
Да никто его и не боготворит. Я бы никогда на него не ссылался, если на разных системах/компиляторах этот код работал бы по-разному.
Сообщение от -=ЮрА=-
Запись от Hrobak размещена 23.05.2013 в 15:02
-
это приведёт к облому и в простом cin>>. М.б будем разрабатывать программу для защиты монитора от головы пьяного глупого пользователя? Вобщем этот пункт счёл бредом
- могу поинтересовтать под детальным расскрытием слова разных компиляторов. Уже очень интересно на чём тестировал. Уверен кроме замшелого билдера или чего-нибудь наподобие для линукса никаких тестов не проводилось, я прав?Запись от -=ЮрА=- размещена 23.05.2013 в 17:39
-
Крайне большая проблема сделать проверку на cin.eof(), - мы же о безопасном вводе говорим, а удары головой по монитору ввод данных лично мне не напоминают, в отличии от случайного/специального нажатия Ctrl+D или Ctrl+Z или чего-то еще.
Сообщение от -=ЮрА=-
GNU C++4.7.3 под Linux, который чем-то вам не угодил, и MSVC 2012 под Windows 7.
Сообщение от -=ЮрА=-
Да и кстати, еще ваш код весело реагирует на ввод типаи скатывается в безудержное веселье при вводе случайного набора символов. Предлагаю несколько переделанный вариантCode 1
4.56.66.65
Не утверждаю, что идеальный, но, во всяком случае, работает гораздо более корректно.C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#include <string> #include <iostream> #include <limits> using namespace std; //Объявляем функцию шаблон //Функция вернёт ИСТИНА если параметр val был веден корректно //в противном случае возврат от функции ЛОЖЬ inline void streamClear (std::istream &is) { is.clear(); is.ignore(numeric_limits<streamsize>::max(),'\n'); } template <class T> bool SafeInput ( const char * msg,//сообщение которое будет сопутствовать вводу T &val ); int main() { int iVal;//Целочисленная переменная double dVal;//Вещественная переменная while(true) { if(!SafeInput("Enter integer : ",iVal))//Безопасный ввод int cout<<"Incorrect input"<<endl; else cout<<"Your input : "<<iVal<<endl; if(!SafeInput("Enter double : ",dVal))//Безопасный ввод double cout<<"Incorrect input"<<endl; else cout<<"Your input : "<<dVal<<endl; } return 0; } template <class T> bool SafeInput ( const char * msg,//сообщение которое будет сопутствовать вводу T &val ) { cout<<msg;//Вывод на экран сопутствующего сообщения //Проверка на корректный ввод должна содержать не только if(!(cin>>val) ) //но и проверку на то что строка более не содержит символов т.е cin.get() != '\n' if(!(cin>>val)) { streamClear(cin); return false; } char c; while (c=cin.get(),c!='\n' && !cin.eof()) if (c!=' ') { streamClear(cin); return false; } cin.clear (); return true; }
Запись от Hrobak размещена 24.05.2013 в 01:31
-
Hrobak
1-е терпеть не могу когда люди врут
а залей ка мне видео с OS Windows любой версии NT линейки где бы нажате Ctr+ Чего то там не привела к Incorrect input.
Я терпеть не могу когда люди врут!
- вот текстовка как реагирует код
- подскажи после чего смеяться?
- не обижайся, но
Знаешь почему - потому, что кода в 2 раза больше стало, появилась доп функция -парень или мистер мне без, разници, возьми на вооружение вот такую древнюю поговорку -
Можешь полистать Шилдта или Страустурпа, а лучше хабр на тему стадии развития программиста (поймёшь о чём я говорил)
- отличий для NT я не увидел.
Раз уж речь зашла о модернизациях, хорошо вот модернизация которая как я уверен справиться с отработкой на Х-ах, где как я понял Ctrl+D и Ctrl+Z обладают магическими свойствами в консоли
Скриншот к сожалению могу прицепить на rghost (когда администрация позволит добавлю его в первый пост)C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
#include <string> #include <iostream> using namespace std; //Объявляем функцию шаблон //Функция вернёт ИСТИНА если параметр val был веден корректно //в противном случае возврат от функции ЛОЖЬ template <class T> bool SafeInput ( const char * msg,//сообщение котороет сопутсвовать вводу T &val ); int main() { int iVal;//Целочисленная переменная double dVal;//Вещественная переменная while(true) { if(!SafeInput("Enter integer : ",iVal))//Безопасный ввод int cout<<"Incorrect input"<<endl; else cout<<"Your input : "<<iVal<<endl; if(!SafeInput("Enter double : ",dVal))//Безопасный ввод int cout<<"Incorrect input"<<endl; else cout<<"Your input : "<<dVal<<endl; } return 0; } template <class T> bool SafeInput ( const char * msg,//сообщение котороет сопутсвовать вводу T &val ) { bool bOk = true;//Флаг успешного ввода cout<<msg;//Вывод на экран сопутсвующего сообщения //Проверка на корректный ввод должна сожержать не только if(!(cin>>val) ) //но и проверку на то что строка более не содержит символов т.е cin.get() != '\n' //также следует учесть что пользователь мог оставить за числом хвост из пробелов //в этом случае нужно анализировать буффер на предмет нахождения не пробелов //поэтому в коде введена getline(cin, buffer) string buffer; if(!(cin>>val)) bOk = false; else if ( getline(cin, buffer) ? (buffer.find_first_not_of(' ') != string::npos) : cin.get() != '\n' ) bOk = false; if(!bOk) { cin.clear();//Сброс флагов ошибок cin.sync();//Очистка буффера ввода //Если не вызвать эти два метода после некорректного ввода 1-е ошибка так и останется флагом cin::bad //Буфер станет генеротором символов оставшихся в нём, т.е если вместо чсла ввели строку из 5-ти символов //то как минимум 5-ть вводов будут неокрректными } return bOk; }
http://rghost.ru/46234093
Не по теме:
Hrobak - в дальнейшем за ложь (обман за NT платформу) буду изымать твои посты, так что будь впредь пиши как оно есть, а не как ты хочешь показать людям - 2раза не предупреждаю.
Запись от -=ЮрА=- размещена 24.05.2013 в 22:12
-
Во-первых, никто вам не врет. Вот так у меня: http://rghost.net/46235093. Или это уже скриншот выполнения модернизированного кода? (он действительно корректно работает на MSVC)
Сообщение от -=ЮрА=-
Речь шла о тестировании на реакцию от последующих пробелов. Ctrl+Z в Win на MSVC даст Incorrect Input, я и не спорю, хотя было бы интересно посмотреть на реакцию MinGW.
Реакция на этот же код абсолютно другая у GNU C++, но ладно, забудем о кросплатформенности. 70 делить на 54 будет 2? О_о Больше на 15 строк, которые обеспечивают корректную работу на разных компиляторах.
Сообщение от -=ЮрА=-
Попробую попридираться.
Сообщение от -=ЮрА=-
К чему заводить лишнюю строку, да и притом фактически делать лишний проход по ней, когда это можно сделать сразу? Я не говорю, что это критично, но на написание простого кода не сильно походит. Посмотрю, как G++ это скушает и отпишу.
Не по теме:
-=ЮрА=-, сами подумайте, какой смысл мне вас обманывать, если и так понятно, что вы работаете со студией и сможете все проверить. Вроде же даже на тролля не похож :scratch:
Запись от Hrobak размещена 24.05.2013 в 23:29
-
Так вот, G++ реагирует так:
1) на последующие пробелы корректно.
2) на EOF в строке корректно.
3) при вводе точек конечное число раз подряд выводит Incorrect Input.
4) при вводе случайных символов бесконечно начинает выводить Incorrect Input.
Пользователь переведен мной в бан по причине обмана
от -=ЮрА=-Запись от Hrobak размещена 24.05.2013 в 23:41


cin>>12,56[пробел] подберёт все до \n.



