C非阻塞键盘输入

2023-11-30

我正在尝试用 C(在 Linux 上)编写一个程序,该程序循环直到用户按下某个键,但不需要按键来继续每个循环。

有没有一种简单的方法可以做到这一点?我想我可以用select()但这似乎需要很多工作。

Alternatively, is there a way to catch a ctrl-c keypress to do cleanup before the program closes instead of non-blocking io?


如前所述,您可以使用sigaction捕获 ctrl-c,或者select捕获任何标准输入。

但请注意,使用后一种方法时,您还需要设置 TTY,使其处于一次字符模式而不是一次一行模式。后者是默认设置 - 如果您输入一行文本,直到您按 Enter 键为止,它不会发送到正在运行的程序的标准输入。

你需要使用tcsetattr()函数可以关闭 ICANON 模式,也可能禁用 ECHO。根据记忆,当程序退出时,您还必须将终端设置回 ICANON 模式!

为了完整起见,这里有一些我刚刚敲出的代码(注意:没有错误检查!),它设置了 Unix TTY 并模拟 DOS<conio.h>功能kbhit() and getch():

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <termios.h>

struct termios orig_termios;

void reset_terminal_mode()
{
    tcsetattr(0, TCSANOW, &orig_termios);
}

void set_conio_terminal_mode()
{
    struct termios new_termios;

    /* take two copies - one for now, one for later */
    tcgetattr(0, &orig_termios);
    memcpy(&new_termios, &orig_termios, sizeof(new_termios));

    /* register cleanup handler, and set the new terminal mode */
    atexit(reset_terminal_mode);
    cfmakeraw(&new_termios);
    tcsetattr(0, TCSANOW, &new_termios);
}

int kbhit()
{
    struct timeval tv = { 0L, 0L };
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(0, &fds);
    return select(1, &fds, NULL, NULL, &tv) > 0;
}

int getch()
{
    int r;
    unsigned char c;
    if ((r = read(0, &c, sizeof(c))) < 0) {
        return r;
    } else {
        return c;
    }
}

