Пищалка
Коллеги, я хочу показать вам как должна выглядеть 21 лаба, чтобы всемогущий её принял, потому что лаба реально простая, но ему не нравиться, что при решение срабатывает не только DELETE, что возникает при использование массива c_cc в termios.
Задача:
Напишите программу, которая входит в бесконечный цикл и издает звуковой сигнал на вашем терминале каждый раз, когда вы нажимаете DELETE. При получении SIGQUIT, она должна вывести сообщение, говорящее, сколько раз прозвучал сигнал, и завершиться.
Проблема:
Я пытался в настройках терминала указать в массив c_cc, чтобы он по нажатию delete слал сигнал, но у delete нет ascii кода, он попадает в терминал как код сразу 4 символов, так как является управляющей клавишей.
Решение:
Я приделал функцию, которая четырьмя getchar проверяет, что пришёл именно delete.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#define ERR_CODE -1
#define ERR_PROC_CODE 1
//delete key codes
#define DELETE_1CODE 27
#define DELETE_2CODE 91
#define DELETE_3CODE 51
#define DELETE_4CODE 126
int bell_count = 0;
struct termios old_term;
int filenoe(FILE * f) {
int desc = fileno(f);
if(desc == ERR_CODE) {
exit(ERR_PROC_CODE);
}
return desc;
}
void reset()
{
if(ERR_CODE == tcsetattr(filenoe(stdin), TCSANOW, &old_term)) {
perror("tcsetattr");
exit(ERR_PROC_CODE);
}
exit(0);
}
void finprint(int sgn)
{
printf("Bell ringed %i\n", bell_count);
reset();
}
char delIsReading() {
if((DELETE_1CODE == getchar()) &&
(DELETE_2CODE == getchar()) &&
(DELETE_3CODE == getchar()) &&
(DELETE_4CODE == getchar())){
return 1;
} else {
return 0;
}
}
int main(int argc, char** argv)
{
struct termios term;
if (ERR_CODE == tcgetattr(filenoe(stdin), &old_term))
{
perror("tcgetattr");
exit(ERR_PROC_CODE);
}
if(SIG_ERR == signal(SIGQUIT, finprint)) {
perror("signal");
exit(ERR_PROC_CODE);
}
term = old_term;
term.c_lflag &= ~ (ICANON | ECHO);
term.c_cc[VMIN] = 1;
if (ERR_CODE == tcsetattr(filenoe(stdin), TCSANOW, &term))
{
perror("tcsetattr");
exit(ERR_PROC_CODE);
}
while (1)
{
if (1 == delIsReading())
{
printf("din-don\a\n");
bell_count++;
}
}
reset();
return 0;
}
P.S. Если кто не в курсе, то SIGQUIT по умолчанию посылается на "ctrl+\". И если придумаете как отловить delete более изящным способом, мне скажите))
Комментариев нет:
Отправить комментарий