If you are asking about how to do something with the console without waiting for the user, but while still checking for user input, that isn't a trivial problem. The C++ console functions aren't designed for simultaneous non-blocking input.
Threads have been mentioned as one way to do this. That could work. There are other ways. Generally, these are platform-specific.
Here's how you might do it under Windows. This program uses the console and prints a dot every half-second
unless the user sent input during that time. If the user did send input, the program displays the keystrokes and adds them to a buffer. When the user presses Enter, the buffer is swapped out (where it could then be used elsewhere as received input, e.g. sent to the interpreter in a text adventure). In this program, the received input string is just displayed back to the user when that happens.
The key functions here are WaitForSingleObject, PeekConsoleInput, and FlushConsoleInputBuffer.
It's a little rough, but it should give you a useful idea of what you could do:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
const int bufferSize = 100;
bool runflag = true;
bool inputSent = false;
wstring userInput;
wstring lastSentInput;
HANDLE hin = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD irBuffer[bufferSize] = { };
DWORD mode;
DWORD inputCount;
DWORD pollState;
TCHAR t;
// Change to raw input mode
GetConsoleMode(hin, &mode); // Store the previous console mode for later restoration
SetConsoleMode(hin, 0); // Disable input echoing etc.
FlushConsoleInputBuffer(hin);
while(runflag)
{
// Give the input stream 500 ms to respond
pollState = WaitForSingleObject(hin, 500);
if(pollState == WAIT_OBJECT_0) // If the input stream signals back...
{
// Record up to (bufferSize) input events, then flush the stream
PeekConsoleInput(hin, irBuffer, bufferSize, &inputCount);
FlushConsoleInputBuffer(hin);
for(DWORD i = 0; i < inputCount; i++)
if(irBuffer[i].EventType == KEY_EVENT)
if(irBuffer[i].Event.KeyEvent.bKeyDown)
{
t = irBuffer[i].Event.KeyEvent.uChar.UnicodeChar;
switch(t)
{
case VK_RETURN:
lastSentInput = userInput;
userInput = L"";
inputSent = true;
break;
case VK_ESCAPE: // Quit on Esc
runflag = false;
break;
case 0:
case VK_SHIFT:
// Do nothing
break;
default:
userInput += t;
wcout << t; // Echo the input
}
}
}
else if(pollState == WAIT_TIMEOUT) // If the input stream times out (no input)
wcout << ".";
else
{ wcout << "\nError: WaitForSingleObject failed"; break; }
if(inputSent)
{
inputSent = false;
wcout << L"\n\nString received: " << lastSentInput
<< endl << endl;
}
}
// Restore previous console mode
SetConsoleMode(hin, mode);
wcout << "\nGoodbye.\n";
return 0;
}
| |