scanf_s не читает ввод при повторном вызове

124
18 августа 2021, 17:20
char s[11];
if (scanf_s("%[a-z]s", s, 10)) printf("String1: %s\n", s);
if (scanf_s("%[a-z]s", s, 10)) printf("String2: %s\n", s);

Output:

abcABC
String1: abc

В чём причина такого поведения scanf_s и как это исправить? Если не использовать модификатор набора символов, всё работает как надо:

char s[11];
if (scanf_s("%s", s, 10)) printf("String1: %s\n", s);
if (scanf_s("%s", s, 10)) printf("String2: %s\n", s);

Output:

abc
String1: abc
XYZ
String2: XYZ
Answer 1
  • Во-первых, форматная строка "%[a-z]s" рассматривается scanf как спецификатор формата %[a-z] за которым следует посторонний самостоятельный символ s. Все самостоятельные символы в форматной строке (кроме пробельных) рассматриваются scanf как требование того, чтобы такой символ присутствовал во входной строке. В ваших входных строках никакого s нет. В результате первый scanf завершается досрочно по ошибке несоответствия формата, хоть и после успешного прочтения abc. Он возвращает 1, т.е. первый printf срабатывает.

    Что такое "%[a-z]s"? Зачем вы поместили туда это s? Формат %[] является самодостаточным форматом scanf. В нем нет и никогда не было никакого s после ].

  • Во-вторых, при входе abcABC ваш первый scanf читает успешно abc, что вы и наблюдаете, а остаток строки - ABC - остается во входном буфере. Ваш второй scanf ничего не читает, так как вход ABC не соответствует формату %[a-z]. Если спецификатору формата не удалось ничего прочитать, scanf не читает пустую строку, а завершается досрочно по ошибке несоответствия формата. Второй scanf возвращает 0, поэтому ваш второй if не срабатывает. Как и должно быть.

  • В-третьих, все форматы scanf, кроме форматов %[] и %c, осуществляют изначальное пропускание пробельных символов во входном потоке, перед тем как начать собственно чтение. Если вы введете на вход вашего кода строку abc с последующим нажатием Enter, то во входном буфере образуется последовательность abc\n. Первый scanf успешно прочитает abc, но символ \n не совпадает с символом s, требуемым первым scanf. Поэтому первый scanf завершится и оставит символ \n во входном потоке. Второй scanf начнет чтение именно с этого символа \n. Так как символ \n не соответствует формату %[a-z] второй scanf ничего прочитать не сможет и вернет 0.

READ ALSO
Для чего устанавливать поток в состояние fail()?

Для чего устанавливать поток в состояние fail()?

Из книги "ПрограммированиеПринципы и практика использования с++"

110
Сортировка строки,содержащей числа,не используя стандартные библиотечные функции.C++

Сортировка строки,содержащей числа,не используя стандартные библиотечные функции.C++

вообше то неправильно выполнить задание за вас, но я решил помочь вам кое в чемВо первых нужно сравнивать строки так, чтобы сравнивались...

214
Для какого типа представления графа написан этот алгоритм (BFS)

Для какого типа представления графа написан этот алгоритм (BFS)

На emaxx начал изучать алгоритмыДошел до графов

121
Assertion failed: !hook.is_linked() в Boost

Assertion failed: !hook.is_linked() в Boost

Не могу понять из-за чего выскакивает исключение "Assertion failed: !hookis_linked(), file d:\boost_1_71_0\boost_1_71_0\boost\intrusive\detail\generic_hook

168