Страницы

Поиск по вопросам

среда, 1 января 2020 г.

бесконечный цикл (scanf), не понимаю почему

#c


#include 

int main(void)
{
    int num;

    do
    {
        scanf("%d", &num);

        if (num >= 1 && num <= 2000)
        {
            // Ниже тело цикла --------------------------
            if (num <= 4)
            {
                printf("few\n");
            }
            else if (num <= 9)
            {
                printf("several\n");
            }
            else if (num <= 19)
            {
                printf("pack\n");
            }
            else if (num <= 49)
            {
                printf("lots\n");
            }
            else if (num <= 99)
            {
                printf("horde\n");
            }
            else if (num <= 249)
            {
                printf("throng\n");
            }
            else if (num <= 499)
            {
                printf("swarm\n");
            }
            else if (num <= 999)
            {
                printf("zounds\n");
            }
            else
            {
                printf("legion\n");
            }
        } // закрывает "if (num >= 1 && num <= 2000)"
    } // закрывает "DO"

    while ((num < 1) || (num > 2000));
}




Как-то по-уродски код вставился...

Задача: На вход программа просит число. Если число в диапазоне от 1 до 2000, то следует
выполнить тело цикла. И повторять это до тех пор, пока число меньше 1 или больше 2000.

В целом все работает. Проблемы возникают тогда, когда я ввожу не число. К примеру
"q". Тогда программа будет бесконечно просить меня ввести что-то, и ей уже все ровно,
что я ввожу нужные значения. Не понимаю, почему не работает. Мой взгляд на вещи:


Обьявляем переменную num
Запускаем цикл DO
Программа запрашивает данные (scanf)
Допустим я ввожу "q"
Т.к num - переменная типа int, я думаю до цикла if даже не дойдет
Проверка на завершения цикла while, но т.к условию num явно не удовлетворяет, то
цикл идет заного
у меня опять запрашивают данные (scanf) и я ввожу "21"
На этом этапе значение num должно пройти в цикл if и цикл while должен завершиться
т.к соблюдаются условия по выходу из цикла
вместо этого я получают цикл из бесконечных scanf....


и еще вопрос: почему я не получаю ошибку, когда пытаюсь ввести что-то, отличное от
типа int? разве "&num" - это ни есть присвоение? всё уже должно было взорваться, когда
я попытался впихнуть туда "q". 
    


Ответы

Ответ 1



Нужно проверять, что возвращает scanf. Сделайте так: if (scanf("%d", &num) != 1) { while(fgetc(stdin) != '\n'); continue; } Т.е. пока не считано нормальное число - игнорировать введеннуюю строку и начать цикл заново... У вас, встретив не цифру, scanf оставляет ее в буфере, и при повторении цикла опять встречает ее же...

Ответ 2



Вам следует проверять результат работы функции scanf, и если было введено не число, то пропускать введенные символы. Это можно сделать следующим образом int num; do { int result = scanf( "%d", &num ); if (result == EOF) break; if (result != 1) { scanf("%*[^\n]"); num == 0; } if (num >= 1 && num <= 2000) { // Ниже тело цикла -------------------------- if (num <= 4) { printf("few\n"); } else if (num <= 9) { printf("several\n"); } else if (num <= 19) { printf("pack\n"); } else if (num <= 49) { printf("lots\n"); } else if (num <= 99) { printf("horde\n"); } else if (num <= 249) { printf("throng\n"); } else if (num <= 499) { printf("swarm\n"); } else if (num <= 999) { printf("zounds\n"); } else { printf("legion\n"); } } // закрывает "if (num >= 1 && num <= 2000)" } while ((num < 1) || (num > 2000)); // закрывает "DO" В этом фрагменте кода, если было введено не число, то функция scanf Ничего не считает, а потому лна возвратит значение 0. В этом случае данное if предложение пропустит все неправильно введенные символы if (result != 1) { scanf("%*[^\n]"); num == 0; } и вы сможете повторить итерацию цикла.

Ответ 3



scanf("%d", &num); Если мы уверены, что никаких EOF пользователь не введёт, то нам надо дождаться ввода числа (scanf вернёт 1) выкидывая нечисловые значения (ведь мусор, лежащий в потоке, сколько не пытайся его читать, числом-то не становится): while (scanf("%d", &num) != 1) scanf("%*s"); Если мы хотим ещё и EOF проверять (который -1), то можно немного переписать условие: while (scanf("%d", &num) == 0) scanf("%*s"); или while (!scanf("%d", &num)) scanf("%*s"); Если хочется порпускать всю строку целиком, то можно использовать while (!scanf("%d", &num)) scanf("%*[^\r\n]"); Как-то так.

Ответ 4



Да эта беда всегда была в scanf и им поэтому никто не пользуется, он выпихивает назад что ему не нравится по ungetc, короче надо строчку через gets ввести, а потом её в sscanf

Комментариев нет:

Отправить комментарий