Не могу понять, что происходит с scanf ("% [^ \ n] \ n", ввод) на языке C - PullRequest
4 голосов
/ 24 февраля 2020
char str[20];
scanf("%[^\n]\n", str);
printf(">>>>%s\n", str);

Это мое понимание: первая часть "[^ \ n]" означает принятие любого символа, кроме '\ n', чтобы получить какой-либо символ, например пробел, из функции scanf и сохранить его в str. Второе значение \ n соответствует совпадению с \ n, которое завершает сканирование, в противном случае \ n освободит поток ввода и оставит для следующего действия ввода.

Но когда я его запустил, результат меня смутил.

xhkjdeiMac:c xhkj$ ./hello
aaaaaaa
ccc
>>>>aaaaaaa

Как видите, я сначала захожу в aaaaaaa и нажимаю клавишу ввода, я думаю, что он сохраняет aaaaaa в str и уже соответствует \ n. Но мне нужно ввести что-то еще, например ccc, затем я могу go перейти к следующему шагу и распечатать str на консоли.

Так почему же это произошло? почему я должен ввести что-то еще и снова нажать клавишу ввода, чтобы завершить sh сканирование?

1 Ответ

1 голос
/ 24 февраля 2020
char str[20];
scanf("%[^\n]\n", str);

OP: первая часть "[^\n]" означает принятие любого символа, кроме '\ n', для получения какого-либо символа, .... и сохранения его в str.

* 1006. *

Не совсем.

Если первым прочитанным символом является '\n', сканирование прекращается. Ничего не сохраняется в str, нулевой символ не добавляется, '\n' остается в stdin и функция возвращает 0 или EOF (я забыл, но это не 1)

Иначе не- '\n' символы читаются и сохраняются до считывания '\n'. '\n' возвращается в stdin, нулевой символ добавляется к str. Сканирование продолжается в формате "\n". Если было прочитано 20 или более символов, результат будет неопределенное поведение .


Основная проблема

OP: Второй \ n соответствует совпадению \ n, которое завершает сканирование, в противном случае \ n освободит поток ввода и оставит для следующего действия ввода.

Нет. Формат "\n" соответствует любому количеству пробелов, а не только 1 '\n'. scanf() потребляет пробелы, такие как '\n', ' ', '\t', ..., до тех пор, пока не будет прочитан символ, не являющийся пробелом. Этот символ, не являющийся пробелом, затем возвращается в stdin.

ОП: зачем мне вводить что-то еще и снова нажимать клавишу ввода, чтобы завершить sh сканирование?

Программа ожидает символ пробела, прежде чем он возвращается. Поскольку stdin обычно строка в буфере, этот символ, не являющийся пробелом, не присваивается scanf() до тех пор, пока у него не появится следующий '\n'.


scanf("%[^\n]\n", str); проблематично c. Используйте fgets(). Проверьте возвращаемые значения.

char str[20];
if (fgets(str, sizeof str, stdin)) {
  str[strcspn(str, "\n")] = '\0'; // lop off potential trailing \n if desired
  printf(">>>>%s\n", str);
}

Если один, знак , должен использовать scanf(), рассмотрите:

*str = 0;              // Handle case when first letter is \n
scanf("%19[^\n]", str);// Consume up to 19 characters
scanf("%*1[\n]");      // Consume 1 \n if present-independent of success of previous
...