int main(int argc, char *argv[])
{
    set_conio_terminal_mode();

    while (!kbhit()) {
        /* do some work */
    }
    (void)getch(); /* consume the character */
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C非阻塞键盘输入 的相关文章

随机推荐

  • 如何将字符串发送到终端而不需要将其作为标准命令?

    我正在用Java编写一个程序 需要使用终端命令才能工作 我的功能基本上是这样的 public void sendLoginCommand throws IOException System out println n Sending Log
  • 在 Ubuntu 12 上安装最新版本的 R?

    我在 Ubuntu 机器上安装 R 时遇到问题 每当我尝试安装软件包时 都会出现错误 package xyz is not available for R version 2 14 1 我尝试通过终端本身安装 R 但无法升级 有没有办法 我
  • Android Things:连接到串行调试控制台

    我一直在尝试连接到串行控制台树莓派 3 with 安卓事物 using USB to TTL cable从我的Linux Ubuntu 机器 尽管我按照文档连接了电缆 但执行时我得到的只是minicom命令如下 with 没有机会输入任何字
  • 在 React hook 上使用 props 值有什么不好吗?

    我是反应钩子的新手 我只是在文档中没有看到这一点 const MyComponent myProp gt const myPropHook setPropHook useState myProp 我想知道这是否是一个好的做法 您传递给的值u
  • CSS中的margin和padding有什么区别?

    有什么区别margin and padding在CSS中 什么时候应该使用其中之一 padding 和 margin 之间最大的区别是垂直边距会自动折叠 而 padding 不会 考虑两个元素一个在另一个之上 每个元素的填充为1em 该填充
  • CodeIgniter 路由 - 仅从一个类的 URL 中删除类名

    我想重新映射这个 index php pages services进入这个index php services 我该怎么做 我尝试过这个 但它不起作用 route any pages 更新 这种方法有动态方法吗 因此 该类中的每个函数都将重
  • UITextView 不调用 ShouldChangeTextInRange

    我使用自定义 UITextView 并需要在返回单击时隐藏键盘 我需要捕获具有文本视图的 ShouldChangeTextInRange 我不知道为什么 但是 方法未被调用 这是我的文本视图的代码 public class Placehol
  • 在 Android 中启用当前禁用的 Spinner

    我在 Android 上闲逛 而我的 Java 知识充其量是有限的 例如 我对它允许内联类这一事实感到困惑 我的问题如下 我有一个布局 其中有三个下拉菜单 我在 onCreate 中初始化了所有三个 第一个从字符串数组中获取值 然而 第二个
  • R - 使用 ggplot2 和栅格包的地理参考栅格图像的原始颜色

    我想使用原来的colortable of a gt gt 地理参考光栅图像 tif 文件 作为彩色比例在 ggplot ggplot2 绘制的地图中 由于找不到更简单的解决方案 我访问了colortable 槽从legend 加载的光栅图像
  • 使用Boost读写XML文件

    有没有什么好的方法 也是一个简单的方法 使用Boost来读写XML文件 我似乎找不到任何使用 Boost 读取 XML 文件的简单示例 您能给我指一个使用 Boost 读写 XML 文件的简单示例吗 如果不是 Boost 有什么好的 简单的
  • array_intersect 多维数组内部

    我有一个多维数组 可以根据用户输入增加 我想在数组内执行 array intersect 以获得键之间的公共值 就像例子 Array php gt Array 0 gt 36 1 gt 51 2 gt 116 3 gt 171 4 gt 2
  • 报告公式中的小数点四舍五入

    我的水晶报表需要将数字四舍五入到小数点后两位 我努力了Round 55 815 2 但它返回55 81代替55 82 我该如何解决这个问题 如果出于显示目的需要对小数进行四舍五入 只需使用 减少小数 图标即可
  • 列出Android设备上的所有图像

    我试图列出自 14 小时以来 Android 设备中的所有图像及其路径 但我无法 它一直给我 java lang RuntimeException 无法启动活动 ComponentInfo 错误 我不明白为什么 有什么帮助吗 package
  • tolower() 不工作

    下面的代码片段用于将字符串转换为小写 int main unsigned char s AbS d tolower s printf s n s return 0 我正在得到output as AbS d 为什么字符串没有被转换 tolow
  • 在 MATLAB 中扫描每一列,无需 for 循环

    I 2 1 A 7 11 8 17 我怎样才能在 A 中选择正确的值而不for loop I是每列的索引向量A 那是I 1 is 8 and I 2 11 Use sub2ind根据正确的行和列坐标生成线性索引 然后使用它们进行索引A 在这
  • 如何提取 git 子目录并从中创建子模块?

    几个月前我开始了一个项目 并将所有内容存储在主目录中 在我的主目录 Project 中 有几个包含不同内容的子目录 项目 论文包含用 LaTeX 编写的文档 Project sourcecode RailsApp 包含我的 Rails 应用
  • 从原点拉取时“git pull”命令之间的差异?

    这些命令之间有什么区别 1 git pull 2 git pull origin 3 git pull origin master 4 git pull origin master 5 git pull origin HEAD master
  • 在 Outlook 插件中,如何检查我们是否处于撰写模式或阅读模式?

    我正在创建一个 Outlook 加载项并在 React 应用程序中使用 OfficeJS API 在那里 我想加载一组特定的撰写模式功能和另一组阅读模式功能 所以我的问题是 如何查看我当前处于哪种模式 如果您不想为读取和撰写模式创建两个单独
  • Android改变Material高程阴影颜色

    是否可以更改 xml 高程属性产生的阴影颜色 我希望通过代码动态改变阴影 我知道这个问题很老了 可能作者不再需要答案了 我会把它留在这里 以便其他人可以找到它 Lollipop 的高程系统不支持彩色阴影 但是 如果您需要彩色阴影 可以使用
  • C非阻塞键盘输入

    我正在尝试用 C 在 Linux 上 编写一个程序 该程序循环直到用户按下某个键 但不需要按键来继续每个循环 有没有一种简单的方法可以做到这一点 我想我可以用select 但这似乎需要很多工作 Alternatively is there