LINUX.ORG.RU

Неочевидное поведение scanf()

 


0

2

Драсте.

Я тут жутко затупил, и не могу понять почему именно так работает.

Есть КОД:

#include <stdio.h>

int main(int aegc, char **argv)
{
	int i, s;
	while (1) {
		s = scanf("%d", &i);
		printf("%d: %d\n", s, i);
	}
	return 0;
}

Когда я в stdin пишу не цифры этот код зацикливается и не даёт мне на следующей итерации писать в in.

~$ ./a.out
3
1: 3
w
0: 3
0: 3
0: 3
0: 3
0: 3
.......
.......
.......
^C

Почему он зацикливается?

★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

Почему он зацикливается?

потому что while(1) {...} является циклом.

MKuznetsov ★★★★★
()

scanf висит и ждёт ввода только тогда, когда нет ничего в stdin (или того, что есть, не хватает для желаемого эффекта, ЕМНИП).

Когда ты печатаешь «w» и жмёшь энтер, в stdin валится строка «w\n», которая скармливается scanf. scanf ничего оттуда не забирает и возвращается с matching failure. При следующем запуске scanf буфер stdin не пустой, поэтому scanf не висит, ожидая ввода, а снова пытается распарсить «w\n» и снова фейлится. И так до бесконечности.

devsdc ★★
()
Ответ на: комментарий от rogerw

А что ты понимаешь под словом «очистить»? Забыть про всё, что пользователь написал? Забыть про часть до '\n'? До пробела?

Я к тому, что забыть про всё, написанное пользователем (что, наверное, ты и имел в виду) — вообще говоря, плохая идея.

devsdc ★★
()
Ответ на: комментарий от rogerw
#include <stdio.h>
#include <string.h>

int main(void)
{
  int i,s;
  char ch;
  char buf[256];
  memset(buf,0,256);
  int indx=0;
  while (1) {
     ch=fgetc(stdin);
     if (ch!='\n'){
       buf[indx++]=ch;
     } else {
        buf[indx]=0;
        sscanf(buf,"%d",&i);
        printf("%d: %d\n", s, i);
        s=0;
        i=0;
        indx=0;
        memset(buf,0,256);
     }
  }
  return 0;
}
Dudraug ★★★★★
()
Последнее исправление: Dudraug (всего исправлений: 2)
Ответ на: комментарий от Dudraug

Я понимаю, что здесь для простоты нет проверки на длину строки (переполнение buf) и EOF. Но переменная ″int s″ зачем нужна то?

mky ★★★★★
()

после

s = scanf("%d", &i);
вставить
if( s == EOF ) { printf("End of file\n"); break; }
if( !s ) { printf("Invalid input\n"); while( getchar() != '\n' ); continue; }

И всё станет хорошо.

Stanson ★★★★★
()
Последнее исправление: Stanson (всего исправлений: 1)
Ответ на: комментарий от Stanson

вот тут ясно просто гетчарами всё высасываем и всё

rogerw
()
Ответ на: комментарий от rogerw

Ну я просто показал как сделать через scanf. С «очищением» stdin. Немного кривовато, не спорю, но и пример же не для продакшена, а для ознакомления с идеей.

Dudraug ★★★★★
()
Ответ на: комментарий от rogerw

Это Уд из Доктора кто. Появляется во 2,4 и вроде 5 (или 6) сезонах.

Dudraug ★★★★★
()
Последнее исправление: Dudraug (всего исправлений: 1)
Ответ на: комментарий от anonymous

Хочешь исключений - пиши на языках с поддержкой исключений.

Aswed ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.