C在延迟无限循环中的奇怪kbhit()行为

NAM*_*E__ 2 c loops kbhit

我一直用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);
}
Run Code Online (Sandbox Code Playgroud)

问题是,虽然循环中的第一个if语句工作正常,但第二个if语句几乎不起作用.如果在此示例中按住"a"键,则会无限期地打印HELLO.如果您按住'b'键,HI几乎不会打印出来,如果有的话.

为什么会出现这种情况?

das*_*ght 5

发生这种情况是因为您在返回时有从缓冲区消耗下一个字符的IsKeyDown副作用.由于你连续两次调用,第一次调用"吃掉"了,所以当运行第二次调用时,缓冲区中没有数据.kbhittrueIsKeyDown'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);
}
Run Code Online (Sandbox Code Playgroud)