【问题标题】:breaking loop with keypress in linux c在linux c中使用按键打破循环
【发布时间】:2013-03-09 12:49:23
【问题描述】:

我需要用 C 语言编写一个程序,它会做这样的事情: 例如,当我按下“a”时,终端将像这样在无休止的循环中写入键入的字符:aaaaaaaaaaaaaaaa...直到按下另一个键,例如“b”。最终输出应该如下所示:aaaaaaaaabbbbbbq(q 应该终止程序)。 我的代码在这里:

int main(int argc, char** argv) {

    int c;
    static struct termios staryTermios, novyTermios;


    tcgetattr(STDIN_FILENO, &staryTermios);

    novyTermios = staryTermios;
    novyTermios.c_lflag &= ~(ICANON);
    tcsetattr(STDIN_FILENO, TCSANOW, &novyTermios);
    while ((c = getchar()) != 'q') {
        putchar(c);
    }

    tcsetattr( STDIN_FILENO, TCSANOW, &staryTermios);

    return 0;
}

这个版本只写一次输入的字符,然后等待另一个按键

【问题讨论】:

    标签: c keypress


    【解决方案1】:

    要达到你想要的结果,你需要使标准输入非阻塞。您可以通过对代码的这种小修改来做到这一点。它在 Mac OS X 10.7.5 上运行良好。请注意,getchar() 在没有准备好读取的字符时返回 EOF(大多数情况下;您和我都无法以足够快的速度键入现代计算机)。我有点担心,在某些系统上,一旦 getchar() 在没有字符可读取的情况下返回 EOF 一次,它可能永远不会再返回 EOF 以外的任何内容,但这对于 Mac OS X 来说不是问题。

    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdlib.h>
    
    static void err_exit(const char *msg);
    
    int main(void)
    {
        int c;
        int oc = '\0';
        struct termios staryTermios, novyTermios;
        int oflags, nflags;
    
        if (tcgetattr(STDIN_FILENO, &staryTermios) != 0)
            err_exit("tcgetattr() failed");
    
        novyTermios = staryTermios;
        novyTermios.c_lflag &= ~(ICANON);
        if (tcsetattr(STDIN_FILENO, TCSANOW, &novyTermios) != 0)
            err_exit("tcsetattr() failed to set standard input");
    
        oflags = fcntl(STDIN_FILENO, F_GETFL);
        if (oflags < 0)
            err_exit("fcntl() F_GETFL failed");
    
        nflags = oflags;
        nflags |= O_NONBLOCK;
        if (fcntl(STDIN_FILENO, F_SETFL, nflags) == -1)
            err_exit("fcntl() F_SETFL failed");
    
        while ((c = getchar()) != 'q')
        {
            if (c != EOF)
                oc = c;
            if (oc != '\0')
                putchar(oc);
        }
    
        if (tcsetattr(STDIN_FILENO, TCSANOW, &staryTermios) != 0)
            err_exit("tcsetattr() failed to reset standard input");
    
        putchar('\n');
        return 0;
    }
    
    static void err_exit(const char *msg)
    {
        fprintf(stderr, "%s\n", msg);
        exit(1);
    }
    

    【讨论】:

      【解决方案2】:

      我猜你需要两个线程来访问一个公共变量。一个线程的工作是连续打印公共变量。第二个的工作是等待来自键盘的输入并相应地更新变量。

      【讨论】:

      • 谢谢,但我是 C 编程新手,不知道如何使用线程。我的朋友建议我使用 read() 函数而不是 od getchar()。但我不知道如何超时 read() 函数或类似的东西
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-16
      • 2021-08-29
      相关资源
      最近更新 更多