Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.59/98: Рейтинг темы: голосов - 98, средняя оценка - 4.59
1 / 1 / 0
Регистрация: 12.04.2012
Сообщений: 20
1

Защита от дурака. Ввод данных типа int с клавиатуры.

14.04.2012, 02:11. Просмотров 20026. Ответов 21
Метки нет (Все метки)

Данные типа int вводятся с клавиатуры. нужно поставить защиту от дурака. Полазил на форуме нашёл программу:

Цитата Сообщение от usernet009 Посмотреть сообщение
ТС, у потока cin есть failbit. Этот фэилбит становится еденичкой если пользователь ввел что то не так, ну например
cin>>i; // i - int
А пользователь вводит 2.2
в переменную i попадает 2 а failbit становится = 1
И, если ты попробуешь дальше ввести чтото, например
cin>>f; //f - float
то ничего не введется так как failbit уже установлен а ввод может происходить только из "хорошего" потока.
В общем. К чему я все это, попробуй вот так
C++
1
2
3
4
5
6
7
cin>>i;
while(cin.fail() == 1) // cin.fail() возвращает 1 если установлет failbit
{
cout<<"IDIOT !! Enter again !\n";
cin.clear(); // сбрасывает все биты потока, тоесть поток становится "хорошим"
cin>>i;
}
p.s сам только недавно прочитал про эти биты\потоки, так что сильно не пинай если на заработает
по аналогии пытался сделать свою:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <conio.h>
#include <iostream>
 
using namespace std;
 
int main()
{
    int i;
 cin>>i;
while (cin.fail() == 1) // cin.fail() возвращает 1 если установлет failbit
{
cout<<"IDIOT !! Enter again !\n";
cin.clear(); // сбрасывает все биты потока, тоесть поток становится "хорошим"
cin>>i;
}
cout << i;
 getch();
 return 0;
}
но когда в поток вводится, например "gt57" программа зависает в бесконечном цикле, выводя беспрерывно строчки "IDIOT !! Enter again !".

подскажите пожалуйста, где ошибка в цикле?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.04.2012, 02:11
Ответы с готовыми решениями:

Защита от дурака, на ввод "мусора" в int
В общем, пытался сделать защиту на ввод неверного значения. Т.е чтобы вводилось значение не более 5...

Ввод/вывод имени и пути файла, а также защита от дурака
Доброго времени суток, господа. Что-то я либо некорректно формулирую запрос в google, либо просто...

Ввод с клавиатуры данных в массив, состоящий из восьми элементов типа TRAIN
помогите пожалуйста, не получается сделать,туго с динамикой. • Описать структуру с именем TRAIN,...

Ввод символа в переменную типа INT
Доброго времени суток. Подскажите самый эффективный способ борьбы с неверным вводом данных...

21
Заблокирован
Автор FAQ
14.04.2012, 02:23 2
grumpy13, всё на много проще
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
 
int main()
{
    int i;
    cout<<"Enter int : ";
    while(!(cin>>i)) 
    {
        cout<<"IDIOT !! Enter again !\n";
        cin.clear(); // сбрасывает все биты потока, тоесть поток становится "хорошим"
        cin.sync();//Удалим данные из буффера
        cout<<"Enter int : ";
    }
    system("pause");
    return 0;
}
2
Миниатюры
Защита от дурака. Ввод данных типа int с клавиатуры.  
1 / 1 / 0
Регистрация: 12.04.2012
Сообщений: 20
14.04.2012, 02:26  [ТС] 3
спасибо большое)

нашёл и у себя ошибку. не хватало строки: cin.sync();

с ней мой вариант так же работает.
0
Заблокирован
Автор FAQ
14.04.2012, 02:28 4
Лучший ответ Сообщение было отмечено как решение

Решение

Ну а вообще посмотри этот пост (тебе код С++)
https://www.cyberforum.ru/blog... omment1451
можешь и блог в целом почитать(только тогда уже весь)
В идеале код должен выглядеть так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
 
