Linux: снова вопрос про аналог conio.h (неблокирующий ввод с клавиатуры под linux)
Господа,
мой вопрос настолько классический, что прямо смешно. Он называется "неблокирующий ввод с клавиатуры под linux".
Я хочу иметь возможность в программе на C спросить "верни мне, пожалуйста, код нажатой клавиши, а если ничего не нажато - верни -1".
Под виндой именно такую функциональность даёт include <conio.h> ... int kb=getch();.
Конечно, я прочитал вот этот и вот этот топики и поэкспериментировал с теми способами, котрые там советуют.
У них есть один недостаток: они "ломают вывод на экран" при помощи простого printf().
То есть, по меткому выражению одного из комментаторов, используя ncurses вы получаете "всё или ничего". То есть, если Вы подключили ncurses - нужно забыть про printf и использовать специфичные для ncurses способы вывода на экран.
С советом, в котором приводится код для getch()
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
return c;
}
}
(это кусочек из полного кода, который доступен по первой ссылке) всё немного лучше, но всё равно, при попытке в цикле вводить симолы и печатаь их коды на экране возникает вот такая картина:
код main'а: (выше мейна написан целиком тот код, который советуют в самом популярном ответе по первой ссылке)
int main(int argc, char *argv[]) {
printf("Hello again!\n");
set_conio_terminal_mode();
while (!kbhit()) {
/* do some work */
}
for(int i=0; i<5; ++i){
int kb = getch(); /* consume the character */
printf ("kb=%d\n", kb);
}
printf ("Bye!\n");
}
картинка на экране:
Ну, то есть, при выполнении каждого printf положение "виртуальной каретки" смещается.
Нельзя ли с этим как то побороться? может, есть способ, как вводить символы с клавиатуры и при этом нормально пользоваться printf?
Ответы (1 шт):
Вы меня устыдили и я быстренько попробовал вспомнить.
У меня
avp@avp-desktop:~/avp/hashcode$ uname -a
Linux avp-desktop 5.4.0-70-generic #78~18.04.1-Ubuntu SMP Sat Mar 20 14:10:07 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
avp@avp-desktop:~/avp/hashcode$ cat /etc/issue
Linux Mint 19.3 Tricia \n \l
avp@avp-desktop:~/avp/hashcode$ echo $TERM
xterm-256color
avp@avp-desktop:~/avp/hashcode$
Вот программка для печати кодов вводимых символов
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
int main()
{
struct termios t, old;
tcgetattr(0, &t);
old = t;
t.c_lflag &= ~(ISIG | ICANON | ECHO);
t.c_cc[VMIN] = 1;
t.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &t);
char c;
while (read(0, &c, 1) == 1) {
printf("'%c' is %d 0%03o 0x%02x\n",
c, c, c, c);
if (c == 4) // ^D is EOF as usual
break;
}
tcsetattr(0, TCSANOW, &old);
return puts("End") == EOF;
}
Я немного подолбил по клавишам и кажется, что у меня она вполне работает:
avp@avp-desktop:~/avp/hashcode$ gcc ttt.c && ./a.out
'1' is 49 0061 0x31
'2' is 50 0062 0x32
'3' is 51 0063 0x33
'
' is 10 0012 0x0a
'
' is 10 0012 0x0a
'
' is 10 0012 0x0a
'
' is 11 0013 0x0b
'q' is 113 0161 0x71
'w' is 119 0167 0x77
'e' is 101 0145 0x65
'' is 127 0177 0x7f
'!' is 33 0041 0x21
'@' is 64 0100 0x40
'$' is 36 0044 0x24
'' is 4 0004 0x04
avp@avp-desktop:~/avp/hashcode$
