代码为here。当我运行程序时(我将kbhit保存为头文件并保存在程序文件夹中),在使用kbhit的第一个实例上我获得了未初始化的读取访问权限(我正在使用DrMemory进行内存调试)。我加入了sys / ioctl.h,因为没有它,我的程序将无法使用FIONREAD。问题在于调用tcsetattr(STDIN,TCSANOW,&term);。我不完全了解它是如何工作的,因此不胜感激。谢谢!
编辑:确切的消息是“未初始化读取:读取12个字节。系统调用ioctl.0x5402参数#2。”该行来自tcsetattr()调用。 将kbhit保存为cpp文件并将其模板化到另一个文件后,将发生此错误。该程序运行正常,除了一个错误。
答案 0 :(得分:0)
这是我修改为实际C而不是C ++的代码版本,因为出于粗心,它只是C ++,带有布尔型true / false和struct关键字。
哦,是的,不要将其放在头文件中。将其放在名为kbhit.c的文件中,然后删除或注释掉测试主函数。并在头文件中编写以下行:
int _kbhit(void);
或者您可能需要:
extern "C" int _kbhit(void);
这就是标题中所需的全部内容。
/**
Linux (POSIX) implementation of _kbhit().
Morgan McGuire, morgan@cs.brown.edu
*/
#include <stdbool.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
int _kbhit(void) {
static bool initialized = false;
if (! initialized) {
// Use termios to turn off line buffering
struct termios term;
tcgetattr(STDIN_FILENO, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &term);
setbuf(stdin, NULL);
initialized = true;
}
int bytesWaiting;
ioctl(STDIN_FILENO, FIONREAD, &bytesWaiting);
return bytesWaiting;
}
//////////////////////////////////////////////
// Simple demo of _kbhit()
int main() {
printf("Press any key");
while (! _kbhit()) {
printf(".");
fflush(stdout);
usleep(1000);
}
printf("\nDone.\n");
return 0;
}
在我看来,这是正确的,而valgrind没有抱怨。我没有记忆博士可查。
此代码的工作方式是,它首先使用tcgetattr
来读取termios(我认为是终端输入输出设置)结构。然后,通过取消设置ICANON位来对其进行修改。佳能是终端的规范设置,其中包括行缓冲。然后,它将新的termios值写回到终端。与tcsetattr
。
ioctl
调用获取缓冲区中正在等待多少字节。如果有字节在等待,那么有人按下了某些键。