int main()
{
    int i;
    cout<<"Enter int : ";
    while(!(cin>>i) || cin.get() != '\n') 
    {
        cout<<"IDIOT !! Enter again !\n";
        cin.clear(); // сбрасывает все биты потока, тоесть поток становится "хорошим"
        cin.sync();//Удалим данные из буффера
        cout<<"Enter int : ";
    }
    system("pause");
    return 0;
}
Почему так
C++
1
while(!(cin>>i) || cin.get() != '\n')
а не как сверху
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
while(!(cin>>i))
- попробуй ввести в верхнем кода 1а или 12blabla и увидишь что целое будет подхвачено хотя по хорошему ввод неверен
3
Миниатюры
Защита от дурака. Ввод данных типа int с клавиатуры.  
Заблокирован
Автор FAQ
14.04.2012, 02:31 5
Лучший ответ Сообщение было отмечено как решение

Решение

Основная фишка - неверный ввод фиксируется вот так
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
if(!(cin>>i))
, для всевозможных дополнительных вариантов неверного ввода необходимо его оснастить ещё cin.get, т.е. идеальній или близкий к нему вариант фиксации вот этот
C++
1
if(!(cin>>i) || cin.get() != '\n')
. И ещё один момент, после кривого ввода обязательно вытерать буффер
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
cin.sync();//Удалим данные из буффера
, а не только сбрасывать флаг ошибки
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
cin.clear();
. Невытертый буффер будет продолжать коробить наш ввод. Вот теперь пожалуй и всё по данному топику
3
1 / 1 / 0
Регистрация: 12.04.2012
Сообщений: 20
14.04.2012, 02:34  [ТС] 6
Огромное вам спасибо !
0
Заблокирован
Автор FAQ
28.04.2013, 17:57 7
"По просьбам трудящихся" ниже проект с безопасным вводом и меню на заданное кол-во цифровых значений
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
#include <iostream>
using namespace std;
 
int main()
{
    int iChoise= 0;//переменная отвечающая за ввод пользователя
    bool bWork = true;//флаг продолжения работы алгоритма
    while( bWork )
    {
        cout<<"\tMENU"<<endl;
        cout<<"1 - Item1"<<endl;
        cout<<"2 - Item2"<<endl;
        cout<<"0 - Exit"<<endl;
        cout<<"Your choise : ";
        if(!(cin>>iChoise) || cin.get() != '\n') 
        {
            cout<<"Incorrect input!"<<endl;
            cin.clear(); // сбрасывает все биты потока, тоесть поток становится "хорошим"
            cin.sync();//Удалим данные из буффера
        }
        else
        {
            switch(iChoise)
            {
            case 1:
                cout<<"Run Item1"<<endl;
                break;
            case 2:
                cout<<"Run Item2"<<endl;
                break;
            case 0:
                bWork = false;
                break;
            default:
                cout<<"Unsupperted choise"<<endl;
                break;
            }
        }
    }
    return 0;
}
1
Миниатюры
Защита от дурака. Ввод данных типа int с клавиатуры.  
p0iznp0izn
28.04.2013, 18:13 8
Трудящиеся говорят Спасибо!
0 / 0 / 1
Регистрация: 16.02.2014
Сообщений: 113
02.03.2014, 21:49 9
Обьясните, пожалуйста, эту строчку
C++
1
while(!(cin>>i) || cin.get() != '\n')
Добавлено через 6 минут
Пока переменная і не целая или введенный символ не Enter, то выполнить...
Так чтоле?
0
1126 / 785 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
02.03.2014, 23:11 10
Цитата Сообщение от Donville Посмотреть сообщение
Обьясните, пожалуйста, эту строчку
C++
1
while(!(cin>>i) || cin.get() != '\n')
Условие !(cin>>i) || cin.get() != '\n' означает: либо ошибка ввода, либо в потоке ввода после чтения i остались ещё символы - не сразу конец строки.

