Why is _getch() reading a whitespace character?

Notice the following:
1
2
3
4
5
6
	
char foo;
        while (true) {
		foo = _getch();
		cout << foo;
	}


The program is supposed to recognize which key the user pressed on and immediately print it.

But it seems along with the key that the user pressed, _getch() is also reading a single whitespace character.. but why?

How do I make it so that it's not reading this white space character? If we take foo to be integer, we never see 32 appearing (which is the ASCII for single whitespace)


Lastly other than _getch() is there any other thing that I can use which simulates _getch() in that it immediately reads key presses without needing a delimiter like "\n" for istream inputs? Why would this be useful? Suppose you're making a console snake game, then you want the snake to immediately turn on key press, you don't want to have to click on enter..
Everybody knows why it would be useful.
It's just not supported in the standard.
So on windows, there's _getch(). But that's not on linux (although we can do something similar).

Anyway, don't assume the extra character is "whitespace" just because you can't see it.
Are you, perchance, pressing the arrow keys?
Some keys (arrow keys, function keys, etc.) send more than one character code.

Print out the integer values of the characters to see what's going on.
@tpb suppose I press the keys a and b, the console gets "a b" instead of "ab".
And when I take foo as int I get "970980" (when I press the button a then b).

Those are the only two keys I pressed..

I was sort of relying on getch() to make a type what's on the screen game..


Doesn't seem like there's anything similar to _getch() for windows. And there's nothing cross-platform.
What happens when you run this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <conio.h>
#include <cctype>

int main()
{
    std::cout << "enter characters. type 'Q' (upper case) to quit:\n" ;

    int ch ;
    while( ( ch = _getch() ) != 'Q' )
    {
        std::cout << ch ;

        // When reading a function key or an arrow key, the first call returns 0 or 0xE0,
        // and the second call returns the actual key code.
        // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getch-getwch?view=vs-2017
        if( ch == 0 || ch == 0xE0 ) std::cout << " + " << ( ch = _getch() ) << " (function or arrow key)\n" ;

        else if( std::isprint(ch) ) std::cout << " '" << char(ch) << "'\n" ;

        else std::cout << " non printable character\n" ;
    }
}
typing from a to k gives this:
enter characters. type 'Q' (upper case) to quit:
97 'a'
0 + 98 (function or arrow key)
0 + 99 (function or arrow key)
0 + 100 (function or arrow key)
0 + 101 (function or arrow key)
0 + 102 (function or arrow key)
0 + 103 (function or arrow key)
0 + 104 (function or arrow key)
0 + 105 (function or arrow key)
0 + 106 (function or arrow key)
0 + 107 (function or arrow key)
0


Anything specific you want me to do?


Only for the first character typed
std::cout << ch;
is displayed and then for all other iterations I get
(function or arrow key)


It gets even weirder when I type a whole bunch of keys.. like when I typed y and then arrow key and then y I got this:
enter characters. type 'Q' (upper case) to quit:
121 'y'
0 + 224 (function or arrow key)
72 'H'
121 'y'
0
Last edited on
So it's as if a 0 code is being sent after every non-special-key.
Try running it and just pushing up down left right, then a b c.
Post the output.

Is it at all possible that the program is running in a wide character mode and _getch() is seeing a 16-bit character one byte at a time?

If you're running it from an IDE, look for an option to use "regular" characters.
closed account (1vRz3TCk)
It looks like Microsoft's documentation could be wrong?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
#include<conio.h>

int main()
{
    int c1, c2;
    while( (c1 = _getch()) != 'Q')
    {
        c2 = _getch();

        std::cout << "c1: " << c1 << "\t|"<<  "c2: " << c2 << "\t|\n";
    }

	return 0;
}
c1: 97  |c2: 0  |
c1: 98  |c2: 0  |
c1: 99  |c2: 0  |
c1: 100 |c2: 0  |
c1: 101 |c2: 0  |
c1: 224 |c2: 75 |
c1: 224 |c2: 72 |
c1: 224 |c2: 80 |
c1: 224 |c2: 77 |


