fgets() not working in a function

16,978

Solution 1

Mixing fgets() with scanf() is problematic.

fgets() consumes the Enter (\n).
scanf("%d", ... sees the \n, which stops the %d conversion, and puts \n back into stdin for the next IO operation - which happend to be OP's fgets() which returns promptly with a short string.

Also need to check scanf() results. specifying a width with "%s is good, like "%3s.

Quick solution: only using 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();

Better solution: use 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.

BTW: scanf() format "%hd %hd" and "%hd%hd" do the same thing.

Solution 2

the problem isn't coming from fgets but rather from scanf because when this line is executed scanf("%d", &flyList[curFly].flightID); and after you hit enter the newline charactere stays in the buffer so when you call fgets it is immediately given to it so it acts as if you hit Enter and moves on . one simple way to prevent this from happening is to put a getchar after every scanf so that it receives the newline character instead

Share:
16,978
Matthew Cassar
Author by

Matthew Cassar

Updated on June 04, 2022

Comments

  • Matthew Cassar
    Matthew Cassar almost 2 years

    I am writing a program which uses fgets() to scan a 3 Char long string as an Airport code for Departure and arrival. When I write the statement outside its method (in the main) it works fine however inside it does not wait for input and leaves the variables blank.

    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++;
        }