Пример 1. Пользователь нажимает клавиши: qwer Enter ( Enter - то есть клавишу Enter )
В этом случае будет выполнено условие !(cin>>i), т.к. из строки "qwer" нельзя прочитать целое число - ошибка ввода.

Пример 2. Пользователь нажимает: 123RT и затем Enter
В этом случае ошибки ввода нет, значение i : 123. Однако в строке ввода ещё остались символы 'R' 'T' и '\n'. В этом случае cin.get() == 'R' ( и значит !='\n' ).

Пример 3. Пользователь вводит: 5111222333 Enter
Здесь ошибка ввода, если sizeof(i) == 4, ошибка диапазона.
2
0 / 0 / 1
Регистрация: 16.02.2014
Сообщений: 113
02.03.2014, 23:40 11
Спасибо большое!
0
7 / 2 / 0
Регистрация: 02.08.2018
Сообщений: 22
08.01.2020, 01:06 12
Здравствуйте!

На VS 2019 все перечисленные коды не работают: переходят в бесконечный цикл.
Что делать?

Добавлено через 1 час 50 минут
Уточняю, что происходит:
При вводе буквы в место числа, cin.fail() становиться равен единице. Но эта единица не хочет
сбрасываться командами clear и sync. А ещё компилятор пропускает поле ввода при cin.fail() = 1, что делает
отчаянную попытку, прописать ввод без команд очистки, ещё более четной !!!
0
бах-бах и в продакшен!
1825 / 1103 / 421
Регистрация: 23.09.2014
Сообщений: 3,536
Записей в блоге: 4
08.01.2020, 01:47 13
Михаил140,

интересно, вот это будет у вас работать:
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
///----------------------------------------------------------------------------|
/// Защита от дурака.
///----------------------------------------------------------------------------:
#include <iostream>
#include <string>
 
template<class T>
    T input_user(const char* promt)
    {   std::cout << promt;
        T my;
        while(!(std::cin>>my) || std::cin.get() != '\n')
        {   std::cout << "Incorrect input!\n\n";
            std::cout << promt << " ";
            std::cin.clear();
            std::cin.sync();
        }
        return my;
    }
 
///----------------------------------------------------------------------------|
/// Тест.
///----------------------------------------------------------------------------:
int main()
{   
    while(true)
    {   
        std::cout   << "int------------------------:\n";
        std::cout   << " = " << ( input_user<int>("   ") +
                                  input_user<int>(" + ") ) << "\n\n";
                         
        std::cout   << "float----------------------:\n";
        std::cout   << " = " << ( input_user<float>("   ") +
                                  input_user<float>(" + ") ) << "\n\n";
                         
        std::cout   << "string----------------------:\n";
        std::cout   << " = " << ( input_user<std::string>("   ") +
                                  input_user<std::string>(" + ") ) << "\n\n";
    }
}
?
0
7 / 2 / 0
Регистрация: 02.08.2018
Сообщений: 22
08.01.2020, 11:08 14
Увы, тоже не работает. Переходит в бесконечный цикл.
Зато нашёл ещё одну "улику": коды, с командой cin.get работают корректно, при вводе чисел с буквами (653оп), но приводе буквы или букв с числами (па23), код тут же ломается.
От кириллицы и латиницы это не зависит.
1
бах-бах и в продакшен!
1825 / 1103 / 421
Регистрация: 23.09.2014
Сообщений: 3,536
Записей в блоге: 4
08.01.2020, 12:27 15
Цитата Сообщение от Михаил140 Посмотреть сообщение
тоже не работает
верно, не работает.

вот щас тестю вот это:
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
///----------------------------------------------------------------------------|
/// Защита от дурака.
///----------------------------------------------------------------------------:
#include <iostream>
#include <string>
 
