在C中读取字符时打印

时间:2012-04-19 13:15:04

标签: c stream newline printf carriage-return

我正在尝试编写一个简单的小代码片段来响应箭头按键。 我知道up由^ [[A表示,我有以下代码检查该序列:

     while( 1 )
     {
         input_char = fgetc( stdin );

         if( input_char == EOF || input_char == '\n' )
         {
             break;
         }

         /* Escape sequence */
         if( input_char == 27 )
         {
             input_char = getc( stdin );

             if( input_char == '[' )
             {
                 switch( getc( stdin ) )
                 {
                     case 'A':
                     printf("Move up\n");
                     break;
                 }
             }
         }
     }

每当我点击“向上”时,转义序列(^ [[A]会出现在屏幕上,但在我按下回车之前不会出现“向上移动”)。

最终目标是将当前行上的文本替换为其他一些数据,因此我尝试了

printf("\r%s", "New Text");

取代“向上移动”,但在按下输入后仍然不显示。

我在读字的方式有问题吗?

谢谢!

编辑快速说明,它适用于* nix系统。

的 感谢大家的指点。我选择了stepanbujnak的解决方案,因为它非常简单。我注意到的一件事是修改字符串(退格等)的键的很多行为与你期望的不同。它会在线上退出任何东西(包括printf'd的东西),我不得不考虑到这一点。在那之后,让其他人排成一行并不太糟糕:)

3 个答案:

答案 0 :(得分:10)

stdin是行缓冲的,因此getc(stdin)fgetc(stdin)无法看到这些字符,直到您按 ENTER 查看此link了解更多详情

编辑:如果您不想进入ncurses,还有其他有用的方法,例如将终端设置为原始模式等来克服此限制。检查这个好的SO帖子

Capture characters from standard input without waiting for enter to be pressed

答案 1 :(得分:3)

您实际上只需要使用 termios

禁用线路缓冲

以下是这样做的一个例子:

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>

int main() {
  struct termios old_term, new_term;
  char c;

  /* Get old terminal settings for further restoration */
  tcgetattr(0, &old_term);

  /* Copy the settings to the new value */
  new_term = old_term;

  /* Disable echo of the character and line buffering */
  new_term.c_lflag &= (~ICANON & ~ECHO);
  /* Set new settings to the terminal */
  tcsetattr(0, TCSANOW, &new_term);

  while ((c = getchar()) != 'q') {
    printf("You pressed: %c\n", c);
  }

  /* Restore old settings */
  tcsetattr(0, TCSANOW, &old_term);

  return 0;
}

答案 2 :(得分:1)

查看curses库以捕获转义序列,例如箭头键。

http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/keys.html

在大多数系统键上,如箭头键,主页,向上翻页,中断等都是转义键,它们使用转义序列来识别自己。像0x1B + Sequence这样的东西,如果你想原始捕获它,你需要直接从文件描述符读取输入并监听序列。另一种方法是使用ncurses。

除了使用curses之外,以下说明如何使用系统调用(例如read

)来完成此操作
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    int fd = 0x0; /* STDIN */
    size_t bytes_read;
    char buf[12];

    bytes_read = read(fd, buf, 3);
    printf("%02x %02x %02x\n", buf[0], buf[1], buf[2]);
    return 0;
}
按UP后

输出

Lukes-ASA-Macbook:tmp luke$ gcc -o out test.c
Lukes-ASA-Macbook:tmp luke$ ./out
^[[A
1b 5b 41

这应该可以帮助你。

您可以缓冲输入以查找0x1b,然后启用解析标志以查找转义字符序列,而不是单个字符解析。