【问题标题】:How to read user input before pressing enter?如何在按 Enter 之前读取用户输入?
【发布时间】:2017-06-26 20:08:52
【问题描述】:

我正在尝试用 C 语言编写一个示例程序,它可以逐个字符地读取用户输入的内容,而无需用户按 Enter。我使用了here 看到的代码,它工作得很好,只是有一个小问题。我想在用户按下回车时处理所有用户的输入,而当我使用system(/bin/stty raw); 时,程序无法再检测到它。如:

int n, i;
char buffer[50];
system ("/bin/stty raw");
for(i=0; i<30 ; i++) {

    buffer[i] = getchar();
    printf("%d\n", buffer[i] == '\n');   //this prints 0 when I press enter
    if(buffer[i] == '\n'){
        break;
    }
}
printf("%s\n",buffer);

system ("/bin/stty cooked");

有没有办法检测用户在执行此操作时是否按下了回车键?

我实际上想要做的是在用户按下回车之前阅读用户的输入,但在他们这样做时做一些事情。我想到的另一种方法是,如果我不逐个字符地读取它,而是使用例如fgets(buffer, 255, stdin);,有没有办法在用户按下回车之前读取 stdin 的缓冲区?我想为此使用 Enter 键,因此不能在另一个字符上终止用户输入,例如使用 while((c=getchar())!= '.'){},使用 here 不是一个选项。

【问题讨论】:

  • 对于raw,您是否打开了icrnl 和/或inlcr?这些与输入上的 CR 到 NL(\r\n)映射有关。尝试:system("/bin/stty -a"); 在你的代码中——甚至可能两次,一次在打开raw 之前,一次在打开之后。或者,换句话说,在原始模式下工作时,您很有可能需要捕获\r,而不是\n
  • 这是所有代码。真的,我只漏掉了int main()return 0;
  • 如果你是在向我讲话,Luke,那么我并不是说你应该创建更多的 MCVE。我告诉你,stty raw 命令正在更改终端中的许多设置,其中一些与 CR (\r) 到 NL (\n) 的转换有关,反之亦然。我还建议您可以尝试在执行stty raw 之前和之后查找设置——这将帮助您确定发生了什么变化。此外,正如答案中所指出的,您应该考虑使用 POSIX &lt;termios.h&gt; 标头和相关功能来更直接地管理终端设置。
  • 您可能会发现在程序篡改终端控件之前捕获stty -g 的输出很有用(使用popen()),然后您可以使用该字符串将终端重置为确切状态它在 stty -g 运行时。
  • 另请注意,getchar 返回int 而不是char 是有原因的,并且您在此处导致的从intchar 的隐式缩小转换会丢弃信息...弄清楚这些信息是什么,因为它可能对您解决尚未注意到的错误有用。

标签: c


【解决方案1】:

您使用stty raw 禁用的终端设置也负责协调\r\n

您可以使用stty -icanon min 1 仅禁用缓冲,或者同时接受\r\n 作为输入。

PS:使用 TCGETS/TCSETS ioctl 来获取、修改和重新应用以前的设置而不是调用 stty 并在之后强制执行熟模式是一种很好的做法。

【讨论】:

  • 对不起,我不太明白。你的意思是我应该检查 \r 而不是 \n?如果是这样,那很好。编辑:没关系,我试过了,它适用于buffer[i] == '\r'
猜你喜欢
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多