Проблемы с функцией scanf и циклом while
Код:
#include<stdio.h>
#include<stdlib.h>
void get_num ( int *pi )
{
printf("Введите число: ");
scanf("%d\n", pi);
}
int main ( void )
{
int i = 1;
while ( i != 0 )
{
get_num(&i);
printf("Ваше число: %d\n", i);
}
return EXIT_SUCCESS;
}
Вывод:
user@user:~$ ./a.out
Введите число: 1
2
Ваше число: 1
Введите число: 3
Ваше число: 2
Введите число: 4
Ваше число: 3
Введите число: a
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
...
После ввода числа предполагался его вывод, но выводится число, введенное в прошлый раз, а при вводе букв возникает бесконечный вывод. Почему такое происходит?
Ответы (3 шт):
Не так хорош в C, но, мне кажется основная причина, почему у вас выводится предыдущее число - это escape символ или new line кому как удобней: \n.
Почему бесконечный цикл?, ответ, как мне кажется это потому что, когда вы вводите нецифровой символ то оператор ввода scanf %d не может спарсить веденный символ как целое число и он оставляет его в буфере.Так что при следующей итерацией цикла while,он считывает точно такой же символ еще раз, повторно.
Потому что вы передали scanf строку формата с пробельным символом:
scanf("%d\n", pi);
// ^^
Любой отдельный символ пробела в строке формата потребляет все доступные последовательные символы пробела из входных данных (определяется как если бы вызывался
isspaceв цикле). Обратите внимание, что нет никакой разницы между"\n"," ","\t\t"или другими пробелами в строке формата.Первый символ, если таковой имеется, после этой использованной последовательности остается непрочитанным
То есть первый вызов scanf будет ожидать число, последовательность пробелов, а потом любой символ (этот символ останется непрочитанным).
Второй вызов будет ожидать то же самое, но в качестве ввода ему будет передан непрочитанный символ с первой итерации. И если он не может быть преобразован в число, произойдёт сбой сопоставления.
В случае сбоя символ так и останется непрочитанным, и на следующей итерации произойдёт то же самое. Поэтому ввод буквы приводит к зацикливанию
Наверное Вы бы хотели получить вот такое поведение вашей программы:
#include <stdio.h>
#include <stdlib.h>
int get_num ( int *pi )
{
printf("Введите число: ");
return scanf("%d", pi);
}
int main ( void )
{
int i = 1, c = 0;
do
{
if ( get_num(&i) != 0)
printf("Ваше число: %d\n", i);
while ((c = getchar() != '\n') && c != EOF){}
} while ( i != 0 );
return EXIT_SUCCESS;
}