2008年8月8日星期五

C 函數的新發現

以往如需要從程式的主迴圈讀取鍵盤的輸入去決定是否退出程式, 我會用另一個執行緒去乎叫 std::cin 或 getchar(), 因為它們都是阻塞 (blocking) 的.

原來我一直忽略了 kbhit() 的存在! 有了它, 以上的問題就可簡化為:

#include

int main() {
while(true) {
// Poll the console without blocing, return true if there is
// a keystroke waiting in the buffer.
if(kbhit()) {
if(getchar() == 'q')
break;
}

// Do something usefull
// ...
}
return 0;
}

可惜 kbhit() 不是標準 C 裡的成員, 在若干平台上我們得自行實踐. 以下編碼出於這裡

#include <sys/select.h>

int kbhit(void)
{
struct timeval tv;
fd_set read_fd;

/* Do not wait at all, not even a microsecond */
tv.tv_sec=0;
tv.tv_usec=0;

/* Must be done first to initialize read_fd */
FD_ZERO(&read_fd);

/* Makes select() ask if input is ready: 0 is the file descriptor for stdin */
FD_SET(0, &read_fd);

/* The first parameter is the number of the largest file descriptor to check + 1. */
if(select(1, &read_fd, NULL/*No writes*/, NULL/*No exceptions*/, &tv) == -1)
return 0; /* An error occured */

/* read_fd now holds a bit map of files that are
* readable. We test the entry for the standard
* input (file 0). */
if(FD_ISSET(0, &read_fd))
/* Character pending on stdin */
return 1;

/* no characters were pending */
return 0;
}