Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中处理Linux控制台中按下的键?_C_Linux_Keyboard - Fatal编程技术网

如何在C中处理Linux控制台中按下的键?

如何在C中处理Linux控制台中按下的键?,c,linux,keyboard,C,Linux,Keyboard,我正在使用Linux控制台,我想做一个程序,输出随机字符,直到按下ESC键。我怎样才能制作这样一个键盘处理程序呢?也许是来自诅咒库?此外,您还需要使用notimeout()告诉getch()不要等待下一次按键。\include #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> char * me = "Parent"; void s

我正在使用Linux控制台,我想做一个程序,输出随机字符,直到按下ESC键。我怎样才能制作这样一个键盘处理程序呢?

也许是来自诅咒库?此外,您还需要使用notimeout()告诉getch()不要等待下一次按键。

\include
#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);
}
#包括 #包括 #包括 char*me=“家长”; 无效符号(整数符号) { //printf(“==%s退出信号%d===\n”,me,signum); 出口(0); } main() { int-pid=fork(); 信号(SIGINT,sigkill); 信号(SIGQUIT、sigkill); 信号(SIGTERM,sigkill); if(pid==0)//if子级 { int-ch; me=“Child”; 而(1) { ch=(rand()%26)+“A”;//将范围限制为ascii A-Z printf(“%c”,ch); fflush(stdout);//刷新输出缓冲区 睡觉(2);//不要过度紧张 如果(1==getppid()) { printf(“==自父项死亡后的子项退出==\n”); 出口(0); } } printf(“==子退出正常==\n”); } else//父进程 { int-ch; 如果((ch=getchar())==27) kill(pid,SIGINT); //printf(“==父退出正常(ch=%d)==\n”,ch); } 返回(0); }
在这个程序中,你只需要在
esc
char之后按
enter
,因为
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);
}

默认情况下,终端设备的线路规程通常在规范模式下工作。在此模式下,终端驱动程序在看到换行符(按下回车键)之前不会向用户空间显示缓冲区

您可以使用
操作
termios
结构,将终端设置为原始(非规范)模式。清除
ECHO
ICANON
标志分别会禁用键入字符时的回显,并导致直接从输入队列满足读取请求。在
c_cc
数组中将
VTIME
VMIN
的值设置为零会导致读取请求(
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;
}
定义源代码700
#包括
#包括
#包括
#包括
#包括
int getkey(){
整数字符;
结构术语或术语属性;
struct termios new_term_attr;
/*将终端设置为原始模式*/
tcgetattr(文件编号(标准输入)和原始术语属性);
memcpy(&new_term_attr,&orig_term_attr,sizeof(struct termios));
新术语(属性c)lflag&=~(ECHO)ICANON);
新术语属性c_cc[VTIME]=0;
新项属性c_cc[VMIN]=0;
tcsetattr(文件号(标准输入)、TCSANOW和新术语属性);
/*从stdin流中读取字符而不阻塞*/
/*如果没有可用字符,则返回EOF(-1)*/
字符=fgetc(标准输入法);
/*恢复原始端子属性*/
tcsetattr(文件号(标准输入)、TCSANOW和原始术语属性);
返回字符;
}
int main()
{
int键;
/*初始化随机数生成器*/
srand(时间(空));
对于(;;){
key=getkey();
/*在ESC(0x1B)上终止循环或在STDIN上终止Ctrl-D(0x04)*/
如果(键==0x1B | |键==0x04){
打破
}
否则{
/*打印0x20-0x7F之间的随机ASCII字符*/
键=(rand()%0x7F);
printf(“%c”,((键<0x20)?(键+0x20):键));
}
}
返回0;
}

注意:为了简单起见,此代码省略了错误检查

除了
getchar
等待输入之外,因此在
getchar
等待用户按[enter]键时不会输出任何随机字符。您应该明确指出您正在谈论(N)curses库。注意:ncurses中的getch()需要正确的ncurses“屏幕”进行初始化,或者它不起作用。你还必须初始化库-这是@ShinTakezou所说的变体。类似和/或相关-不
ICRNL
进入
c\u iflag
字段,而不是
c\u lflag
字段?这似乎可行,但似乎每次都提供了整个缓冲区。所以如果我按a,然后按b,然后按c,在按c之后它会显示出来aababc@Jackie可能在(getchar()!=EOF)时执行
while
字符=fgetc(标准输入法)非常感谢您提供了非常简洁的答案!