我想放慢一段时间,只有一个命令,而不是程序-初学者级别-C++
我想创建一个带秒的密钥计数器。我试过了,但它会减慢程序的速度,而不仅仅是几秒钟。
#include <iostream>
#include <Windows.h>
#include <conio.h>
using namespace std;
int x = 1;
int secs = 0;
int clicks = 0;
int main() {
while (true) {
if (x == 1) {
secs++;
Sleep(1000);
system("CLS");
cout << "Clicks: " << clicks << " Time: " << secs;
x = 2;
}
else if (2 == x) {
_getch();
clicks++;
system("CLS");
cout << "Clicks: " << clicks << " Time: " << secs;
x = 1;
}
}
}
解决方案
您似乎希望Sleep
函数在等待计时器时不阻塞整个程序,但在等待计时器时继续处理键盘输入。此外,您似乎希望getch
函数在等待键盘输入时不会阻塞整个程序,而是在等待键盘输入时继续处理计时器。然而,这不是这些函数的工作方式。这两个函数将一直阻塞,直到它们等待的特定类型的事件发生。
通常可以使用WaitForMultipleObjects
函数来实现此目的。然而,在本例中,函数WaitForSingleObject
就足够了,因为该函数将允许您指定除了要等待的对象句柄之外的超时间隔。这样,您就可以同时在计时器和对象句柄上等待键盘输入。
WaitForSingleObject
只有在使用ReadConsoleInput
等低级控制台API函数处理控制台输入时才能可靠地工作。似乎无法可靠地预测kbhit
和getch
是否会工作,也不能可靠地与ReadConsole
一起工作。
我相信这个程序能达到您的要求:
#include <Windows.h>
#include <iostream>
#include <cstdio>
int main()
{
HANDLE hStdin = INVALID_HANDLE_VALUE;
ULONGLONG ullStartTime;
//counter of the number of times a keypress was registered
int num_keypresses = 0;
//get input handle
hStdin= GetStdHandle( STD_INPUT_HANDLE );
if ( hStdin == INVALID_HANDLE_VALUE )
{
std::cerr << "error opening input handle!
" << std::flush;
exit( EXIT_FAILURE );
}
//remember time that program started
ullStartTime = GetTickCount64();
for (;;) //infinite loop, equivalent to while(1)
{
ULONGLONG ullElapsedTime = GetTickCount64() - ullStartTime;
int seconds = (int) ( ullElapsedTime / 1000 );
int remainder = (int) ( ullElapsedTime % 1000 );
//round up to next second, if appropriate
if ( remainder >= 500 )
{
seconds++;
remainder -= 1000;
}
//uncomment the folllowing line to clear the screen
//std::system( "cls" );
//write data to screen
std::cout << "Keypresses: " << num_keypresses << " Time: " << seconds << " seconds
" << std::flush;
//wait for either a keypress to occur, or for a timeout to occur
switch ( WaitForSingleObject( hStdin, 1000 - remainder ) )
{
case WAIT_OBJECT_0:
{
DWORD dwRead;
INPUT_RECORD ir;
//console input event occurred, so read it
if ( !ReadConsoleInput( hStdin, &ir, 1, &dwRead ) || dwRead != 1 )
{
std::cerr << "error reading input!
" << std::flush;
std::exit( EXIT_FAILURE );
}
if ( ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown )
{
num_keypresses += ir.Event.KeyEvent.wRepeatCount;
}
break;
}
case WAIT_TIMEOUT:
{
//timeout occurred
break;
}
default:
{
std::cerr << "unexpected error!
" << std::flush;
std::exit( EXIT_FAILURE );
}
}
}
}
如果我等待大约5秒才开始按键,然后按几个键,则我得到的输出如下:
Keypresses: 0 Time: 0 seconds
Keypresses: 0 Time: 1 seconds
Keypresses: 0 Time: 2 seconds
Keypresses: 0 Time: 3 seconds
Keypresses: 0 Time: 4 seconds
Keypresses: 0 Time: 5 seconds
Keypresses: 1 Time: 6 seconds
Keypresses: 1 Time: 6 seconds
Keypresses: 2 Time: 7 seconds
Keypresses: 2 Time: 7 seconds
Keypresses: 2 Time: 8 seconds
Keypresses: 3 Time: 9 seconds
Keypresses: 3 Time: 9 seconds
Keypresses: 4 Time: 10 seconds
Keypresses: 4 Time: 10 seconds
Keypresses: 4 Time: 11 seconds
Keypresses: 5 Time: 11 seconds
Keypresses: 5 Time: 11 seconds
Keypresses: 5 Time: 12 seconds
Keypresses: 6 Time: 12 seconds
Keypresses: 6 Time: 13 seconds
Keypresses: 6 Time: 14 seconds
Keypresses: 7 Time: 15 seconds
Keypresses: 7 Time: 15 seconds
Keypresses: 7 Time: 16 seconds
Keypresses: 7 Time: 17 seconds
在原始程序中,您使用std::system("cls");
清除屏幕,而不是每次打印一行。在我的程序中,我没有清除屏幕,但是,您可以取消对std::system("cls");
行的注释,它应该可以工作。我已经把它放在正确的位置了。但是请注意,使用std::system
is not recommended。有关更好的替代方案,请参阅Microsoft官方文档中的this page。
相关文章