Edit:
It looks like it may be a bug in the Universal CRT.
https://developercommunity.visualstudio.com/content/problem/247770/-getch-broken-in-vs-157.html
Last edited on
@CodeMonkey, make sure you are compiling the program in a non-wide character (non-unicode?) mode.
> Only for the first character typed
> std::cout << ch;
> is displayed and then for all other iterations I get
> (function or arrow key)

Try this now (wide chars, _getwch):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <conio.h>
#include <ctype.h>

int main()
{
	std::wcout << L"enter characters. type 'Q' (upper case) to quit:\n";

	wint_t ch;
	while ( ( ch = _getwch() ) != L'Q' )
	{
		std::wcout << ch ;

		// When reading a function key or an arrow key, the first call returns 0 or 0xE0,
		// and the second call returns the actual key code.
		// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getch-getwch?view=vs-2017
		if( ch == 0 || ch == 0xE0 ) std::wcout << L" + " << ( ch = _getwch() ) << L" (function or arrow key)\n";

		else if( iswprint(ch) ) std::wcout << L" '" << wchar_t(ch) << L"'\n";

		else std::wcout << L" non printable character\n";
	}
}

closed account (1vRz3TCk)
tpb wrote:
@CodeMonkey, make sure you are compiling the program in a non-wide character (non-unicode?) mode.
:0| but anyway...

So, JLBorges's code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <conio.h>
#include <cctype>

int main()
{
    std::cout << "enter characters. type 'Q' (upper case) to quit:\n";

    int ch;
    while ((ch = _getch()) != 'Q')
    {
        std::cout << ch;

        // When reading a function key or an arrow key, the first call returns 0 or 0xE0,
        // and the second call returns the actual key code.
        // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getch-getwch?view=vs-2017
        if (ch == 0 || ch == 0xE0) std::cout << " + " << (ch = _getch()) << " (function or arrow key)\n";

        else if (std::isprint(ch)) std::cout << " '" << char(ch) << "'\n";

        else std::cout << " non printable character\n";
    }
}


compiled in debug mode gives:
enter characters. type 'Q' (upper case) to quit:
97 'a'
0 + 98 (function or arrow key)
0 + 99 (function or arrow key)
0 + 100 (function or arrow key)
0 + 101 (function or arrow key)
0 + 224 (function or arrow key)
75 'K'
224 + 72 (function or arrow key)
224 + 77 (function or arrow key)
224 + 80 (function or arrow key)


compiled in release mode gives:

enter characters. type 'Q' (upper case) to quit:
97 'a'
98 'b'
99 'c'
100 'd'
101 'e'
224 + 75 (function or arrow key)
224 + 72 (function or arrow key)
224 + 77 (function or arrow key)
224 + 80 (function or arrow key)
0 + 59 (function or arrow key)
0 + 60 (function or arrow key)
0 + 61 (function or arrow key)
0 + 62 (function or arrow key)


edit:
Steve Wishnousky wrote:
The Debug Universal C Runtime (ucrtbased.dll) comes from the Windows 10 SDK and a copy is installed with the Visual Studio installer. The Windows 10 SDK is not currently planning an update until the next major Windows OS Release. In the meantime, I recommend using an older version of the Debug Universal C Runtime from the Windows 10 Fall Creators Update (10.0.16299). Older versions of the Windows SDK can be downloaded from here: https://developer.microsoft.com/en-us/windows/downloads/sdk-archive . For binaries compiled against the Debug Universal C Runtime, the version installed into System32 by Visual Studio will be preferred, but you can copy any ucrtbased.dll version from the Windows SDK and place it beside your binary to do an "app-local" deployment of the Debug Universal C Runtime.
Steve Wishnousky, Software Engineer II - Visual C++ Libraries
Last edited on
CodeMonkey wrote:
but anyway...

I don't get your comment. Clearly I'm correct that it's a wide character problem, and I believe I was the first person to mention it (followed by Borges suggestion to use _getwch).
Last edited on
closed account (1vRz3TCk)
tpb, it was an expression of not being impressed with the suggestion to 'make sure you are compiling the program in a non-wide character (non-unicode?) mode'.

I don't agree that it's a wide character problem
@Nwb Have you considered using PDCurses/NCurses? It's what I use for this type of stuff, and it's cross platform. I'm not as big a fan of the native Windows stuff.
Topic archived. No new replies allowed.