while(ch != 'q')
{
printf("looping\n");
sleep(1);
if(kbhit())
{
ch = readch();
printf("you hit %c\n",ch);
}
}
This code gives me a blocking getch() like functionality. I am trying to use this code to capture up down arrow keys.
这段代码给了我一个阻塞getch()之类的功能。我试图使用此代码捕获向下箭头键。
Added: Trying to capture key codes of up arrow gives me 3 chars 27, 91 and 65. Using if/else I am trying pattern matching but I only get 2 chars. Next one is captured when next key is pressed.
补充:尝试捕获向上箭头的关键代码给我3个字符27,91和65.使用if / else我正在尝试模式匹配,但我只得到2个字符。按下下一个键时捕获下一个。
I want to capture full words using getchar() while always looking for certain keys all the time(esc, del etc.).
我想使用getchar()捕获完整的单词,同时总是一直在寻找某些键(esc,del等)。
2 个解决方案
#1
1
This example could help:
这个例子可以帮助:
raw.c - raw mode demonstration
/* Raw mode demo */
/* See exactly what is being transmitted from the terminal. To do this
we have to be more careful. */
#include <stdio.h>
#include <signal.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
struct termios oldtermios;
int ttyraw(int fd)
{
/* Set terminal mode as follows:
Noncanonical mode - turn off ICANON.
Turn off signal-generation (ISIG)
including BREAK character (BRKINT).
Turn off any possible preprocessing of input (IEXTEN).
Turn ECHO mode off.
Disable CR-to-NL mapping on input.
Disable input parity detection (INPCK).
Disable stripping of eighth bit on input (ISTRIP).
Disable flow control (IXON).
Use eight bit characters (CS8).
Disable parity checking (PARENB).
Disable any implementation-dependent output processing (OPOST).
One byte at a time input (MIN=1, TIME=0).
*/
struct termios newtermios;
if(tcgetattr(fd, &oldtermios) < 0)
return(-1);
newtermios = oldtermios;
newtermios.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
/* OK, why IEXTEN? If IEXTEN is on, the DISCARD character
is recognized and is not passed to the process. This
character causes output to be suspended until another
DISCARD is received. The DSUSP character for job control,
the LNEXT character that removes any special meaning of
the following character, the REPRINT character, and some
others are also in this category.
*/
newtermios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
/* If an input character arrives with the wrong parity, then INPCK
is checked. If this flag is set, then IGNPAR is checked
to see if input bytes with parity errors should be ignored.
If it shouldn't be ignored, then PARMRK determines what
character sequence the process will actually see.
When we turn off IXON, the start and stop characters can be read.
*/
newtermios.c_cflag &= ~(CSIZE | PARENB);
/* CSIZE is a mask that determines the number of bits per byte.
PARENB enables parity checking on input and parity generation
on output.
*/
newtermios.c_cflag |= CS8;
/* Set 8 bits per character. */
newtermios.c_oflag &= ~(OPOST);
/* This includes things like expanding tabs to spaces. */
newtermios.c_cc[VMIN] = 1;
newtermios.c_cc[VTIME] = 0;
/* You tell me why TCSAFLUSH. */
if(tcsetattr(fd, TCSAFLUSH, &newtermios) < 0)
return(-1);
return(0);
}
int ttyreset(int fd)
{
if(tcsetattr(fd, TCSAFLUSH, &oldtermios) < 0)
return(-1);
return(0);
}
void sigcatch(int sig)
{
ttyreset(0);
exit(0);
}
int main()
{
int i;
char c;
/* Catch the most popular signals. */
if((int) signal(SIGINT,sigcatch) < 0)
{
perror("signal");
exit(1);
}
if((int)signal(SIGQUIT,sigcatch) < 0)
{
perror("signal");
exit(1);
}
if((int) signal(SIGTERM,sigcatch) < 0)
{
perror("signal");
exit(1);
}
/* Set raw mode on stdin. */
if(ttyraw(0) < 0)
{
fprintf(stderr,"Can't go to raw mode.\n");
exit(1);
}
while( (i = read(0, &c, 1)) == 1)
{
if( (c &= 255) == 0177) /* ASCII DELETE */
break;
printf( "%o\n\r", c);
}
if(ttyreset(0) < 0)
{
fprintf(stderr, "Cannot reset terminal!\n");
exit(-1);
}
if( i < 0)
{
fprintf(stderr,"Read error.\n");
exit(-1);
}
return 0;
}
(backspace to stop the demo, origin)
(退格停止演示,原点)
#2
3
I can't reproduce Your problem:
我无法重现你的问题:
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include "kbhit.h" /* http://linux-sxs.org/programming/kbhit.html */
int main(){
init_keyboard();
char ch='x';
while( ch != 'q' ){
printf("looping\n");
sleep(1);
if( kbhit() ){
printf("you hit");
do{
ch = readch();
printf(" '%c'(%i)", isprint(ch)?ch:'?', (int)ch );
}while( kbhit() );
puts("");
}
}
close_keyboard();
}
#1
1
This example could help:
这个例子可以帮助:
raw.c - raw mode demonstration
/* Raw mode demo */
/* See exactly what is being transmitted from the terminal. To do this
we have to be more careful. */
#include <stdio.h>
#include <signal.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
struct termios oldtermios;
int ttyraw(int fd)
{
/* Set terminal mode as follows:
Noncanonical mode - turn off ICANON.
Turn off signal-generation (ISIG)
including BREAK character (BRKINT).
Turn off any possible preprocessing of input (IEXTEN).
Turn ECHO mode off.
Disable CR-to-NL mapping on input.
Disable input parity detection (INPCK).
Disable stripping of eighth bit on input (ISTRIP).
Disable flow control (IXON).
Use eight bit characters (CS8).
Disable parity checking (PARENB).
Disable any implementation-dependent output processing (OPOST).
One byte at a time input (MIN=1, TIME=0).
*/
struct termios newtermios;
if(tcgetattr(fd, &oldtermios) < 0)
return(-1);
newtermios = oldtermios;
newtermios.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
/* OK, why IEXTEN? If IEXTEN is on, the DISCARD character
is recognized and is not passed to the process. This
character causes output to be suspended until another
DISCARD is received. The DSUSP character for job control,
the LNEXT character that removes any special meaning of
the following character, the REPRINT character, and some
others are also in this category.
*/
newtermios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
/* If an input character arrives with the wrong parity, then INPCK
is checked. If this flag is set, then IGNPAR is checked
to see if input bytes with parity errors should be ignored.
If it shouldn't be ignored, then PARMRK determines what
character sequence the process will actually see.
When we turn off IXON, the start and stop characters can be read.
*/
newtermios.c_cflag &= ~(CSIZE | PARENB);
/* CSIZE is a mask that determines the number of bits per byte.
PARENB enables parity checking on input and parity generation
on output.
*/
newtermios.c_cflag |= CS8;
/* Set 8 bits per character. */
newtermios.c_oflag &= ~(OPOST);
/* This includes things like expanding tabs to spaces. */
newtermios.c_cc[VMIN] = 1;
newtermios.c_cc[VTIME] = 0;
/* You tell me why TCSAFLUSH. */
if(tcsetattr(fd, TCSAFLUSH, &newtermios) < 0)
return(-1);
return(0);
}
int ttyreset(int fd)
{
if(tcsetattr(fd, TCSAFLUSH, &oldtermios) < 0)
return(-1);
return(0);
}
void sigcatch(int sig)
{
ttyreset(0);
exit(0);
}
int main()
{
int i;
char c;
/* Catch the most popular signals. */
if((int) signal(SIGINT,sigcatch) < 0)
{
perror("signal");
exit(1);
}
if((int)signal(SIGQUIT,sigcatch) < 0)
{
perror("signal");
exit(1);
}
if((int) signal(SIGTERM,sigcatch) < 0)
{
perror("signal");
exit(1);
}
/* Set raw mode on stdin. */
if(ttyraw(0) < 0)
{
fprintf(stderr,"Can't go to raw mode.\n");
exit(1);
}
while( (i = read(0, &c, 1)) == 1)
{
if( (c &= 255) == 0177) /* ASCII DELETE */
break;
printf( "%o\n\r", c);
}
if(ttyreset(0) < 0)
{
fprintf(stderr, "Cannot reset terminal!\n");
exit(-1);
}
if( i < 0)
{
fprintf(stderr,"Read error.\n");
exit(-1);
}
return 0;
}
(backspace to stop the demo, origin)
(退格停止演示,原点)
#2
3
I can't reproduce Your problem:
我无法重现你的问题:
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include "kbhit.h" /* http://linux-sxs.org/programming/kbhit.html */
int main(){
init_keyboard();
char ch='x';
while( ch != 'q' ){
printf("looping\n");
sleep(1);
if( kbhit() ){
printf("you hit");
do{
ch = readch();
printf(" '%c'(%i)", isprint(ch)?ch:'?', (int)ch );
}while( kbhit() );
puts("");
}
}
close_keyboard();
}