Я пишу на C, и кажется, что программа игнорирует команду scanf
и начинает выполнять бесконечный цикл, если я вставляю что-нибудь, кроме числа. Кто-нибудь знает, как это исправить или даже что происходит?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define NBITS 8
void inserimento() {
int N, ret;
do {
printf("Immetti un numero maggiore di 1\n");
ret = scanf("%d", &N);
} while (ret == 0 || N <= 1);
}
int main() {
int N;
inserimento();
}
Я пробовал изменить порядок оператора or и использовать решение из кода, который дал нам мой профессор, но я довольно новичок в этом, поэтому не знаю, не ошибся ли я при его копировании.
Это связано с тем, что символы остаются в буфере клавиатуры. Поэтому вам необходимо очистить буфер клавиатуры.
@ CGi03 Не «буфер клавиатуры». Это опасное заблуждение. Символы остаются в потоке и должны быть удалены из потока путем их чтения.
Никогда не используйте scanf
для взаимодействия с пользователем. Прочитайте весь интерактивный ввод с помощью fgets
, затем проанализируйте полученную строку. Смотрите здесь.
Повторите 1000 раз: Никогда не используйте scanf.
Это происходит потому, что символы остаются в потоке. Поэтому вы должны опорожнить поток.
#include <stdio.h>
void fflush_stdin(void)
{
int c;
while ((c = getchar()) != EOF && c != '\n');
}
void inserimento()
{
int N, ret;
do
{
printf("Immetti un numero maggiore di 1\n");
ret = scanf("%d", &N);
fflush_stdin();
}
while(ret==0 || N <= 1);
}
int main()
{
inserimento();
}
Когда первый вызов scanf("%d", &N)
возвращает EOF
, ret==0 || N <= 1
пытается оценить неинициализированный N
. Бесконечный цикл все еще может существовать. Используйте ret==0 || (ret > 0 && N <= 1)
Есть несколько проблем:
scanf()
не удается преобразовать входные данные в десятичное целое число, он вернет либо 0
, и ошибочный ввод должен быть удален вручную, либо EOF
, если обнаружен конец файла или ошибка чтения. Рекомендуется тщательно проверять эти условия, чтобы гарантировать правильную работу во всех случаях.N
в функцию main
, поэтому значение, прочитанное inserimento()
, будет потеряно.do
/while
сбивают с толку и подвержены ошибкам, я рекомендую использовать циклы forever for (;;)
и явные тесты.Вот модифицированная версия:
#include <stdbool.h>
#include <stdio.h>
int flush_stream(FILE *fp) {
int c;
while ((c = fgetc(fp)) != EOF && c != '\n')
continue;
return c;
}
bool inserimento(int *dest) {
for (;;) {
printf("Enter a number greater than 1:\n");
switch (scanf("%d", dest)) {
case EOF:
printf("invalid or missing input\n");
return false;
case 0:
flush_stream(stdin);
printf("invalid input\n");
break;
case 1:
if (*dest > 1)
return true;
printf("invalid entry: %d\n", *dest);
break;
}
}
}
int main(void) {
int N;
if (inserimento(&N)) {
/* do something with N */
return 0;
} else {
return 1;
}
}