Как говорит @MFisherKDX, проверьте возвращаемое значение scanf
. Со страницы руководства scanf :
Эти функции возвращают количество элементов ввода, которые были успешно сопоставлены
и назначенный, который может быть меньше, чем предусмотрено, или даже ноль в
событие раннего неудачного сопоставления.
Значение EOF возвращается, если конец ввода достигнут до того, как
происходит первое успешное преобразование или сбой сопоставления. EOF это
также возвращается, если происходит ошибка чтения, в этом случае ошибка
индикатор для потока (см. ferror (3)) установлен, и errno установлен
указать ошибку.
Таким образом, захват возвращаемого значения scanf
в переменной int
и последующее сравнение этой переменной с 1
(в вашем случае, потому что вы пытаетесь прочитать только 1 элемент) должны сообщить вам, успешно ли scanf
читать целочисленное значение.
Однако при использовании scanf
есть неприятная ловушка , о которой вам следует знать. Если вы введете n
в командной строке, scanf
завершится неудачно и вернет 0
, но оно также будет не потреблять введенный вами ввод. Это означает, что при следующем вызове scanf
он будет читать тот же ввод (введенный вами символ n
) и снова не выполнится. И это будет продолжаться независимо от того, сколько раз вы звоните scanf
. Меня всегда удивляет, что преподаватели компьютерных наук продолжают преподавать scanf
студентам, учитывая не только эту потенциальную ловушку, но и несколько других ловушек . Хотелось бы, чтобы у меня был никель на каждый час , который какой-то студент CS изучал где-то изо всех сил, пытаясь заставить scanf
вести себя так, как подсказывает их интуиция. Я бы уже вышел на пенсию на своем частном острове. Но я отвлекся.
Один из способов обойти эту конкретную ловушку - проверить, не удалось ли scanf
, и, если да, преднамеренно потреблять и отбрасывать весь ввод от stdin
до следующего символа новой строки или EOF
, в зависимости от того, что наступит раньше.
Сначала давайте рассмотрим некоторый un фиксированный код, который вызывает бесконечный цикл, если вы введете нецелое число в качестве ввода:
// Typing the letter 'n' and hitting <Enter> here causes an infinite loop:
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else
printf("Invalid number\n");
}
Приведенный выше код (после того, как вы наберете n
и нажмете <Enter>
), войдет в бесконечный цикл и просто начнет извергать «Неверное число» снова и снова. Опять же, это потому, что введенный вами n
никогда не удаляется из буфера ввода.
Есть несколько возможных способов обойти эту проблему , но, по-видимому, все согласны с тем, что наиболее переносимый и надежный способ сделать это заключается в следующем:
// Fixed. No more infinite loop.
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else {
printf("Invalid number\n");
// Consume the bad input, so it doesn't keep getting re-read by scanf
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) ;
if (ch == EOF) break;
}
}