Я использую консоль Linux, и я хотел бы сделать программу, какие выводы случайные символы до ESC нажимаются. Как я могу сделать такой обработчик клавиатур?
getch () из библиотеки Curses, возможно? Кроме того, вам нужно будет использовать notimeout (), чтобы сообщить getch () не ждать следующего нажатия клавиши.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
char * me = "Parent";
void sigkill(int signum)
{
//printf("=== %s EXIT SIGNAL %d ===\n", me, signum);
exit(0);
}
main()
{
int pid = fork();
signal(SIGINT, sigkill);
signal(SIGQUIT, sigkill);
signal(SIGTERM, sigkill);
if(pid == 0) //IF CHILD
{
int ch;
me = "Child";
while(1)
{
ch = (rand() % 26) + 'A'; // limit range to ascii A-Z
printf("%c",ch);
fflush(stdout); // flush output buffer
sleep(2); // don't overwhelm
if (1 == getppid())
{
printf("=== CHILD EXIT SINCE PARENT DIED ===\n");
exit(0);
}
}
printf("==CHILD EXIT NORMAL==\n");
}
else //PARENT PROCESS
{
int ch;
if((ch = getchar())==27)
kill(pid, SIGINT);
//printf("==PARENT EXIT NORMAL (ch=%d)==\n", ch);
}
return(0);
}
В этой программе вам нужно будет только нажать enter
после esc
char, потому что getchar ()
является блокирующей функцией. .
Также вы можете удалить или уменьшить время сна для дочернего процесса по мере необходимости.
изменить настройки tty одним нажатием клавиши:
int getch(void) {
int c=0;
struct termios org_opts, new_opts;
int res=0;
//----- store old settings -----------
res=tcgetattr(STDIN_FILENO, &org_opts);
assert(res==0);
//---- set new terminal parms --------
memcpy(&new_opts, &org_opts, sizeof(new_opts));
new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);
tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);
c=getchar();
//------ restore old settings ---------
res=tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);
assert(res==0);
return(c);
}
Дисциплина линии для оконечного устройства по умолчанию часто работает в каноническом режиме. В этом режиме драйвер терминала не представляет буфер в пользовательское пространство до тех пор, пока не появится новая строка (нажата клавиша Enter ).
Вы можете установить терминал в необработанный (неканонический) режим, используя tcsetattr ()
для управления структурой termios
. Очистка флагов ECHO
и ICANON
соответственно отключает отображение символов при их вводе и вызывает удовлетворение запросов на чтение непосредственно из входной очереди. Установка значений VTIME
и VMIN
на ноль в массиве c_cc
вызывает немедленный возврат запроса на чтение ( fgetc ()
). чем блокировать; эффективно опрашивает stdin. Вызов fgetc ()
вернет EOF
, если символ недоступен в потоке.
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <time.h>
int getkey() {
int character;
struct termios orig_term_attr;
struct termios new_term_attr;
/* set the terminal to raw mode */
tcgetattr(fileno(stdin), &orig_term_attr);
memcpy(&new_term_attr, &orig_term_attr, sizeof(struct termios));
new_term_attr.c_lflag &= ~(ECHO|ICANON);
new_term_attr.c_cc[VTIME] = 0;
new_term_attr.c_cc[VMIN] = 0;
tcsetattr(fileno(stdin), TCSANOW, &new_term_attr);
/* read a character from the stdin stream without blocking */
/* returns EOF (-1) if no character is available */
character = fgetc(stdin);
/* restore the original terminal attributes */
tcsetattr(fileno(stdin), TCSANOW, &orig_term_attr);
return character;
}
int main()
{
int key;
/* initialize the random number generator */
srand(time(NULL));
for (;;) {
key = getkey();
/* terminate loop on ESC (0x1B) or Ctrl-D (0x04) on STDIN */
if (key == 0x1B || key == 0x04) {
break;
}
else {
/* print random ASCII character between 0x20 - 0x7F */
key = (rand() % 0x7F);
printf("%c", ((key < 0x20) ? (key + 0x20) : key));
}
}
return 0;
}
Примечание. В этом коде для простоты не выполняется проверка ошибок.