我正在尝试制作一个简单的控制台计算器。它按预期工作,但是,我想通过按下按钮来退出程序,而不让程序等待循环结束。我尝试将!(GetAsyncKeyState(VK_RSHIFT))
放入while循环条件中,我也尝试将!(GetAsyncKeyState(VK_RSHIFT))
放入循环中的if语句中,结果是相同的。
#include <iostream>
#include <Windows.h>
using namespace std;
int main() {
cout << "Press RSHIFT for the program to close!n";
while (!(GetAsyncKeyState(VK_RSHIFT))) {
long double num1, num2;
char mathOp;
cin >> num1 >> mathOp >> num2;
switch (mathOp) {
case('+'):
cout << num1 + num2 << endl;
break;
case('-'):
cout << num1 - num2 << endl;
break;
case('*'):
cout << num1 * num2 << endl;
break;
case('/'):
cout << num1 / num2 << endl;
break;
default:
cout << "ERROR: Operator doesn't match available operators (+ - * /)!n";
}
}
return 0;
}
函数调用
GetAsyncKeyState(VK_RSHIFT)
将在调用函数时报告SHIFT键的状态。然而,这似乎不是你想要的。
你似乎想让阻塞函数调用
cin >> num1 >> mathOp >> num2;
当用户按下SHIFT键时立即中止,以便退出程序。
当使用c++标准库的std::cin
时,这是不可能的。
但是,您可以调用特定于平台的函数ReadConsoleInput
来等待键盘事件,而不是使用std::cin
。如果用户按下SHIFT键,则可以停止程序。如果用户按了不同的键,则可以将该字符添加到输入缓冲区中,当用户按ENTER键时,可以处理该输入缓冲区。
这样,当用户按下SHIFT键时,您的程序将立即得到通知,并且您不必诉诸不可靠的解决方法,例如调用Sleep
函数。
然而,这个解决方案需要你在一个较低的层次上处理输入,这需要你的程序做一些通常会自动完成的额外工作,比如将输入回显到屏幕上,并为BACKSPACE和ENTER键提供特殊处理。
我写了这样一个程序:
#include <Windows.h>
#include <iostream>
#include <string>
#include <sstream>
void process_input( const std::string &line )
{
std::stringstream ss( line );
long double num1, num2;
char mathOp;
ss >> num1 >> mathOp >> num2;
if ( !ss )
{
std::cout << "Error parsing input line "" << line << ""n" << std::flush;
return;
}
switch (mathOp)
{
case('+'):
std::cout << num1 + num2 << 'n';
break;
case('-'):
std::cout << num1 - num2 << 'n';
break;
case('*'):
std::cout << num1 * num2 << 'n';
break;
case('/'):
std::cout << num1 / num2 << 'n';
break;
default:
std::cout << "Unknown operator encountered in line "" << line << ""n";
}
std::cout << std::flush;
}
int main( void )
{
HANDLE hStdIn = GetStdHandle( STD_INPUT_HANDLE );
INPUT_RECORD ir;
DWORD dwRead;
std::string line;
//get scan code of the right shift key
UINT uRShiftScanCode = MapVirtualKeyA( VK_RSHIFT, MAPVK_VK_TO_VSC );
for (;;)
{
if ( !ReadConsoleInputA( hStdIn, &ir, 1, &dwRead ) )
{
std::cout << "Error in ReadConsoleInputn";
std::exit( EXIT_FAILURE );
}
if ( ir.EventType != KEY_EVENT || !ir.Event.KeyEvent.bKeyDown )
continue;
if ( ir.Event.KeyEvent.wVirtualScanCode == uRShiftScanCode )
{
std::cout << "nnRight shift press detected, exiting program!n";
return 0;
}
switch ( ir.Event.KeyEvent.uChar.AsciiChar )
{
case 0: //keystroke does not translate to a valid character
break;
case 'r': //carriage return character
//echo input to output
std::cout << 'n' << std::flush;
process_input( line );
line.clear();
break;
case 'b': //backspace character
for ( WORD i = 0; i < ir.Event.KeyEvent.wRepeatCount; i++ )
{
//echo backspace to output
std::cout << "b b" << std::flush;
//remove last character from string
if ( !line.empty() )
{
line.pop_back();
}
}
break;
default:
for ( WORD i = 0; i < ir.Event.KeyEvent.wRepeatCount; i++ )
{
//echo input to output
std::cout << ir.Event.KeyEvent.uChar.AsciiChar << std::flush;
//add character to input buffer
line.push_back( ir.Event.KeyEvent.uChar.AsciiChar );
}
}
}
}
这个程序有以下行为:
5+3
8
10*4
40
5-3
2
20/3
6.66667
Right shift press detected, exiting program!
正如你所看到的,当用户按下右SHIFT按钮时,它立即正确地做出反应。