Byker Dave
Byker Dave

Reputation: 139

Make a 'press any key' routine that is compatible with redirected standard input

I've got a C/C++ program that runs in a console window, and prompts the user to press any key to continue, or 'q' to quit. It currently uses _kbhit() to detect if a key has been pressed, and then uses _getch() to determine what character it was.

Now I want to be able to automate this program (from a C# app using a Process with RedirectStandardInput and CreateNoWindow set). Obviously I can no longer rely on _kbhit() as it uses ReadConsoleInput(), which fails when launched using my C# app. In my C# app I use process.StandardInput.Write("A") to push something onto the stream in an attempt to get my console app to continue.

In the console app I have used SetConsoleMode() to clear the ENABLE_LINE_INPUT flag so that I can use getchar() to return as soon as a character is pressed, and this works reasonably well (when I press a character key in the console window as well as when the call is made from the c# app). However, it has flaws in that it now only accepts characters keys (i.e. no F, Alt, Shift keys etc.) which isn't too big a problem, but moreso I seem to have to press return twice (and this is a key that lots of people will likely choose to press in the 'any key' situation).

Does anyone know how I can make the console app respond to a key (any a bonus, charcters and return only is acceptable) pressed ONCE, whilst still responding to a single character pushed onto the stream from my C# app?

Something I did notice, calling system("PAUSE") gives the exact behaviour I want, other than knowing what key was pressed so that I can quit on 'q'. I don't know how PAUSE does it though, and it doesn't let me use my custom message either :(.

I'm sure there's a really obvious solution, but it has been driving me mad. Any thoughts are much appreciated!

Upvotes: 3

Views: 3982

Answers (4)

Byker Dave
Byker Dave

Reputation: 139

Thank you for all your responses, I've learned a lot about handling input!

However, I couldn't get anything to work exactly how I wanted, so I had to abandon the unified approach and put in a check to see if it was running in a window. If it is, I stick with _kbhit(), and if not I use PeekNamedPipe(), which gives me the number of characters sent from my C# app without transfering them into the stdin buffer. There's still a few issues that I have to work out to do with clearing any data that I don't want from the pipe, but it's solved my initial problem.

Thanks again for all the suggestions, they will undoubtably come in handy next time I have an input nightmare :)

Upvotes: 0

Puppy
Puppy

Reputation: 146968

Use cin.get(). This returns the appropriate key.

Upvotes: 0

BSchlinker
BSchlinker

Reputation: 3481

Here is a very good implementation for C++. Be sure to read over the entire tutorial, as I it may initially appear that it doesn't help you.

http://www.daniweb.com/forums/thread90228.html

Upvotes: 1

Thomas Matthews
Thomas Matthews

Reputation: 57728

There are two issues with the resolutions:

  1. Neither the C or C++ languages have portable functions for waiting for a keyboard key to be hit. It's an operating system (platform) issue.*
  2. C and C++ have different methods for resolving I/O. Choose your language, C or C++.

In my C++ console applications, I ask the user to "Press Enter to Continue" and use the ignore method of cin:

void Pause(void)
{
    std::cout << "Press ENTER to continue.\n";
    std::cout.flush(); // Insurance, make sure the text is displayed.
    std::cin.ignore(100000, '\n');  // Ignore characters until an ENTER (newline) is received.
    return;
}

I suggest you create a single file with the Pause function. You can write different versions for different platforms and let the build system select the correct file.

  • Not all platforms that run C or C++ are required to have keyboards. Many embedded systems don't have keyboards. Also, many windowing systems receive messages, events or signals when a key is pressed. Again, something different and not standard.

Upvotes: 3

Related Questions