Все 3 формата начинаются с "%[^\n]"
.
"%[^\n]"
- это плохой код 2 , который не имеет ограничения по ширине и подвержен переполнению буфера. Используйте ограничение width , например "%99[^\n]"
с char s[100];
.
"%[...]"
не использует начальные пробелы, как многие другие спецификаторы.
Этот спецификатор направляет ввод для чтения до тех пор, пока не встретится '\n'
1 . '\n'
возвращается в stdin
. Все остальные символы сохраняются в соответствующем целевом массиве s
.
Если символы не были прочитаны (не считая '\n'
), спецификатор не работает и scanf()
возвращает без изменения s
- остальной формат не используется. Нет нулевой символ добавлен.
Если символы были прочитаны, они сохраняются, а нулевой символ добавляется к s
, и сканирование продолжается со следующей части формат.
"\n"
действует так же, как " "
, "\t"
, "any_white_space_chracter"
и считывает и отбрасывает 0 или более пробелов. Это продолжается до тех пор, пока не будет прочитано 1 , отличное от пробелов. Этот непробельный символ возвращается в stdin
.
Данный ввод с буферизацией строки, это означает, что строка с непробельным символом после ввода необходима, чтобы увидеть следующий непробельный и разрешить scanf()
двигаться дальше.
С scanf()
"\n"
в конце формата будет плохим и вызвал проблему OP.
"%*c"
читает 1 символ 1 и отбрасывает его - даже если это не '\n'
. Этот спецификатор не влияет на счетчик возврата из-за '*'
.
Лучшая альтернатива - использовать fgets()
.
char s[100];
if (fgets(s, sizeof s, stdin)) {
s[strcspn(s, "\n")] = '\0'; // To lop off potential trailing \n
Меньшая альтернатива -
char s[100] = { 0 };
scanf("%99[^\n]", s);
// With a separate scanf ....
scanf("%*1[\n]"); // read the next character if it is a \n and toss it.
1 ... или конец файла, или редкая ошибка ввода.
2 IMO, хуже, чем gets()
.