Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
ququ_smile
1 / 1 / 0
Регистрация: 28.01.2013
Сообщений: 162
#1

Охота на ошибки, при неправильном вводе - C++

23.07.2013, 00:27. Просмотров 883. Ответов 19
Метки нет (Все метки)

В общем проблема такая. Если есть переменная типа int, а туда с клавы вводят какой-нибудь символ, то программе это не нравится и она начинает блевать. Т.е. в потоке cin остается кое-что нехорошее, что нужно убрать. Я пытался перехватить эту ошибку и перехватил, однако после этой ошибки программа завершается и загрязненный поток cin остается бесполезным, а мне это не нужно. Я пытался очистить поток функцией std::cin.clear() , но как-то бесполезно. Как мне исцелить этот поток? Вот код:
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
#include <iostream>
#include <windows.h>
#include <stdexcept>
 
int main()
try {
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    int x;
    while(true)
    {
        std::cout<<"Введите число (int)\n";
        std::cin>>x;
        if(x == 93) break; // Цикл завершается, при вводе 93
        if(!std::cin)
        {
           // throw std::runtime_error("Ошибка, это не число.Поробуйте еще разок\n"); //Ловушка для ошибки
            std::cin.clear();
            std::cout<<"Ошибка, это не число.Поробуйте еще разок\n";
        }
    }
 
    std::cout<<"Если вы читаете это, значит начали выполнятся те инструкции, которые идут после цикла \n";
    return 0;
}
 
catch (std::runtime_error& e)
{
    std::cerr<<e.what()<<std::endl;
}
 
