How do I get a single character from stdin?

How do I get a single character from the stdin?
get() needs a delimiter, but I just want to extract a single character without waiting for anything.

Hello Grime,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

int main()
{
	char ch{};

	std::cin.get(ch);

	std::cout << "\n " << ch << std::endl;


	// <--- Used mostly for testing in Debug mode. Removed if compiled for release.
	// <--- Used to keep the console window open in Visual Studio Debug mode.
	// The next line may not be needid. If you have to press enter to see the prompt it is not needed.
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue: ";
	std::cin.get();

	return 0;
}

This will extract one character from the input buffer no matter how many characters are there. Note: the rest of what may have been typed may still be in the input buffer.

See: http://www.cplusplus.com/reference/istream/istream/get/?kw=cin.get

Hope that helps,

Andy
But Andy, cin.get() waits for me to click the enter button.. I don't want it to wait.
Hello Grime,

You did not say that.

There is no C++ version of the C "getch()" function. The closest that you could get is "std::cin.get()", but you have to press enter at the very least.

I my-self have not had much luck finding a C++ replacement for "getch()" so far.

Short of writing your own function I am sorry that I do not have anything I can tell you.

Maybe someone else might know of something.

I have not used "boost", but there may be something there.

Andy
Sorry if I was unclear Andy, I meant that when I said "get() needs a delimiter, but I just want to extract a single character without waiting for anything."

Thanks anyways. I presume writing my own function for something like this would be very complex, but if it's not that complex then I'm up for it, where do I start?

One question: 'How' does get() wait for an enter? Does it read stdin until it sees a '\n'?

My second question would be: Is there any reason istream::putback() should not be used to insert characters to stdin?

If get() reads for '\n' and putback() can be used, then we might use them with peek() to insert '\n' to the stdin. Is that too crazy?

Is there a better way? Like essentially modifying get() to not wait for '\n' ourselves? Would that be too complex?


Edit:
1
2
3
  cin.putback('x');
  char c;
  c= cin.get();


That code executes without waiting for the enter button to be pressed.. Anybody knows why??

Oh and also this doesn't work:
1
2
3
4
5
6
7
  cin.putback('x');
  cin.putback('t');
  char c;
  c= cin.get();
  cout << (int)c;
  c = cin.get();
  cout << (int)c;


Both cout statements give blanks.


If putback() is the wrong way of inserting to stdin, how do you insert to stdin?
Last edited on
Hello Grime,

I have thought about writing a function, but have yet to do so.

I may be a little off with the function name, but I believe it is something like: "getAnyKeyState()". I would have to look that one up and the down side is that you would be stuck in a loop checking for a keypress and that may not be the best way to write a program.

Andy
With standard c++ you cannot achieve that. So you need a more or less platform dependent solution. Take a look at ncurses/pdcurses (for windows).
Guys see my edit. Although I'm 100% sure that the edit is wrong..

Handy Andy, can't you check if key "had been pressed"? Is that not possible without a loop?

Maybe we can use peek() and string stream?? We don't have to click on enter to transfer data from stdin to string stream now do we!

edit: no clue
1
2
	stringstream Mystr;
	Mystr << cin.rdbuf();
Last edited on
your standard c++ tools are waiters. That is, if you try to read from the keyboard, they will wait until the user types something and presses the enter key.

you can use peek, but as you said, you need a thread or a loop to do that.

nonstandard solutions are just better here. Tying up a full thread to do keyboard IO by hand is resource heavy. The nonstandard solutions are using hardware cues / low level tools that are hardware and OS specific and outside the scope of the language. People like to avoid nonstandard solutions but there is a time and a place for it. The key to using them cleanly is to keep the nonstandard code isolated so it is easy to replace if you change to a different OS. Just make a generic getkeyboardwhatsit function that you can define with some macro magic to do the nonstandard inputs via the current OS flavor and its good to go. It may only have 1 version for now, and that is ok too. You can always add another OS later, just a line or two, because you kept it isolated from the rest of the code.

Topic archived. No new replies allowed.