scanf не чете вход

Прочетох още теми за scanf и намерих някои отговори, но никой не ми помогна:

while(!comanda){
    int tmp;
    if (scanf("%d", &tmp) == 0)
        getchar();
    else{
        comanda = tmp;
        fprintf(stdout,"%d",&comanda);
        fflush(stdout);}
    }
}

Проблемът е, че след като тези редове код се изпълнят, нищо не се случва. След това имам проверка на "comanda", която не се изпълнява.


person Octavian    schedule 13.03.2011    source източник
comment
fprintf(stdout,"%d",&comanda); - & не трябва да е там. Само като странична бележка.   -  person dialer    schedule 13.03.2011
comment
моля, бъдете по-конкретни. къде спира кодът, когато кажеш, че нищо не се случва? къде блокира?   -  person Mat    schedule 13.03.2011
comment
Редактирано. Сега трябва да има смисъл.   -  person Octavian    schedule 13.03.2011
comment
На какво е равна командата първоначално?   -  person jonsca    schedule 13.03.2011
comment
Първоначално командата е равна на нула. Това е проблем със scanf, който приема новия ред в буфера или нещо подобно.   -  person Octavian    schedule 13.03.2011


Отговори (2)


Един от проблемите с scanf и всички форматирани функции за въвеждане е, че терминалите обикновено работят в линеен режим или варен режим и API е предназначен за суров режим. С други думи, scanf реализациите обикновено няма да се върнат, докато не се срещне прехвърляне на ред. Входът е буфериран и бъдещите извиквания към scanf ще консумират буферираната линия. Помислете за следната проста програма:

#include <stdio.h>

int main() {
    int a_number;
    printf("Enter a number: ");
    fflush(stdout);
    while (scanf("%d", &a_number) != EOF) {
        printf("you entered %d\n", a_number);
        printf("Enter another number: ");
        fflush(stdout);
    }
    return 0;
}

Можете да въведете няколко числа, преди да натиснете return. Ето пример за изпълнение на тази програма.

bash$ gcc foo.c
bash$ ./a.out
Enter a number: 1 2 3 4 5 6 7 8 9 10<Return>
you entered 1
Enter another number: you entered 2
Enter another number: you entered 3
Enter another number: you entered 4
Enter another number: you entered 5
Enter another number: you entered 6
Enter another number: you entered 7
Enter another number: you entered 8
Enter another number: you entered 9
Enter another number: you entered 10
Enter another number: <Ctrl+D>bash$ 
bash$

Всяко повикване към scanf прочете едно число от входния поток, но първото повикване не се върна, докато не натиснах return. Останалите обаждания се върнаха незабавно, без блокиране за повече входни данни, тъй като входният поток беше буфериран и можеше да прочете друго цяло число от потока.

Алтернативите на това са да използвате fgets и да обработвате цели редове от данни наведнъж или да използвате терминален интерфейс за деактивиране на "канонична обработка на въвеждане". Повечето хора използват fgets, тъй като разделът на терминалния интерфейс на POSIX не е внедрен под Windows.

person D.Shawley    schedule 13.03.2011

Вашият scanf("%d", &tmp) може да върне една от 3 стойности

  • ако върне 1, това означава, че стойността е прочетена и поставена в tmp
  • ако върне 0, това означава, че е имало лош знак в буфера (който откривате и се отървавате от следващото getchar())
  • ако върне EOF, това означава, че stdin е в състояние край на файла. Без значение колко getchar()s правите, условието „край на файла“ не изчезва и вие оставате в безкраен цикъл.

Също така тествайте върнатата стойност от scanf за EOF.

while(!comanda){
    int tmp;
    int ret;
    ret = scanf("%d", &tmp);
    if (ret == 0)
        getchar();
    else if (ret == EOF){
        perror("stdin end-of-file");
        break; /* get out of the loop */
    }
    else {
        comanda = tmp;
        fprintf(stdout,"%d",comanda); /* & is an error */
        fflush(stdout);}
    }
}

Или дори по-добре, повторете програмата си, за да прочете цял ред с fgets() и да го анализира с sscanf().

person pmg    schedule 13.03.2011