catch(...)
{
    std::cout<<"Другая ошибка : С \n";
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.07.2013, 00:27
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Охота на ошибки, при неправильном вводе (C++):

ошибка при вводе в неправильном формате - C++
Доброго всем времени суток! Есть код, очень простенький. И есть баг: если пользователь вводит вместо цифр буквы или ещё какую-нить...

Устранение возможной ошибки пользователя при вводе - C++
Здравствуйте! Есть участок кода (если понадобится скину весь код), в самом начале есть выбор пункта меню у меня на данный момент...

Как реализовать вывод ошибки при вводе пользователем символов? - C++
Допустим есть программа выполняющая простейшую операцию, например, нахождение суммы двух целых чисел. Как сделать так, чтобы в случае ввода...

Почему при вводе числа программа работает нормально, а при вводе буквы уходит в бесконечный цикл? - C++
void mainmenu() { cout &lt;&lt; &quot;Введи число&quot; &lt;&lt; endl; cin &gt;&gt; choice; if (choice == 1) { cout &lt;&lt; &quot;Hello&quot; &lt;&lt; endl; } ...

Как организовать повтор ввода при неправильном ответе - C++
Добрый вечер, форумчане! Пытаюсь сделать в консоли программку - квест. Пользователь вводит правильный ответ, и программа продолжает...

Составить программу, которая при вводе символа с клавиатуры выво-дит "латинская буква" при вводе латинской буквы и "не латинская бук-ва" во всех остал - C++
Составить программу, которая при вводе символа с клавиатуры выво-дит &quot;латинская буква&quot; при вводе латинской буквы и &quot;не латинская бук-ва&quot;...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Denisqwwq
38 / 32 / 1
Регистрация: 01.06.2013
Сообщений: 117
23.07.2013, 00:39 #2
C++
1
 std::cin.sync();
Добавлено через 6 минут
после
C++
1
std::cin.clear();
ququ_smile
1 / 1 / 0
Регистрация: 28.01.2013
Сообщений: 162
23.07.2013, 00:46  [ТС] #3
Спасибо. А вы не можете наглядно объяснить в чем отличие между clear() и sync() ? А то из объяснения, которое я нашел в интернете мне ничего не понятно (сброс битов ошибок входного стандартного потока). Как это понимать?
Denisqwwq
38 / 32 / 1
Регистрация: 01.06.2013
Сообщений: 117
23.07.2013, 01:06 #4
ququ_smile, http://cppstudy.wordpress.com/2009/0...in-get-and-co/
вот, более доступно написано.
ququ_smile
1 / 1 / 0
Регистрация: 28.01.2013
Сообщений: 162
23.07.2013, 01:20  [ТС] #5
"Эта функция восстанавливает поток, если он по какой-либо причине оказался в ошибочном состоянии. Например, из потока пытались прочитать число, а там в это время находились буквы. В этом случае, поток переводится в состояние отказа, и дальнейшие операции с ним неосуществимы. В том числе и cin.get(). Функция же clear() “очищает” состояние потока, делая его вновь веселым и работоспособным."


Написано, что она "очищает" состояния потока, делая его работоспособным. А написал я эту тему, потому-что после этой функции поток не выздоровел.
Denisqwwq
38 / 32 / 1
Регистрация: 01.06.2013
Сообщений: 117
23.07.2013, 01:29 #6
ququ_smile,
Цитата Сообщение от ququ_smile Посмотреть сообщение
Функция же clear() “очищает” состояние потока
, но не сам поток.

Не по теме:

Вполне возможно, что я ошибаюсь.

Belfegor
Ghost
172 / 172 / 6
Регистрация: 16.09.2012
Сообщений: 526
23.07.2013, 01:31 #7
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
int main() {
    int n;
    while (true) {
        std::cin >> n;
        if (std::cin.good())
            std::cout << "Ok" << std::endl;
        else {
            std::cout << "Not number" << std::endl;
            break;
        }
    }
    return 0;
}
alsav22
5417 / 4813 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.07.2013, 02:12 #8
Цитата Сообщение от ququ_smile Посмотреть сообщение
Написано, что она "очищает" состояния потока, делая его работоспособным.
При ошибке, в потоке устаналивается один из флагов ошибки (failbit, badbit), невведённое остаётся в потоке. clear() сбрасывает флаги ошибок, поток становится рабочим, но нужно убрать из потока и то, что осталось невведённым.

Добавлено через 19 минут
Цитата Сообщение от Denisqwwq Посмотреть сообщение
std::cin.sync();
sync() не срабатывает в Linux при очистке потока. Почему неясно, но на практике это так. Можно использовать такую конструкцию (будет выход из ввода, если в строке нет посторонних символов (кроме первых пробелов)):

C++
1
2
3
4
5
6
7
8
9
    cout << "Enter the number: " << endl;
    int i;
    while (!(cin >> i) || cin.peek() != '\n')
    {
        cin.clear();
        while (cin.get() != '\n');
        cout << "Error! Retry input\n";
        cout << "Enter the number: " << endl;
    }
Denisqwwq
38 / 32 / 1
Регистрация: 01.06.2013
Сообщений: 117
23.07.2013, 02:15 #9
alsav22, спасибо большое.
обязательно возьму на заметку!
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
23.07.2013, 11:17 #10
alsav22,
C++
1
while (cin.get() != '\n');
==
C++
1
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
23.07.2013, 11:41 #11
ForEveR, причем ignore() должен работать быстрее.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
23.07.2013, 11:46 #12
Tulosba, По-хорошему да. Как-то так это выглядит в libcxx
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
            if (__n == numeric_limits<streamsize>::max())
            {
                while (true)
                {
                    typename traits_type::int_type __i = this->rdbuf()->sbumpc();
                    if (traits_type::eq_int_type(__i, traits_type::eof()))
                    {
                       __err |= ios_base::eofbit;
                       break;
                    }
                    ++__gc_;
                    char_type __ch = traits_type::to_char_type(__i);
                    if (traits_type::eq(__ch, static_cast<char_type>(__dlm)))
                        break;
                }
            }
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
23.07.2013, 11:57 #13
ForEveR, а в VS как-то так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if (_Ok && 0 < _Count)
            {   // state okay, use facet to extract
            _TRY_IO_BEGIN
            for (; ; )
                {   // get a metacharacter if more room in buffer
                int_type _Meta;
                if (_Count != INT_MAX && --_Count < 0)
                    break;  // buffer full, quit
                else if (_Traits::eq_int_type(_Traits::eof(),
                    _Meta = _Myios::rdbuf()->sbumpc()))
                    {   // end of file, quit
                    _State |= ios_base::eofbit;
                    break;
                    }
                else
                    {   // got a character, count it
                    ++_Chcount;
                    if (_Meta == _Metadelim)
                        break;  // got a delimiter, quit
                    }
                }
            _CATCH_IO_END
            }
Но я бы еще хотел сказать и про sentry-объект, который в случае с ignore() создается и уничтожается один раз, а при вызове get() каждый раз.
alsav22
23.07.2013, 12:57
  #14

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
причем ignore() должен работать быстрее.
Всё это, конечно, очень важно для строки, например, из 5 символов.

Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
23.07.2013, 13:00 #15
alsav22, ну дело не только в скорости. Просто всё таки лучше, когда само название функции говорит о выполняемых действиях.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.07.2013, 13:00
Привет! Вот еще темы с ответами:

Выведение ошибки на экран ри вводе одинаковых чисел - C++
Нужно вывести на экран,что мол &quot;вы ввели одинаковые числа повторите попытку ещё раз&quot; А задача заключается в том,что когда пользователь...

Кирилица отображается нормально при выводе из программы, но иероглифы при вводе в консоль - C++
Что надо подключить что бы в консоли писать русскими буквами? cin &gt;&gt; kol; cin &gt;&gt; x; cout &lt;&lt; &quot;У вас есть &quot; &lt;&lt; kol &lt;&lt; &quot; &quot; &lt;&lt; x; ...

Дебри указателей - охота на память - C++
Случай: *p-&gt;CreateSoundFromFile(&amp;p)-&gt;(*p=new)-&gt;p-&gt;Release(); Освобождается ли память верно с массива в указателе и с самого указателя при...

Ошибка при вводе - C++
мне нужно записать числа с файла в список , подскажите что не так выводит последнее лишнее число не пойму откуда оно берется #include...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
23.07.2013, 13:00
Ответ Создать тему
Опции темы

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