template<class T>
T input_user(const char* promt)
{
    T a;
    std::cout << promt;
    std::cin  >> a;
 
    while (std::cin.fail () || std::cin.get() != '\n')
    {      std::cin.clear();
           std::cin.sync ();
           std::cout << "Error!\n\n" << promt;
           std::cin  >> a;
    }
    return a;
}
 
///----------------------------------------------------------------------------|
/// Тест.
///----------------------------------------------------------------------------:
int main()
{
    while (true)
    {
 
        std::cout << input_user<int>        ("int------------------------:\n")
                  << "\n\n";
 
        std::cout << input_user<float>      ("float----------------------:\n")
                  << "\n\n";
 
        std::cout << input_user<std::string>("string---------------------:\n")
                  << "\n\n";
    }
}
Вроде всё гуд.
Но нет гарантии, что может всплыть какое-нить г...люк
0
7 / 2 / 0
Регистрация: 02.08.2018
Сообщений: 22
08.01.2020, 14:06 16
XLAT, нет, не работает: int = p4 и всё, снова цикл
0
Модератор
Эксперт CЭксперт С++
3909 / 3382 / 599
Регистрация: 07.10.2015
Сообщений: 6,970
08.01.2020, 14:29 17
Михаил140, такой вариант:
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
///----------------------------------------------------------------------------|
/// Защита от дурака.
///----------------------------------------------------------------------------:
#include <iostream>
#include <string>
 
template<class T>
T input_user(const char* promt)
{
    T a;
    std::cout << promt;
 
    while (!(std::cin >> a))
    {
        std::cin.clear();
        std::cin.ignore(1000, '\n');
        std::cout << "Error!\n\n" << promt;
    }
    std::cin.ignore(1000, '\n');
    return a;
}
 
///----------------------------------------------------------------------------|
/// Тест.
///----------------------------------------------------------------------------:
int main()
{
    while (true)
    {
        std::cout << input_user<int>        ("int------------------------: ")
            << "\n\n";
 
        std::cout << input_user<float>      ("float----------------------: ")
            << "\n\n";
 
        std::cout << input_user<std::string>("string---------------------: ")
            << "\n\n";
    }
}
2
бах-бах и в продакшен!
1825 / 1103 / 421
Регистрация: 23.09.2014
Сообщений: 3,536
Записей в блоге: 4
08.01.2020, 16:39 18
liv, тоже есть некорректности,
например: дурак может ввести 555nnn
но это полбеды, дальше если вы вводили с ошибкой, то потом код введёт себя не так,
как от него ожидаешь.

Михаил140,
ещё один вариант(ошибку int = p4 отрабатывает корректно) претендующий на универсальность,
тестил на VS2019 Version 16.4.2
но я плохой тестер, может вы чё-нить(глюки) тут найдете.
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
///----------------------------------------------------------------------------|
/// Защита от дурака.
///----------------------------------------------------------------------------:
#include <iostream>
#include <string>
 
class cFool
{
public:
    cFool& operator >> (std::string& a) ///-------------------------std::string:
    {
        getline(std::cin, a);
        promt = "";
        return *this;
    }
 
    cFool& operator >> (unsigned char& a) ///---------------------unsigned char:
    {
        bool      is_error;
        unsigned  n;
        do
        {   std::cin  >> n;
 
                is_error = std::cin.fail() || std::cin.get() != '\n';
            if (is_error)
            {
                std::cout << "Error!\n\n" << promt;
                std::cin.clear();
                std::cin.ignore(9999, '\n');
                std::cin.sync();
            }
            else if(n > 255)
            {   is_error  = true;
                std::cout << "Error bound!\n\n" << promt;
            }
        } while (is_error);
 
        a = n;
        promt = "";
        return *this;
    }
 
    template<class T>
    cFool& operator >> (T& a) ///--------------------------------------template:
    {
        std::cin >> a;
 
        while (std::cin.fail() || std::cin.get() != '\n')
        {
            std::cin.clear();
            std::cin.ignore(9999, '\n');
            std::cin.sync();
            std::cout << "Error!\n\n" << promt;  std::cin >> a;
        }
        promt = "";
        return *this;
    }
 
