scanf() ведет себя неправильно

У меня есть очень короткий фрагмент, который читается целым числом:

#include <stdio.h>

int main() {
    while (1) {
        int i = 0;
        int r = scanf("%d", &i);

        if (r == EOF) {
            printf("Error using scanf()\n");
        } else if (r == 0) {
            printf("No number found\n");
        } else {
            printf("The number you typed in was %d\n", i);
        }
    }
}

но проблема в том, что если я ввожу любую букву, она просто продолжает цикл и печатает «Номер не найден» вместо ожидания следующего ввода.

Что я делаю неправильно?


person Meta    schedule 21.02.2011    source источник


Ответы (3)


При использовании scanf, если вы пытаетесь выполнить операцию чтения, а найденные данные не соответствуют ожидаемому формату, scanf оставляет неизвестные данные позади, чтобы их забрала будущая операция чтения. В этом случае происходит то, что вы пытаетесь прочитать отформатированные данные от пользователя, данные пользователя не соответствуют вашему ожидаемому формату, и поэтому он ничего не может прочитать. Затем он зацикливается, чтобы попытаться прочитать снова, и находит тот же оскорбительный ввод, который был раньше, затем снова зацикливается и т. д.

Чтобы исправить это, вам просто нужно потреблять символы, которые испортили ввод. Один из способов сделать это — вызвать fgetc для чтения символов до тех пор, пока не будет обнаружена новая строка, которая очистит все недопустимые символы:

while (1) {
    int i = 0;
    int r = scanf("%d", &i);

    if (r == EOF) {
        printf("Error using scanf()\n");
    } else if (r == 0) {
        printf("No number found\n");

        /* Consume bad input. */
        while (fgetc(stdin) != '\n')
            ;

    } else {
        printf("The number you typed in was %d\n", i);
    }
}

Надеюсь это поможет!

person templatetypedef    schedule 21.02.2011
comment
Лучше иметь бесполезный буфер для передачи вызову fgets для завершения строки. А еще лучше использовать fgets с самого начала. - person Chris Lutz; 21.02.2011

Похоже, вы не очищаете входной буфер и оставляете неверный символ для сканирования снова и снова.
См. здесь:
Сканирование и циклы
и
сканирование не завершается

person Joe    schedule 21.02.2011

Страница руководства говорит

ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ Эти функции возвращают количество назначенных входных элементов. Это может быть меньше, чем предусмотрено, или даже ноль, в случае сбоя сопоставления. Ноль указывает на то, что несмотря на наличие входных данных, конверсии не были назначены; обычно это происходит из-за недопустимого входного символа, такого как буква для преобразования `%d'.

Поскольку вы использовали "%d" , если вы используете любое число, это будет работать нормально, иначе оно не будет потреблять его из буфера.

person Rahul Dimri    schedule 21.02.2011