按键侦测遇到BUG
该程式在执行时会侦测按键是否按下与纪录按键之间的间隔时间遇到的问题是该段标注区域会多一次的纪录,不知道是什么地方出问题。
程式码与图片如下#
程序代码:
#include <stdio.h> #include <windows.h> #define MAX_KEYS 30 #define MAX_KEYSB 30 #define MAX_INTERVALS (MAX_KEYS - 1) #define MAX_INTERVALSB (MAX_KEYSB - 1)// 設定驗證密碼紀錄的間隔數比輸入按鍵少一 int main() { INPUT_RECORD input_record; HANDLE console = GetStdHandle(STD_INPUT_HANDLE); DWORD events_read; // DWORD變量: 事件讀取(記錄按鍵按下的時間和釋放的時間) LARGE_INTEGER start_time, end_time, frequency; BOOL last_event_was_release = FALSE; LARGE_INTEGER last_release_time; int key_count = 0; double sum, avg; char keys[MAX_KEYS] = { 0 }; char keysB[MAX_KEYSB] = { 0 }; double intervals[MAX_INTERVALS - 1] = { 0 }; double intervalsB[MAX_INTERVALSB - 1] = { 0 };// 設定陣列紀錄間隔數組 double intervaldifferent; char input[20]; // 儲存使用者輸入的字串 char target[] = "password"; // 設定目標字串 int flag = 1; QueryPerformanceFrequency(&frequency); printf("請設定節拍密碼\n\n"); while (1) { if (ReadConsoleInput(console, &input_record, 1, &events_read)) { //讀取控制台輸入(console是正在讀取的控制台輸入緩衝區的句柄,&input_record是指向緩衝區的指針,該緩衝區接收讀取的輸入記錄,1是要讀取的輸入記錄數,&events_read是一個指向變量的指針,該變量接收實際讀取的輸入記錄數) if (input_record.EventType == KEY_EVENT) { //檢查輸入記錄的事件類型是否為鍵盤事件 if (input_record.Event.KeyEvent.bKeyDown) { //檢查鍵是否被按下。如果此條件為真,代碼將執行 if 語句內的代碼塊 if (last_event_was_release && input_record.Event.KeyEvent.wVirtualKeyCode != VK_RETURN) { //檢查上一個事件是否為按鍵釋放以及當前事件是否為按鍵(不包括回車鍵) LARGE_INTEGER press_time; QueryPerformanceCounter(&press_time); //記錄按鍵事件的時間 double intervalA = (double)(press_time.QuadPart - last_release_time.QuadPart) / frequency.QuadPart * 1.0; //併計算按鍵與最後一次按鍵釋放事件之間的間隔 intervals[key_count - 1] = intervalA; // 將間隔存儲在適當索引 (key_count - 1) 的間隔數組中 printf("上下按鍵的時間間隔(節奏): %.3fs\n", (double)(press_time.QuadPart - last_release_time.QuadPart) / frequency.QuadPart * 1.0); //將間隔打印到控制台。打印的消息包括按鍵和最後一次按鍵釋放事件之間的時間間隔(以秒為單位) } QueryPerformanceCounter(&start_time); //用於獲取性能計數器的值,該值存儲在start_time變量中,然後用於計算按鍵按下和按鍵釋放之間經過的時間。 last_event_was_release = FALSE; //設置FALSE為表示最後一個事件是按鍵,這是計算節奏中按鍵之間的間隔所需要的。 if (key_count < MAX_KEYS) { keys[key_count++] = input_record.Event.KeyEvent.uChar.AsciiChar; } } else { LARGE_INTEGER release_time; QueryPerformanceCounter(&release_time); last_release_time = release_time; last_event_was_release = TRUE; if (input_record.Event.KeyEvent.uChar.AsciiChar != '\0') { printf("'%c'\n", input_record.Event.KeyEvent.uChar.AsciiChar); } else { printf("Key pressed for %.3f s\n", (release_time.QuadPart - start_time.QuadPart) / frequency.QuadPart * 1.0); } } } } // 如果Enter鍵被按下,跳出設定密碼 if (GetAsyncKeyState(VK_RETURN) & 1) { printf("\n==============================================================================\n"); printf("再輸入一次節拍密碼\n\n"); int key_countB = 0; while (2) { if (ReadConsoleInput(console, &input_record, 1, &events_read)) { //讀取控制台輸入(console是正在讀取的控制台輸入緩衝區的句柄,&input_record是指向緩衝區的指針,該緩衝區接收讀取的輸入記錄,1是要讀取的輸入記錄數,&events_read是一個指向變量的指針,該變量接收實際讀取的輸入記錄數) if (input_record.EventType == KEY_EVENT) { //檢查輸入記錄的事件類型是否為鍵盤事件 if (input_record.Event.KeyEvent.bKeyDown) { //檢查鍵是否被按下。如果此條件為真,代碼將執行 if 語句內的代碼塊 if (last_event_was_release && input_record.Event.KeyEvent.wVirtualKeyCode != VK_RETURN) { //檢查上一個事件是否為按鍵釋放以及當前事件是否為按鍵(不包括回車鍵) LARGE_INTEGER press_time; QueryPerformanceCounter(&press_time); //記錄按鍵事件的時間 double intervalA = (double)(press_time.QuadPart - last_release_time.QuadPart) / frequency.QuadPart * 1.0; //併計算按鍵與最後一次按鍵釋放事件之間的間隔 intervalsB[key_countB - 1] = intervalA; // 將間隔存儲在適當索引 (key_count - 1) 的間隔數組中 printf("上下按鍵的時間間隔(節奏): %.3fs\n", (double)(press_time.QuadPart - last_release_time.QuadPart) / frequency.QuadPart * 1.0); //將間隔打印到控制台。打印的消息包括按鍵和最後一次按鍵釋放事件之間的時間間隔(以秒為單位) } QueryPerformanceCounter(&start_time); //用於獲取性能計數器的值,該值存儲在start_time變量中,然後用於計算按鍵按下和按鍵釋放之間經過的時間。 last_event_was_release = FALSE; //設置FALSE為表示最後一個事件是按鍵,這是計算節奏中按鍵之間的間隔所需要的。 if (key_countB < MAX_KEYS) { keysB[key_countB++] = input_record.Event.KeyEvent.uChar.AsciiChar; } } else { LARGE_INTEGER release_time; QueryPerformanceCounter(&release_time); last_release_time = release_time; last_event_was_release = TRUE; if (input_record.Event.KeyEvent.uChar.AsciiChar != '\0') { printf("'%c' 鍵被按下\n", input_record.Event.KeyEvent.uChar.AsciiChar); } else { printf("Key pressed for %.3f s\n", (release_time.QuadPart - start_time.QuadPart) / frequency.QuadPart * 1.0); } } } } // 如果Enter鍵被按下,跳出設定密碼 if (GetAsyncKeyState(VK_RETURN) & 1) { int i = 0; for (int i = 0; i < key_count; i++) { if (keys[i] != keysB[i]) { printf("密碼數字設定錯誤\n"); } else { printf("密碼數字設定正確\n"); } } for (int i = 0; i < key_count - 1; i++) { intervaldifferent = intervals[i] - intervalsB[i]; if (intervaldifferent < 0) { intervaldifferent = intervaldifferent * (-1); } if (intervaldifferent > 0.25 * intervals[i]) { printf("密碼數字間隔錯誤\n"); } else { printf("密碼數字間隔正確\n"); } } break; } } break; } } return 0; } /* */