Вот версия кода, который я модифицировал, чтобы он был настоящим C, а не C++, поскольку он был C++ только из-за небрежности с ключевыми словами bool true/false и struct.
И да, не помещайте это в заголовочный файл. Поместите его в файл с именем kbhit.c и удалите или закомментируйте тестовую основную функцию. И в заголовочном файле просто напишите строку:
int _kbhit(void);
Или вам может понадобиться:
extern "C" int _kbhit(void);
Это все, что вам нужно в шапке.
/**
Linux (POSIX) implementation of _kbhit().
Morgan McGuire, [email protected]
*/
#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. Canon — это каноническая настройка для терминалов, включающая буферизацию строк. Затем он записывает новые значения termios обратно в терминал. с tcsetattr
.
Вызов ioctl
получает, сколько байтов ожидает в буфере. Если есть ожидающие байты, значит кто-то нажал какие-то клавиши.
person
Zan Lynx
schedule
18.02.2019
tcsetattr
будет вызываться ровно один раз за время жизни программы, становится сомнительным называть это утечкой памяти, поскольку любое выделение, которое она производит, будет освобождено при выходе из процесса. Единственное, что я могу придумать, это то, что вы намекаете на сохранение kbhit в виде заголовочного файла. Означает ли это, что вы, возможно, связываете несколько копий этого кода для каждого исходного файла (и вызываете его из разных исходных файлов). Просто чтобы исключить невероятное, убедитесь, что у вас нет кода в файлах заголовков. - person selbie   schedule 18.02.2019tcgetattr
записывает в структуру. Я знаю, что у valgrind есть всевозможные пользовательские правила для определения подобных вещей для известных библиотек. - person Zan Lynx   schedule 21.02.2019