2014-02-09 62 views
2

delay(msec)sleep(sec)這樣的函數會將程序延遲指定的時間,但只能在控制傳遞給它之後。例如,使用緊接在delay()之前的printf()函數,首先執行printf(),然後執行delay()。但是,如果我們使用scanf(),getchar()等輸入處理函數,則控件不會傳遞到delay(),直到我輸入。對?如何在輸入函數中使用時間延遲?

有沒有辦法在指定時間執行scanf(),然後在完成時間後退出,即使沒有輸入被饋送?是否有任何功能在指定的時間段內執行scanf()或任何其他輸入功能?

回答

0

你是正確的,因爲你的程序有一個單獨的線程,scanf()之後的sleep()不會被執行,直到scanf()結束。

我想你要做的是讀一個字符串,等待一段時間。解決方法是建立要單獨掃描的字符串(同時檢查時間限制是否已過期),然後將字符串傳遞到sscanf()(請注意其他s)以供日後處理。

第一位是硬的部分。可能最容易的方法是在STDIN(即輸入流)上使用循環並輸入select(),並且超時時間很短。每當角色到達時,將其添加到字符串中。您需要手動處理(例如)刪除。請用gettimeofday閱讀時間,如果此時間和開始時間之間的時間差超過給定的超時時間,則退出您超時的時間。

另一種方法是使用SIGALRM的報警處理程序。您可能(或可能不會)發現這令人滿意地終止了fgets()。您將需要一個sigaction沒有SA_RESTART。隨着風,這應該工作。我說「隨風而過」,因爲看起來似乎有錯誤的c庫版本,當收到EINTR時,無條件地重試。例如見:http://alumnus.caltech.edu/~dank/sigtest.c

當然,也許有些圖書館可以幫助你。 readline沒有內置超時。 editline可能。

+0

我怎樣才能在stdin做一個選擇()?謝謝 – user3124361

+0

'STDIN'與文件描述符0相關聯。根據需要使用'FD_SET'和'select()'。 – abligh

0

好的,不知道其他平臺,但是Windows用戶有一個解決方法:在Windows.h下有這個GetKeyState(keyID),允許檢查鍵盤按鍵的狀態。

這裏有一個現實化我做:

#include <stdio.h> 
#include <Windows.h> 

void PrintKey(int * key) { 

    /* initially lowercase */ 
    int lowercase = 1; 

    /* if shift is being held, indicated by the leftmost bit 
    invert the lowercase boolean */ 
    if ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000) lowercase ^= 1; 

    /* if Caps Lock is toggled, indicated by the rightmost bit 
    invert the lowercase boolean (again) */ 
    if ((GetKeyState(VK_CAPITAL) & 0x0001) == 0x0001) lowercase ^= 1; 

    /* print the key */ 
    if (*key > '9' && lowercase) putchar(*key + 'a' - 'A'); 
    else putchar(*key); 

} 

int main() 
{ 
    int timeout = 10000;    /* timeout (in milliseconds) */ 
    char keysheld['Z' + 1] = { 0 };  /* record of keys being held (1: being hold, 0: released) */ 
    int lastkeyonhold = 0;    /* last key that has been pressed */ 
    int holddelay;      /* delay before repeating starts (in millisec) */ 
    int repeatperiod = 40;    /* how much before each repeat (in millisec) */ 

    while (timeout > 0) { 
    /* until timeout */ 

     /* check keys from 0 to Z */ 
     for (int i = '0'; i <= 'Z'; i++) { 
      if (i == '9' + 1) i = 'A'; 

      /* 0x8000 is the leftmost bit for 2 bytes... 
      leftmost bit is given as 1, if the key is being pressed */ 
      if ((GetKeyState(i) & 0x8000) == 0x8000) { 

       /* if the key wasn't already being known as held 
       make it known as the last key that has been pressed 
       refresh the delay record to 500 milliseconds 
       and print the key once */ 
       if (!keysheld[i]) { 
        lastkeyonhold = i; 
        holddelay = 500; 
        PrintKey(&i); 
       } 

       /* regardless, make the key known as pressed */ 
       keysheld[i] = 1; 
      } 

      /* if the key is not being hold, make it known so 
      this is important, because this is what will allow us to have 
      a freshly pressed key to be our lastkeyonhold */ 
      else keysheld[i] = 0; 
     } 

     /* if the console window is the active window */ 
     if (GetConsoleWindow() == GetForegroundWindow()) { 

      /* and the last key pressed is still being pressed */ 
      if (keysheld[lastkeyonhold]) { 
       /* and the hold delay is over... then repeatedly print the key */ 
       if (holddelay < 0) PrintKey(&lastkeyonhold); 
       /* else, just keep on consuming the delay */ 
       else holddelay -= repeatperiod; 
      } 

      /* if return has been pressed while the console window is active 
      break out... */ 
      if ((GetKeyState(VK_RETURN) & 0x8000) == 0x8000) { 
       break; 
      } 

     } 

     Sleep(repeatperiod); 
     timeout -= repeatperiod; 
    } 

    /* print a New Line ('\n' or 10, whatever) after breaking out, for whatever reason */ 
    putchar(10); 
    system("pause"); 

    return 0; 
} 

它基本上只是複製你有什麼對任何文本編輯器,如果你要按下或按下並按住你的鍵盤上的按鍵,通過檢測鍵盤鍵的狀態。您可以閱讀代碼中的註釋以獲得詳細的解釋。

它僅會爲上述不幸的字母,字母和數字鍵......我很可能添加了數字鍵盤的鍵,但它會很麻煩手工管理的區位鍵。我不知道是否有一個更簡單的方法來做到這一點的關鍵,比手工管理所有的按鈕以外的其餘部分。對於虛擬按鍵的全名單:http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx

相關問題