Search code examples
cfgetsgetchar

I have to enter twice for my getchar() to work


I have trobule with getchar(). I have to enter twice for my code to work properly. I write my code like this:

#include<stdio.h>
#include<stdlib.h>
#define MAX_LEN 20

struct part {
    int number;
    char name[MAX_LEN + 1];
} part_1;
 
int main(void){
    int ch, th; 

    for (;;) {
        printf("Enter operation code: ");
        while ( (ch = getchar()) != '\n' && ch != EOF){
            switch (ch){

                case 'i': 
                printf("Enter part number: ");
                scanf("%d",&part_1.number);

                while ( (th = getchar()) != '\n'); /*I use this to remove newline character*/

                printf("Enter part name: ");
                fgets(part_1.name,MAX_LEN,stdin);
                break; 
                
                case 'q': exit(0);
            }
        }
    }
}   

When running the compiler, I expect my result to be like this:

Enter operation code: i
Enter part number: 1
Enter part name: test
Enter operation code: i

However, I have to enter twice for the code to work properly:

Enter operation code: i
Enter part number: 1
Enter part name: test
-> /* This is where I have to press 'Enter' twice */
Enter operation code: i

Solution

  • When you enter a part name and press enter fgets will return and break out from the switch-statement and go back to the while-statement: while ( (ch = getchar()) != '\n' && ch != EOF){. You then need to press enter one more time to make the condition false so that it goes back to the for-statement in which it will print "Enter operation code: " again.

    Basically you want to find a way to break out from both the switch-statement and while-statement when a part name has been read.

    Now, I'm not sure exactly you want it to behave, but you could try to replace the while-statement with:

    [...]
        for (;;) {
            printf("Enter operation code: ");
            ch = getchar();
            if (ch != '\n') getchar();  // remove linebreak from stdin
            switch (ch){
    [...]
    

    with that the output will look like this:

    Enter operation code: a
    Enter operation code: b
    Enter operation code: c
    Enter operation code: i
    Enter part number: 1234
    Enter part name: hello
    Enter operation code: d
    Enter operation code: e
    Enter operation code: f
    Enter operation code:
    Enter operation code:
    Enter operation code: q