Nguyen Huy
Nguyen Huy

Reputation: 45

Weird behavior of getchar()

Currently, I am doing a project in c language in which I have to write a while loop to constant receive either keyboard input or joystick input. The joystick input is okay but for the keyboard input, there are 2 types of inputs: arrow and normal input ('a', 'b', ...). For the keyboard input, I referred to this link (https://stackoverflow.com/a/11432632) to receive arrow keys. Here is my code:

while(true){
    if (getchar() == '\033') { // if the first value is esc
        getchar(); // skip the [
        switch(getchar()) { // the real value
        case 'A':
            printf("arrow up \n");
            break;
        case 'B':
            printf("arrow down \n");
            break;
        case 'C':
            printf("arrow right \n");
            break;
        case 'D':
            printf("arrow left \n");
            break;
        }
    }
    if (getchar() != '\033'){
        printf("non arrow \n");
    }
}

However, the "non arrow" constantly appears even though I pressed arrow button.

If I changed the code from printf("non arrow \n") by have a variable char c, assign getchar() to it and later print c:

    if (getchar() != '\033'){
                printf("non arrow \n");
            }

The output will be as expected for arrow key (receive and print as expected) but nothing appeared when 'e' or 'r' or other single character key is entered.

I wonder what is the problem for my code and how can I modify it to receive behavior as I want.

I hope to receive answer soon.

Thank you, Huy Nguyen.

Upvotes: 0

Views: 57

Answers (1)

Barmar
Barmar

Reputation: 780688

You're reading another character when you do if (getchar() != '\033'), not testing the same character that you tested the first time.

Use else instead of calling getchar() again.

while(true){
    if (getchar() == '\e') { // if the first value is esc
        getchar(); // skip the [
        switch(getchar()) { // the real value
        case 'A':
            printf("arrow up \n");
            break;
        case 'B':
            printf("arrow down \n");
            break;
        case 'C':
            printf("arrow right \n");
            break;
        case 'D':
            printf("arrow left \n");
            break;
        default:
            printf("non arrow\n");
        }
    } else {
        printf("non arrow \n");
    }
}

I've added a default: case to the switch in case they send a different escape sequence. You should probably also check that the first character after ESC is [, not just assume it will be.

If you have more than two conditions, you can use switch(getchar()) there, like you do with the character after ESC [, or you can assign the result of getchar() to a variable and test that in the conditions.

Also, you should use else if when you're testing mutually-exclusive conditions.

Upvotes: 1

Related Questions