scanf: «%[^,]s» против «%[^,],s»

#c #scanf

#c #scanf

Вопрос:

Я прочитал это здесь, но я не могу это понять.

 //assume a and b are char arrays

scanf("%[^,]s",a);     // first scanf()

scanf("%[^,],s",b);    // second scanf() 
  

Я могу понять, что первый scanf() будет сканировать строку до ',' обнаружения. Но как насчет второго?

В этой ссылке говорится, что первая scanf() не уничтожит запятую, в то время как вторая ее уничтожит.

Что именно trash the comma означает?

Комментарии:

1. удалить s из "%[^,]s" и ("%[^,],s"

2. Вы неправильно процитировали исходную ссылку. В строках формата нет s . «Мусор» означает «удалить из входного потока». Второй scanf удалит , , что означает, что другой getchar() прочитает следующий символ после запятой.

Ответ №1:

scanf("%[^,]s",a); прочитает до , и затем оставит , во входном буфере .
scanf("%[^,],s",a); прочитает до , и после прочтения , отбросит это.

И оба они будут считывать и отбрасывать конечную строку s .

Попробуйте этот пример кода и увидите разницу:

 #include <stdio.h>
int main()
{
   char a[10];
   char b;
   scanf("%[^,]s",a);
   //scanf("%[^,],s",b); 
   scanf("%c", amp;b);
   printf("%sn%c", a, b);
}
  

Комментарии:

1. спасибо, но сначала это также отбрасывается, я имею в виду, что если мы напечатаем это с помощью printf (), то результат будет таким же

2. @A.s.Bhullar Нет, первый не отбрасывает его. Разница в том, что осталось во входном потоке .

3. Ты имел в виду scanf("%[^,],s",a) во втором случае, верно?

4. @Chnossos; Да. Это была опечатка. Я пропустил это , 🙂

5. Вы пробовали этот код: #include <stdio.h> int main() { char a[10]; char b; scanf("%[^,]s",a); scanf("%c", amp;b); printf("%sn%c", a, b); } ?

Ответ №2:

Обратите внимание, что %[…] это само по себе является полной спецификацией преобразования. Подробные сведения см. в спецификации POSIX для scanf() или на справочной странице вашей системы.

Из ваших двух утверждений:

 scanf("%[^,]s",a);     // first scanf()
  

Такого рода работы, но на самом деле не делают того, что вы (вероятно) ожидаете от этого. Он считывает последовательность символов без запятой вплоть до первой запятой, а затем не соответствует s , но не имеет способа сообщить об этом сбое. Следующим символом из входных данных будет запятая (или EOF, если во входных данных нет запятых).

 scanf("%[^,],s",b);    // second scanf() 
  

Это тоже вроде как работает, но тоже делает не совсем то, что вы ожидаете. Он считывает последовательность символов без запятой, затем запятую, а затем s , но у него также нет способа сообщить, прочитал ли он запятую или s после нее. Если во входных данных есть запятая и s после нее, то следующим входным символом будет тот, который следует за s . Если есть запятая и не- s , то следующим прочитанным символом будет не- s . В противном случае следующее чтение вернет EOF.

Оба оператора написаны плохо. Было бы намного лучше, если бы код проверял статус возврата и был записан как:

 if (scanf("%[^,],s", b) != 1)
    …report problem…
  

Обратите внимание, что если следующим символом во входных данных является запятая, все операторы вернут 0, указывая, что никакая информация не была доступна для чтения b .

Комментарии:

1. «Такого рода работы, но на самом деле не делают того, что вы ожидаете». Не имеете ли вы в виду «но не по той причине, о которой вы думаете».? В любом случае 1.

2. Есть ли существенная разница между двумя вариантами? Я немного изменил формулировку (с помощью «вероятно»), но я не вижу существенной разницы между «работает, но не делает того, что вы ожидаете» и «работает, но не по той причине, о которой вы думаете».

3. Да, есть существенная разница. Вы точно объяснили, почему это работает так, как ожидалось, даже если s не является частью спецификатора формата. Причина полностью отличается от ожидаемой.

Ответ №3:

Они оба помещают одни и те же символы в целевую переменную (a или b), но во втором ТАКЖЕ пропускается запятая, так что СЛЕДУЮЩЕЕ чтение не начнется с нее.