2013-12-24 2 views
3

Я пишу программу, которая использует fgets() для сканирования строки длиной 3 символа в виде кода аэропорта для вылета и прибытия. Когда я пишу заявление вне его метода (в основном), он отлично работает, но внутри него не ждет ввода и оставляет переменные пустыми.fgets() не работает в функции

void newFlight() 
    { 
     printf("\n"); 
     printf("============= CREATE A NEW FLIGHT ============= \n"); 
     printf("Type 0 at any point to exit to main menu. \n"); 
     printf("\n"); 

     printf("EnterFlight ID (0 to cancel) : "); 
     scanf("%d", &flyList[curFly].flightID); 

     char codeA [4]; 
     printf ("Enter Destination (Airport Code): "); 
     fgets(codeA, 3, stdin); 
     strcpy(codeA, flyList[curFly].arrive); 
     printf("%s %s \n", codeA, flyList[curFly].arrive); //TEST 

     printf("Enter Place Of Departure: "); 
     char codeD[4]; 
     scanf("%s", codeD); 
     strcpy(codeD, flyList[curFly].depart); 
     printf("%s %s \n", codeD, flyList[curFly].depart); //TEST 

     printf("Enter Date Of Departure (DD MM YYYY): "); 
     scanf("%hd %hd %hd", &flyList[curFly].timeOfDep.day, &flyList[curFly].timeOfDep.month, &flyList[curFly].timeOfDep.year); 

     printf("Enter Time Of Departure (HH MM)in 24Hr Format: "); 
     scanf("%hd %hd", &flyList[curFly].timeOfDep.hour, &flyList[curFly].timeOfDep.minute);  

     curFly++; 
    } 
+0

Я добавил fflush (stdin); теперь он ждет ввода, но не принимает его ... –

+0

scanf остается новой строкой. и переписать следующий 'strcpy (codeA, flyList [curFly] .depart);' – BLUEPIXY

+0

@Barmar Я проверил это, я не думаю, что это то же самое, что и проблема с итерациями, моя проблема связана с фактическим сканированием строки –

ответ

1

Смешивание fgets() с scanf() проблематично.

fgets() потребляет (\n).
scanf("%d", ... видит \n, который останавливает %d преобразования и помещает \n обратно в stdin для следующего операции ввода-вывода - который СЛУЧИЛСЯ быть OP-х fgets(), который возвращает быстро с короткой строкой.

Также необходимо проверить результаты scanf(). указав ширину с "%s, это хорошо, как "%3s.

Быстрое решение: только с помощью scanf()

// scanf("%d", &flyList[curFly].flightID); 
if (1 != scanf("%d", &flyList[curFly].flightID)) handle_error(); 
... 
char codeA [4]; 
// fgets(codeA, 3, stdin); 
if (1 != scanf("%3s", codeA) handle_error(); 
... 
// Likely backwards 
// strcpy(codeA, flyList[curFly].arrive); 
strcpy(flyList[curFly].arrive, codeA); 
... 
char codeD[4]; 
// scanf("%3s", codeD); 
if (1 != scanf("%3s", codeD)) handle_error(); 
... 
// scanf("%hd %hd %hd", &flyList[curFly].timeOfDep.day, &flyList ... 
if (3 != scanf("%hd %hd %hd", &flyList[curFly].timeOfDep.day, &flyList[curFly].timeOfDep.month, &flyList[curFly].timeOfDep.year)) handle_error(); 
... 
// scanf("%hd %hd", &flyList[curFly].timeOfDep.hour, &flyList ... 
if (2 != scanf("%hd %hd", &flyList[curFly].timeOfDep.hour, &flyList[curFly].timeOfDep.minute)) handle_error(); 

Лучшее решение: использовать fgets()/sscanf()

// scanf("%d", &flyList[curFly].flightID); 
char buf[100]; 
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOForIOError(); 
if (1 != sscanf(buf, "%d", &flyList[curFly].flightID)) handle_parse_error(); 
... 
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOForIOError(); 
if (1 != sscanf(buf, "%3s", flyList[curFly].arrive) handle_parse_error(); 
... 
etc. 

КСТАТИ: формат scanf()"%hd %hd" и "%hd%hd" делать то же самое.

+0

Спасибо, что это отлично работает Я думаю, что я буду использовать основное решение, так как это мое первое задание в C. Не могли бы вы объяснить «if (1! = Scanf («% d », & flyList [curFly] .flightID)) handle_error(); ', который используется для сканирования строк еще раз спасибо –

+0

'% d' говорит' scanf() 'искать' int'. В случае успеха 'scanf()' возвращает 1 как 1 спецификатор. Если 0 (нет 'int' найдено) или' EOF' (ошибка конца файла или IO), выполняется функция 'handle_error()'. 'handle_error()' - это просто фиктивное имя для вашего кода о том, как вы будете обрабатывать незаконный вход, - который я нахожу более легким во втором решении. – chux

+0

Возможно, это будет поздно .. Но вы также можете предложить способ обойти, если есть переполнение, а следующий fgets - не автоматически. Я имею в виду, что если входная строка больше, чем размер массива символов, следующий массив символов будет назначен автоматически. Одно из решений, о котором я могу думать, - использовать fseek и перемещать указатель stdin до конца. –

1

проблема исходит не от fgets а от scanf, потому что, когда эта линия выполнена scanf("%d", &flyList[curFly].flightID); и после того, как вы нажмете ввести новую строку charactere остается в буфере так, когда вы звоните fgets он сразу же уделяется он так действует, как будто вы нажимаете Enter и двигаетесь дальше. один простой способ, чтобы предотвратить это, чтобы положить getchar после каждого scanf так, что он получает символ новой строки вместо

Смежные вопросы