我一直用kbhit()测试一些东西,并发现了一个带有延迟无限循环的奇怪行为。在这个代码示例中,我将循环延迟每秒运行30次。
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
_Bool IsKeyDown(char c)
{
if(kbhit())
{
char ch1 = getch();
if(ch1 == c)
return 1;
}
return 0;
}
/*
*
*/
int main(int argc, char** argv) {
while(1)
{
if(IsKeyDown('a'))
{
printf("HELLO\n");
}
if(IsKeyDown('b'))
{
printf("HI\n");
}
Sleep(1000 / 30);
}
return (EXIT_SUCCESS);
}
问题是,虽然循环中的第一个if语句工作正常,但第二个if语句几乎不起作用。如果在此示例中按住“a”键,则会无限期地打印HELLO。如果您按住'b'键,HI几乎不会打印出来,如果有的话。
为什么会出现这种情况?
答案 0 :(得分:5)
这是因为当IsKeyDown
返回kbhit
时,true
会产生消耗缓冲区中下一个字符的副作用。由于你连续两次调用IsKeyDown
,第一次调用“吃掉”'b'
,所以当运行第二次调用时,缓冲区中没有数据。
您需要重新组织代码,以便每次循环迭代只调用IsKeyDown
一次。您的循环应存储其返回值,并将该存储的值与您需要的字符进行比较(例如'a'
和'b'
):
int GetKeyDown() {
if(kbhit())
{
return getch();
}
return -1;
}
while(1)
{
int keyDown = GetKeyDown();
if(keyDown == 'a')
{
printf("HELLO\n");
}
if(keyDown == 'b')
{
printf("HI\n");
}
Sleep(1000 / 30);
}
答案 1 :(得分:0)
因为第一个IF消耗了正在按下的键。更改您的代码,以便读取密钥一次:
int main(int argc, char** argv) {
char key;
while(1)
{
if (khbit())
key = getch();
else
key = 0;
if(key == 'a')
{
printf("HELLO\n");
}
if(key == 'b')
{
printf("HI\n");
}
Sleep(1000 / 30);
}
return (EXIT_SUCCESS);
}