    std::string promt;
    cFool& operator >>(const char* promt_) ///----------------------------promt
    {
        std::cout << promt_;
        promt = promt_;
        return *this;
    }
}cin_fool;
 
///----------------------------------------------------------------------------|
/// Тест.
///----------------------------------------------------------------------------:
int main()
{
    setlocale(0, "");
 
    int m;
    std::string ss;
 
    ///--------------------------------------------|
    /// Тест цепочки с приглашением.               |
    ///--------------------------------------------:
    cin_fool >> "Строка: " >> ss >> "Число : " >> m;
    std::cout << "validator: "
        << "ss = " << ss << ", "
        << "m  = " << m << "\n\n";
 
    ///--------------------------------------------|
    /// Зацикленный тест для разных типов.         |
    ///--------------------------------------------:
    while (true)
    {
        std::cout << "char-----------------------:\n";
        char c;        cin_fool >> "c = " >> c;
        std::cout << "validator: " << c << "\n\n";
 
        std::cout << "unsigned char-----0,...,255:\n";
        unsigned char u; cin_fool >> "u = " >> u;
        std::cout << "validator: '" << u << "'\n\n";
 
        std::cout << "int------------------------:\n";
        int n;         cin_fool >> "n = " >> n;
        std::cout << "validator: " << n << "\n\n";
 
        std::cout << "float----------------------:\n";
        float f;       cin_fool >> "f = " >> f;
        std::cout << "validator: " << f << "\n\n";
 
        std::cout << "std::string----------------:\n";
        std::string s; cin_fool >> "s = " >> s;
        std::cout << "validator: " << s << "\n\n";
    }
}
1
7 / 2 / 0
Регистрация: 02.08.2018
Сообщений: 22
08.01.2020, 17:00 19
liv, прикольно! На буквы и на буквы с числами реагирует корректно, а числа считывает, пока не обнаружит букву. Но это - то что нужно!
XLAT, тоже Спасибо!
1
бах-бах и в продакшен!
1825 / 1103 / 421
Регистрация: 23.09.2014
Сообщений: 3,536
Записей в блоге: 4
08.01.2020, 17:14 20
Цитата Сообщение от Михаил140 Посмотреть сообщение
а числа считывает, пока не обнаружит букву
вот здесь это исправлено:
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
///----------------------------------------------------------------------------|
/// Защита от дурака.
///----------------------------------------------------------------------------:
#include <iostream>
#include <string>
 
template<class T>
T input_user(const char* promt)
{
    T a; std::cout << promt; std::cin >> a;
 
    while (std::cin.fail() || std::cin.get() != '\n')
    {
        std::cin.clear();
        std::cin.ignore(9999, '\n');
        std::cin.sync();
        std::cout << "Error!\n\n" << promt; std::cin >> a;
    }
    return a;
}
 
///----------------------------------------------------------------------------|
/// Тест.
///----------------------------------------------------------------------------:
int main()
{
    while (true)
    {
 
        std::cout << input_user<int>("int------------------------:\n")
            << "\n\n";
 
        std::cout << input_user<float>("float----------------------:\n")
            << "\n\n";
 
        std::cout << input_user<std::string>("string---------------------:\n")
            << "\n\n";
    }
}
2
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.01.2020, 17:14

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

Как разрешить ввод только чисел типа int?
Доброго времени суток. Подскажите, пожалуйста, как разрешить ввод только чисел типа int....

Защита от дурака
Как в этот код добавить защиту от ввода символов? #include &quot;stdafx.h&quot; #include &lt;iostream&gt;...

защита от дурака
Знаю что таких тем уже было много, но в них я ничего полезного не нашел. Так вот задания:...

Защита от дурака
Помогите, пожалуйста. Программа должна печатать только цифры (а не буквы и прочие символы, знак...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.