Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - user single char input rendering weird results

Tags:

c

char

input

New here and I have a very simple question. I am making a simple program in C that requires the user to enter a choice of what to do with a char. After they enter the result, the program goes back to the menu. However it seems to take some sort of ghost input as if the char has some unknown value. I need to set the char back to its default state.

Code:

/* display menu for user */
void menu() {

    printf("\n- - - Phone Book Database - - -\n");
    printf("\nSelect an action:\n\n");
    printf("\tc:\tCreate a database entry.\n");
    printf("\ts:\tSearch the database entries.\n");
    printf("\td:\tDelete a database entry.\n");
    printf("\tq:\tQuit program.\n\n");

    printf("Enter choice: ");
    menu_choice = getchar();

    if(menu_choice != 'c' && menu_choice != 's'
        && menu_choice != 'd' && menu_choice != 'q') {
            printf("\n\n\tInvalid choice.\n");
            menu();
    }
    //fflush(stdin);
}

Here is an example output:

- - - Phone Book Database - - -

Select an action:

    c:  Create a database entry.
    s:  Search the database entries.
    d:  Delete a database entry.
    q:  Quit program.

Enter choice: c

Enter name: test

Enter address: test

Enter number: 3

- - - Phone Book Database - - -

Select an action:

    c:  Create a database entry.
    s:  Search the database entries.
    d:  Delete a database entry.
    q:  Quit program.

Enter choice: 
    Invalid choice.

- - - Phone Book Database - - -

Select an action:

    c:  Create a database entry.
    s:  Search the database entries.
    d:  Delete a database entry.
    q:  Quit program.

Enter choice: q

Entering c as an input calls the following function

/* creates a new record in array */
void create_record() {
    char name[MAX];
    char address[MAX];
    int number;

    rec_num++; /* add 1 to marker for record placement */

    printf("\nEnter name: ");
    scanf("%s", name);

    printf("\nEnter address: ");
    scanf("%s", address);

    printf("\nEnter number: ");
    scanf("%d", &number);

    strcpy(record[rec_num].name, name);
    strcpy(record[rec_num].address, address);
    record[rec_num].number = number;
}
like image 308
James Manes Avatar asked Dec 04 '12 16:12

James Manes


2 Answers

Looks like you have your answer already, and reviewing, it is correct; using getchar() will read one character from stdin

printf("Enter choice: ");
menu_choice = getchar();

When I get to this prompt at the console and type c<enter key> it's causing two char's to go to stdin: 'c' and '\n'

The first time getchar(); runs, it picks up just the 'c' leaving the newline character. On the second iteration the '\n' is picked up without waiting on anything from the user; thus is seems as though there is "ghost input".

I just wanted to point out, whenever you're getting input from the user and the results aren't what you've expected it doesn't hurt to just dump it back to verify what's happening, something like:

if(menu_choice != 'c' && menu_choice != 's'
    && menu_choice != 'd' && menu_choice != 'q') {
        printf("\n\n\tYou entered %c (%d).\n", menu_choice, menu_choice);
        printf("\tThat's an invalid choice.\n");
        menu();
}

Would have shown you:

You entered
 (10).
That's an invalid choice.

Between the fact it was on a different line, and checking that decimal result against an ASCII table you'd see that 1010 is the newline character, which could help lead you to a result.

Edit:

1 option for consuming a newline -

printf("what character?");
c = getchar(); // Get the character from stdin
getchar();     // consume the newline character that was left

a second option:

printf("what character?");
scanf("%c ", &c); // Get the character from stdin, note the space after the %c
                  // that will allow any special characters including \t and \n

If you just want to get the character and then end at & consume the '\n', you have to add and escape the newline char:

printf("what character?");
scanf("%c\\n", &c); 
like image 173
Mike Avatar answered Nov 05 '22 02:11

Mike


As others have pointed out, it's the newline character. Just add another

(void) getchar(); /* read and discard newline */

where ever you only want to read one character.

like image 2
Arun Taylor Avatar answered Nov 05 '22 03:11

Arun Taylor