0

I am writing a basic program in C using Windows API to read from standard input and display it flawlessly on the standard out. The whole program works great but as soon as I quit the program, there are some trailing characters left behind on a terminal input. Maybe I am a little bit too picky about it but for me, it is too frustrating.

The code is the following:

#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>

/*********************************************************/

/* ClearScreen function definition .... */


struct Keys {
    unsigned int k1: 1;
    unsigned int k2: 1;
    unsigned int k3: 1;
    unsigned int k4: 1;
};

void check_key(struct Keys* keys)
{
    keys->k1 = 0; keys->k2 = 0; keys->k3 = 0; keys->k4 = 0; 
    if (GetKeyState('A') & 0x8000)
    {
        keys->k1 = 1;
    }
    if (GetKeyState('S') & 0x8000)
    {
        keys->k2 = 1;
    }
    if (GetKeyState('D') & 0x8000)
    {
        keys->k3 = 1;
    }
    if (GetKeyState('F') & 0x8000)
    {
        keys->k4 = 1;
    }
}

void print_keys(struct Keys keys)
{
    ClearScreen();
    printf("K1 = %d | K2 = %d | K3 = %d | K4 = %d",
            keys.k1, keys.k2, keys.k3, keys.k4);
    printf("\n");
    printf("P1 = 1");
}

int main ()
{
    hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
    if (hStdOut == INVALID_HANDLE_VALUE) return -1;

    struct Keys keys = {0, 0, 0, 0};

    while (1)
    {
        check_key(&keys);
        print_keys(keys);
        Sleep(100);
    }

    CloseHandle(hStdOut);

    return 0;
}

Example:

Let's say I am running this program and input the following keystrokes sequence "zczxcvcvbxxvbc". After the execution of the program I am left with this on my terminal: enter image description here

What I want to achieve is to have clear terminal input after usage, without those characters in place.

Is there any way to achieve this?

satk0
  • 170
  • 1
  • 9
  • `GetKeyState` is not a good idea. Using `scanf`? Try `printf( "\r\n" );` at the end. – i486 Mar 01 '23 at 19:48
  • 1
    The program hasn't requested any input. So the buffered input you typed appeared afterwards, in the shell. A windows program could do `while(kbhit()) getch();` in the loop to adsorb those key presses. – Weather Vane Mar 01 '23 at 19:49
  • @i486 That would not make this program as interactive as it is. – satk0 Mar 01 '23 at 19:53
  • Why not? What I suggested is non-blocking. Place it before the `Sleep`. – Weather Vane Mar 01 '23 at 19:53
  • 1
    @WeatherVane Please make it an answer so I can set it as a solution ;D – satk0 Mar 01 '23 at 19:56
  • 1
    Side note: I suggest that you use the function [`ReadConsoleInput`](https://learn.microsoft.com/en-us/windows/console/readconsoleinput) instead of `GetKeyState`. That way, you will be using a proper queue of keypress events. I don't think that `GetKeyState` was designed to be used the way you are using it. – Andreas Wenzel Mar 01 '23 at 19:58
  • @AndreasWenzel I am really interested in how it could be implemented. I used `GetKeyState` in order to avoid hitting *Enter* each time I want to use a keystroke. – satk0 Mar 01 '23 at 20:05
  • If you use MSVC's `getch` or `getche` you don't need to hit Enter. Obviously it's no more portable than your `winapi` calls. There are also ways to make `getchar` work unbuffered. – Weather Vane Mar 01 '23 at 20:17
  • 1
    You may want to take a look at [this answer of mine to another question](https://stackoverflow.com/a/72394274/12149471) for an example of waiting for and reading keypresses using `ReadConsoleInput` and `WaitForSingleObject`. – Andreas Wenzel Mar 01 '23 at 20:38
  • @AndreasWenzel, WeatherVane Thank you both, would definitely check those functions out ! – satk0 Mar 01 '23 at 20:52
  • 1
    @Urax: If you are only looking for something simple, then using `_kbhit`, `_getch` and `_getche` may be sufficient. Using `ReadConsoleInput` is more powerful and flexible, but also more complicated. – Andreas Wenzel Mar 01 '23 at 22:16

1 Answers1

2

The program hasn't requested any input. So the buffered input you typed appeared afterwards, in the shell. A windows program could do

while (1)
{
    check_key(&keys);
    print_keys(keys);
    while(kbhit()) 
       getch(); 
    Sleep(100);
}

in the loop to adsorb those key presses.

You might want to use _kbhit and _getch to avoid compiler warnings.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56