简体   繁体   English

在C中读取字符时打印

[英]Printing while reading characters in C

I'm trying to write a simple little snippet of code to respond to an arrow key press. 我正在尝试编写一个简单的小代码片段来响应箭头按键。 I know that up is represented by ^[[A, and I have the following code that checks for that sequence: 我知道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;
                 }
             }
         }
     }

Whenever I hit "up", the escape sequence (^[[A) shows up on the screen, but "Move up" doesn't appear until I hit enter. 每当我点击“向上”时,转义序列(^ [[A]显示在屏幕上,但“上移”直到我按下回车才出现。

The end goal is to replace the text on the current line with some other data, and so I tried to do 最终目标是用其他一些数据替换当前行上的文本,所以我试着这样做

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

in place of "Move up", but it still doesn't show up until after enter is pressed. 取代“向上移动”,但在按下输入后仍然不会显示。

Is there something wrong with the way I'm reading in characters? 我在读字的方式有问题吗?

Thanks! 谢谢!

EDIT Quick note, it's for *nix systems. 编辑快速注释,它适用于* nix系统。

SOLUTION Thanks for the pointers everyone. 解决方案感谢大家的指点。 I went with stepanbujnak's solution because it was rather straightforward. 我选择了stepanbujnak的解决方案,因为它非常简单。 The one thing I noticed is that a lot of the behavior of keys that modify the string ( backspace, etc ) is different than you would expect. 我注意到的一件事是修改字符串(退格等)的键的很多行为与你期望的不同。 It will backspace through ANYTHING on the line (including printf'd stuff), and I had to account for that. 它会在线上退出任何东西(包括printf'd的东西),我不得不考虑到这一点。 After that it wasn't too bad getting the rest to fall in line :) 在那之后,让其他人排成一行并不是太糟糕:)

stdin is line buffered and hence getc(stdin) or fgetc(stdin) don't get to see those characters till you press ENTER See this link for more details stdin是行缓冲的,因此getc(stdin)fgetc(stdin)直到你按ENTER才能看到这些字符。查看此链接了解更多详情

EDIT : If you don't want to get into ncurses there are other useful methods like setting the terminal to raw mode etc to overcome this limitation. 编辑 :如果您不想进入ncurses还有其他有用的方法,如将终端设置为原始模式等,以克服此限制。 Check this nice SO post 检查这个不错的SO帖子

Capture characters from standard input without waiting for enter to be pressed 从标准输入中捕获字符,无需等待按下输入

You actually only need to disable line buffering using termios 实际上,您只需要使用termios禁用行缓冲

Here's an example of doing it: 这是一个这样做的例子:

#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;
}

Look at the curses library for capturing escape sequences such as arrow keys. 查看curses库以捕获转义序列,例如箭头键。

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

On most systems keys such as arrow keys, home, page up, break etc are escaped keys they use an escape sequence to discern themselves. 在大多数系统键上,例如箭头键,主页,向上翻页,中断等都是转义键,它们使用转义序列来识别自己。 Something like 0x1B + Sequence, if you wanted to capture it raw you'd need to read the input directly from the file descriptor and listen for the sequences. 像0x1B + Sequence这样的东西,如果你想原始捕获它,你需要直接从文件描述符读取输入并监听序列。 The alternative is above using ncurses. 另一种方法是使用ncurses。

Outside of using curses the following illustrates how to accomplish this using system call(s) such as read 在使用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;
}

output after pressing UP 按UP后输出

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

This should get you on your way. 这应该可以帮到你。

You can buffer the input looking for 0x1b and then enable a parsing flag to look for an escape sequence of characters in lieu of single character parsing. 您可以缓冲输入以查找0x1b ,然后启用解析标志以查找转义字符序列以代替单字符解析。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM