2014-01-12 66 views
2

我一直在用kbhit()測試一些東西,並發現了一個帶有延遲死循環的奇怪行爲。在這個代碼示例中,我將循環延遲爲每秒運行30次。C在延遲的無限循環中出現奇怪的kbhit()行爲

#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語句幾乎沒有功能。如果您在本例中按住'a'鍵,HELLO將無限期地打印。如果按住'b'鍵,HI幾乎不會被打印。

爲什麼會發生這種情況?

+0

您的'b'被'a'getch()吸收。你應該首先getch()然後檢查哪一個是那個,所以第二個不會因爲第一個而被忽略。 – Vladp

+0

因爲'getch()'被定義爲'int getch(void)',所以在使用'getch()'時,你還應該使用'int'而不是'char'。 – pzaenger

回答

4

這是因爲你的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); 
} 
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); 
}