By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,388 Members | 1,770 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,388 IT Pros & Developers. It's quick & easy.

how to read a single keystroke in C++

P: n/a
Hi,

probably a stupid question, but I haven't been able to find anything.

Is there a istream related function that let me read exactly one keystroke
from the keyboard through cin?

What I need it to do is this:
- remove all characters currently in the input buffer
- block until the user presses a key
- return the ascii code of the key that was pressed

This should work also, if the user just hit the enter key.

I'm probably too stupid to get it right, but the usual get/getline()
functions always block until the user hits enter, even if the user enteres
other keys before, but on the other hand, if the user presses enter only,
getline continues to block and does not return the empty line.

Ideally I would like somethink like this:

1. a menu, where the user can press 1, 2 or 3 (and the program reactiving
immediately without the need for the user to press enter afterwards)
2. a "Press any key to continue" function, that waits for exactly one
keystroke, no matter what key it is.

Frank
Jul 23 '05 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Frank Bormann wrote:
probably a stupid question, but I haven't been able to find anything.

Is there a istream related function that let me read exactly one keystroke
from the keyboard through cin? [...]


There is no such thing as 'keyboard' AFA C++ _language_ is concerned.
Jul 23 '05 #2

P: n/a

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:cZ*******************@newsread1.mlpsca01.us.t o.verio.net...
Frank Bormann wrote:
probably a stupid question, but I haven't been able to find anything.

Is there a istream related function that let me read exactly one keystroke from the keyboard through cin? [...]


There is no such thing as 'keyboard' AFA C++ _language_ is concerned.


Ok, let me ask differently: How can I determine, if there are chars to read
in the cin streambuf without blocking? I've tried to use in_avail() and
readsome(), but they always return 0 on cin, even if there's still input
data present in the buffer.
Jul 23 '05 #3

P: n/a
Frank Bormann wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:cZ*******************@newsread1.mlpsca01.us.t o.verio.net...
Frank Bormann wrote:
probably a stupid question, but I haven't been able to find anything.

Is there a istream related function that let me read exactly one
keystroke
from the keyboard through cin? [...]


There is no such thing as 'keyboard' AFA C++ _language_ is concerned.

Ok, let me ask differently: How can I determine, if there are chars to read
in the cin streambuf without blocking? I've tried to use in_avail() and
readsome(), but they always return 0 on cin, even if there's still input
data present in the buffer.


Let me ask you, then. If 'in_avail' or 'readsome' returns 0, what makes
you think that "there's still input data present"? I mean, if you have
some other way of knowing that there are data in the stream, why don't
you use the same method to read it? Catch my drift?
Jul 23 '05 #4

P: n/a
Frank Bormann wrote:
Ok, let me ask differently: How can I determine, if there are chars to read
in the cin streambuf without blocking? I've tried to use in_avail() and
readsome(), but they always return 0 on cin, even if there's still input
data present in the buffer.

I suppose in most PCs, cin accepts input only after you press Enter, so the closest thing
I can suggest is using the old, good, system-dependent extensions, getch() and getche()
(the second echoes the input). It is usually defined in conio.h when it is available.

They are not part of the C++ standard though.
--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #5

P: n/a

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:xC*******************@newsread1.mlpsca01.us.t o.verio.net...
Let me ask you, then. If 'in_avail' or 'readsome' returns 0, what makes
you think that "there's still input data present"? I mean, if you have
some other way of knowing that there are data in the stream, why don't
you use the same method to read it? Catch my drift?


There's still input data present, because get() or getline() reads it. My
problem currently is this:

