Почему для scanf() отрицательный набор сканирований %[^\n] показывает правильный вывод для \n, но не скансет %[aeiou] для aegis?

В следующей программе, если я использую строку для инвертированного набора сканов, она отлично работает, если я ввожу строку из нескольких слов (заканчивающуюся на ENTER или новую строку), даже если новая строка находится в инвертированном списке.

Но если вместо этого я использую строку для скансета и ввожу слово «эгида» (или любое слово с согласными, если уж на то пошло), то выводятся ненужные символы. По аналогии с первым случаем, если я ввожу это слово, должно быть выведено как минимум "ae"? Объясните, пожалуйста, такое поведение набора сканирований и инвертированного набора сканирований для scanf().

#include <stdio.h>

int main ()
{
char str[30];
 printf("Enter the string\n");
 //scanf("%[^\n]",str);
 //scanf("%[aeiou]",str);
 printf("%s",str);
}

person Thokchom    schedule 24.10.2015    source источник
comment
Я не знаю, какой результат вы получите, но он работает правильно - ideone.com/AhfcSL   -  person ameyCU    schedule 24.10.2015
comment
Предоставьте минимальный воспроизводимый пример   -  person Spikatrix    schedule 24.10.2015
comment
@ameyCU Я использую кодовые блоки. В любом случае, всегда ли это будет работать так, как в вашей ссылке ideone? Это всегда ожидаемое поведение?   -  person Thokchom    schedule 24.10.2015
comment
@Thokchom Да, он всегда будет выдавать ожидаемый результат.   -  person ameyCU    schedule 24.10.2015


Ответы (1)


Это потому, что код по ошибке не проверяет возвращаемое значение scanf()

printf("Enter the string\n");
scanf("%[^\n]",str);
scanf("%[aeiou]",str);  // check result before using `str`
printf("%s",str);

С помощью scanf("%[^\n]",str); и ввода типа "123\n" str получает значения "123" а '\n' остается в stdin. Затем с scanf("%[aeiou]",str); и вводом типа "aegis\n" первая строка '\n' блокирует сохранение чего-либо, поскольку '\n' не является гласной, ничего не сохраняется в str и, поскольку код не проверяет возвращаемое значение scanf(), не понимает, что str может быть недействительным.

1) Всегда проверяйте возвращаемое значение scanf() и семейства.

if (scanf(some_format, var1, var2, ...) != ExpectedConversionCount) {
  Fail();
}

2) scanf("%[^\n]",str); прочитать строку не удается 3 вещи: нет ограничений на ввод, не удается ничего прочитать, если строка состоит только из '\n'. Без проверки возвращаемого значения EOF не обнаруживается.

3) Используйте fgets() вместо scanf() для пользовательского ввода.

person chux - Reinstate Monica    schedule 24.10.2015
comment
Боюсь, в моем вопросе не упоминается использование обоих scanf() — одного с набором сканов, другого с отрицательным набором сканов — одновременно. Таким образом, в первой строке нет ничего, что блокировало бы '\n'. Обратитесь к ссылке ideone, предоставленной пользователем ameyCU. Он правильно поставил вопрос. - person Thokchom; 25.10.2015
comment
@Thokchom Лучше опубликовать критический элемент вашего вопроса здесь, а не полагаться на сторонний сайт. - person chux - Reinstate Monica; 25.10.2015
comment
Я имею в виду, что я не использовал обе строки scanf() в своей программе. Я использую только одну строку за раз (комментируя другую). Я сослался на эту ссылку, так как ameyCU правильно ответил на вопрос. Будет полезно, если вы сможете ответить, исходя из этой предпосылки. - person Thokchom; 25.10.2015
comment
@Thokchom Пост, раскомментировавший 1 и только 1 из 2 прокомментированных строк, с одним вводом "aegis", после чего вывод ненужных символов невозможен IMO. Поэтому я подозреваю, что некоторые элементы представленных фактов ошибочны. Тем не менее, лучшее грубое действие, если все еще то же самое: проверить результаты функции ввода кода, прежде чем пытаться использовать str. Попробуйте воссоздать проблему и сообщите о возвращаемом значении scanf(). Если у вас возникли проблемы с повторным созданием, подозревайте, что проблема возникла с версией кода, в которой обе scanf() лжи закомментированы - как в опубликованной. - person chux - Reinstate Monica; 25.10.2015