Windows 控制台只有一個全域游標位置。子執行緒更新時間時移動游標,主執行緒 scanf 讀取輸入時游標已被移走,導致輸入字元出現在錯誤位置。
void real_time(int X, int Y) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
time_t t; struct tm *tm;
// 初始繪製日期、時、分
GetConsoleScreenBufferInfo(hOut, &csbi); // 存儲主執行緒游標
SetCursor(X, Y);
t = time(NULL); tm = localtime(&t);
printf("%04d-%02d-%02d %02d:%02d:", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
SetConsoleCursorPosition(hOut, csbi.dwCursorPosition); // 還原游標
while (1) {
GetConsoleScreenBufferInfo(hOut, &csbi); // 每秒存儲一次
t = time(NULL); tm = localtime(&t);
if (tm->tm_sec == 0) { // 分變化
SetCursor(X+10, Y);
printf("%02d:%02d", tm->tm_hour, tm->tm_min);
} else { // 秒變化
SetCursor(X+16, Y);
printf("%02d", tm->tm_sec);
}
SetConsoleCursorPosition(hOut, csbi.dwCursorPosition); // 還原
Sleep(1000);
}
}
GetConsoleScreenBufferInfo(hOut, &csbi):取得目前游標座標 csbi.dwCursorPosition。SetConsoleCursorPosition(hOut, pos):將游標移回指定座標。int main() {
system("title 即時時鐘");
printf("\n\n\n輸入序號:");
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)real_time, NULL, 0, NULL);
int k; scanf("%d", &k); // 主執行緒輸入不再受干擾
return 0;
}
此法確保子執行緒「借用」游標後立即歸還,主執行緒輸入體驗流暢。