I want some "Press any key to continue" like implementation. Or at least
"Press <return> to continue" which would be less nice but still acceptable.
Now, if I use cin.getline() to try and read such input, the cin.getline()
call never returns, if the user just presses the <return> key (apparently
because it's an empty line and getline discards that). If instead I use
"char c; cin.get(c);" and the user instead of just pressing <return> had
entered some other characters before pressing return, I read only the first
character and the others remain in the buffer. Now, the next time, program
flow comes across this "Press <return> to continue" code, the cin.get(c)
immediately reads the first of the characters that are still in the buffer
from the previous input. I can of course call
cin.ignore(numeric_limits<streamsize>::max()); as described in the C++ FAQ
to get rid of those characters, but if I do that and the buffer was already
empty, it never returns from the cin.ignore() call, no matter what I enter.
So I need to have a non-blocking way of knowing, if there are characters in
the cin buffer, so I can check before calling ignore.

Frank
Jul 23 '05 #6

P: n/a

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1113529832.856545@athnrd02...
Frank Bormann wrote:

I suppose in most PCs, cin accepts input only after you press Enter, so the closest thing I can suggest is using the old, good, system-dependent extensions, getch() and getche() (the second echoes the input). It is usually defined in conio.h when it is

available.

I was afraid, you were going to say that. I was thinking about that too, I'm
sure, I could easily manage to get what I want, by using the low-level file
descriptor i/o of the glibc, but I was hoping to find a system-independent
solution.

Frank
Jul 23 '05 #7

P: n/a
Frank Bormann wrote:
[...]


You might want to consult the FAQ at:

http://www.parashift.com/c++-faq-lit...html#faq-15.17

HTH,
- J.
Jul 23 '05 #8

P: n/a
Frank Bormann wrote:

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:xC*******************@newsread1.mlpsca01.us.t o.verio.net...
Let me ask you, then. If 'in_avail' or 'readsome' returns 0, what makes
you think that "there's still input data present"? I mean, if you have
some other way of knowing that there are data in the stream, why don't
you use the same method to read it? Catch my drift?
There's still input data present, because get() or getline() reads it. My
problem currently is this:

I want some "Press any key to continue" like implementation. Or at least
"Press <return> to continue" which would be less nice but still acceptable.
Now, if I use cin.getline() to try and read such input, the cin.getline()
call never returns, if the user just presses the <return> key (apparently
because it's an empty line and getline discards that).


Aehm. Then you did something wrong.

#include <string>
#include <iostream>

using namespace std;

int main()
{
string input;

cout << "Press <return> to continue\n";
getline( cin, input );

cout << "Bye\n";
}

waits exactly for the user pressing return.
Ok. The user can enter other things before the return, but
it definitly will return by just pressing the <return> key
If instead I use
"char c; cin.get(c);" and the user instead of just pressing <return> had
entered some other characters before pressing return, I read only the first
character and the others remain in the buffer. Now, the next time, program
flow comes across this "Press <return> to continue" code, the cin.get(c)
immediately reads the first of the characters that are still in the buffer
from the previous input.


OK. So what is hindering you to do:

char c;
while( cin.get(c) != '\n' )
;

That is: loop until the return key is detected?
You *know* that there has to be a '\n' somewhere.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #9

P: n/a
Frank Bormann wrote:

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1113529832.856545@athnrd02...
Frank Bormann wrote:

I suppose in most PCs, cin accepts input only after you press Enter, so

the closest thing
I can suggest is using the old, good, system-dependent extensions, getch()

and getche()
(the second echoes the input). It is usually defined in conio.h when it is

available.

I was afraid, you were going to say that. I was thinking about that too, I'm
sure, I could easily manage to get what I want, by using the low-level file
descriptor i/o of the glibc, but I was hoping to find a system-independent
solution.


No.
As a rule of thumb: C++ knows nothing about any hardware. No keyboard, no mouse,
no monitor, no harddisk, no network, ...

Accessing such things is always platform dependent.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #10

P: n/a
Frank Bormann wrote:
Hi,

probably a stupid question, but I haven't been able to find anything.

Is there a istream related function that let me read exactly one keystroke
from the keyboard through cin?


Not a stupid question at all, because it's a tricky problem.

First, in_avail has always worked fine for me. I don't know why it wouldn't
work for you, so I can't help you there.

Second, cin calls blocking until enter is hit is not a problem of cin, but
of the OS. There are WinAPI calls (I don't know which exactly) that you can
use to set the console into return-after-each-character mode.

Third, I'm pretty sure - no, actually I *know*, because that very fact
caused me trouble just yesterday - that getline (at least the std::string
version) does not discard empty lines.

--
Sebastian Redl
Jul 23 '05 #11

P: n/a

"Karl Heinz Buchegger" <kb******@gascad.at> wrote in message
news:42***************@gascad.at...
I want some "Press any key to continue" like implementation. Or at least
"Press <return> to continue" which would be less nice but still acceptable. Now, if I use cin.getline() to try and read such input, the cin.getline() call never returns, if the user just presses the <return> key (apparently because it's an empty line and getline discards that).


Aehm. Then you did something wrong.


Thank you!!! Yes, I was using the istream member function getline, not this
global string function.
This finally works at least for the "Press <return> to continue".

Frank
Jul 23 '05 #12

P: n/a
Frank Bormann skrev:
Hi,

probably a stupid question, but I haven't been able to find anything.

Is there a istream related function that let me read exactly one keystroke
from the keyboard through cin?

...
Frank


This is an OT-answer for Win32

_#include <stdlib.h>_

_system ("PAUSE");_

gives

"Press any key to continue"

Wasn't that what you were looking for?

-- Pelle
Jul 23 '05 #13

P: n/a
sam
Ioannis Vranos wrote:
Frank Bormann wrote:
Ok, let me ask differently: How can I determine, if there are chars to
read
in the cin streambuf without blocking? I've tried to use in_avail() and
readsome(), but they always return 0 on cin, even if there's still input
data present in the buffer.
I suppose in most PCs, cin accepts input only after you press Enter, so
the closest thing I can suggest is using the old, good, system-dependent
extensions, getch() and getche() (the second echoes the input). It is
usually defined in conio.h when it is available.

I never use this API in g++ before. Is it similar to curses base IO API?
In curses C API, it can do exactly what the OP is asking for.
Surely, you can "Wrap" curses C API into C++ classes. Perhaps curses has
already had a set of C++ API in the open source community.

Sam.
They are not part of the C++ standard though.

Jul 23 '05 #14

P: n/a

"Frank Bormann" <ne*************@xoxy.net> wrote in message
news:42***********************@news.freenet.de...

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1113529832.856545@athnrd02...
Frank Bormann wrote:

I suppose in most PCs, cin accepts input only after you press Enter, so

the closest thing
I can suggest is using the old, good, system-dependent extensions,
getch()

and getche()
(the second echoes the input). It is usually defined in conio.h when it
is

available.

I was afraid, you were going to say that. I was thinking about that too,
I'm
sure, I could easily manage to get what I want, by using the low-level
file
descriptor i/o of the glibc, but I was hoping to find a system-independent
solution.


The only way to do (almost) that is to specifically support certain known
platforms/implementations via conditional compilation:

#ifdef THIS_PATFORM
this_platform_get();
#elseif THAT_PLATFORM
that_platform_get();
#else
some_standard_blocking_input_function();
#endif

-Mike
Jul 23 '05 #15

P: n/a

"Sebastian Redl" <e0******@student.tuwien.ac.at> wrote in message
news:42***********************@tunews.univie.ac.at ...
Frank Bormann wrote:
Hi,

probably a stupid question, but I haven't been able to find anything.

Is there a istream related function that let me read exactly one
keystroke
from the keyboard through cin?


Not a stupid question at all, because it's a tricky problem.

First, in_avail has always worked fine for me. I don't know why it
wouldn't
work for you, so I can't help you there.

Second, cin calls blocking until enter is hit is not a problem of cin, but
of the OS. There are WinAPI calls (I don't know which exactly) that you
can
use to set the console into return-after-each-character mode.

Third, I'm pretty sure - no, actually I *know*, because that very fact
caused me trouble just yesterday - that getline (at least the std::string
version) does not discard empty lines.


<OT>
If you're using VC++ 6.0, note that the 'std::getline()' supplied
with it has a bug which causes the behavior you describe, the fix to
which is available at http://www.dinkumware.com/vc_fixes.html
(One or more of the later VC++ 'service packs' from Microsoft might also
address this problem, I didn't check).
</OT>

-Mike
Jul 23 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.