scanf пропускает ввод: пробел перед %c
Чаще всего «пропуск» случается при чтении символа после числа. Решение — пробел перед %c:
#include <stdio.h>
int main(void) {
int n;
char c;
scanf("%d", &n);
scanf(" %c", &c);
printf("n = %d, c = %c\n", n, c);
return 0;
}5
yn = 5, c = yЕсли ввода не ждёт fgets после scanf или scanf зацикливается на буквах — сразу переходите к разделам fgets после scanf и scanf зациклился.
Почему так происходит
Когда вы набираете 5 и нажимаете Enter, программа получает два символа: 5 и перевод строки \n. scanf("%d") забирает 5, а \n остаётся ждать следующего чтения. Формат %c читает любой символ, в том числе \n, — поэтому scanf("%c", &c) сразу получает перевод строки и не ждёт ввода. Видно, что попало в c, если вывести код символа:
#include <stdio.h>
int main(void) {
int n;
char c;
scanf("%d", &n);
scanf("%c", &c);
printf("Код символа в c: %d\n", c);
return 0;
}5
yКод символа в c: 1010 — код перевода строки. Пробел в формате " %c" означает «пропустить все пробелы, табуляции и переводы строк», и %c получает первый настоящий символ.
Числовые форматы (%d, %lf) и %s пробелы и переводы строк перед значением пропускают сами, поэтому scanf("%d", …) после scanf("%d", …) работает без пробела.
fgets после scanf получает пустую строку
Та же причина: fgets читает до \n и находит его сразу. Перед fgets дочитайте остаток строки:
#include <stdio.h>
#include <string.h>
int main(void) {
int age;
char name[100];
scanf("%d", &age);
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
}
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = '\0';
printf("%s, %d лет\n", name, age);
return 0;
}17
Анна ПетроваАнна Петрова, 17 летЦикл с getchar() выбрасывает всё, что осталось в строке после числа, вместе с \n. Переменная ch — int, а не char: так её можно сравнить с EOF.
Не используйте fflush(stdin): по стандарту C fflush — только для вывода, а для ввода результат не определён. В старых учебниках этот приём встречается, потому что некоторые компиляторы для Windows так очищали ввод, но полагаться на это нельзя.
scanf зациклился
Если вместо числа ввести буквы, scanf("%d") ничего не прочитает, вернёт 0 и оставит буквы на месте. Цикл while (…) scanf("%d", &x); будет снова и снова натыкаться на те же буквы. Поэтому результат scanf проверяют, а при ошибке выбрасывают остаток строки:
#include <stdio.h>
int main(void) {
int x;
while (scanf("%d", &x) != 1) {
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
}
if (ch == EOF) {
return 1;
}
printf("Это не число, попробуйте снова\n");
}
printf("Принято: %d\n", x);
return 0;
}abc
42Это не число, попробуйте снова
Принято: 42Если ввод кончился совсем (EOF), программа завершается, а не крутится вечно.