C程序中的标准输出转义查询和标准输入冲突(无ncurses)

C程序中的标准输出转义查询和标准输入冲突(无ncurses),c,escaping,printf,stdout,stdin,C,Escaping,Printf,Stdout,Stdin,我正在编写一个没有ncurses的小型cli程序,我面临一个问题。 我使用转义序列来查询光标位置,当用户没有输入或输入频率低时,这可以正常工作,但当用户输入频率高时,这会污染我的查询响应 我使用read处理用户输入,如下所示: read(0, &c, sizeof(c)) printf("\033[6n"); scanf("\033[%d;%dR", y, x); 我使用printf/scanf处理转义序列查询,如下所示: read(0, &c, sizeof(c)) pr

我正在编写一个没有ncurses的小型cli程序,我面临一个问题。 我使用转义序列来查询光标位置,当用户没有输入或输入频率低时,这可以正常工作,但当用户输入频率高时,这会污染我的查询响应

我使用read处理用户输入,如下所示:

read(0, &c, sizeof(c))
printf("\033[6n");
scanf("\033[%d;%dR", y, x);
我使用printf/scanf处理转义序列查询,如下所示:

read(0, &c, sizeof(c))
printf("\033[6n");
scanf("\033[%d;%dR", y, x);
为了解决这个问题,我尝试在每次读取后获取光标的位置。当我一直按一个键(例如“z”)时,我在printf和scanf之间收到一些z,因此scanf失败。 我希望在查询期间阻止或缓冲用户输入,但不是:(

在查询之后,我可以在scanf和buffer输入之前搜索stdin流上的序列,但这相当繁重,而且不是100%确定

有没有一个简单的解决办法来解决这个问题? (确保订单,在查询前阻止用户输入等)

在2014-07-01 21:21编辑:

我创建了一个小样本来解决这个问题。 标准键没有问题,但UP键或HOME键污染了printf/scanf查询序列

// Build gcc -o test main.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>

char getch();
void get_cursor_pos(int* x, int* y);
void reset_terminal_mode();

struct termios g_termios;

int main(int arc, char** argv)
{
    char c;
    int x,y;
    struct termios new_termios; 
    printf("TEST STDOUT/STDIN QUERY\n");

    // Setting raw terminal
    printf("Setting raw terminal mode...\n");
    tcgetattr(0, &g_termios);
    memcpy(&new_termios, &g_termios, sizeof(struct termios));
    atexit(reset_terminal_mode);
    cfmakeraw(&new_termios);            
    new_termios.c_oflag |= OPOST|ONLCR;
    tcsetattr(0, TCSANOW, &new_termios);

    // Main loop
    printf("Starting main loop...\n");
    printf("(Press [=] to abort)\n");
    do{
        c=getch();
    printf("0x%02X",c); 
    get_cursor_pos(&x,&y);
    printf("<%dx%d> ",x,y);         
    }while(c!='=');

    // End loop
    printf("\nEnd\n");
    return EXIT_SUCCESS;
}

char getch()
{
    char c;
    read(0, &c, sizeof(c));
    return c;
}

void get_cursor_pos(int* x, int* y)
{
    *x=0; 
    *y=0;
    printf("\033[6n");
    scanf("\033[%d;%dR", y, x);
}

void reset_terminal_mode()
{
    printf("Reset terminal mode...\n");
    tcsetattr(0, TCSANOW, &g_termios);
}
//构建gcc-o test main.c
#包括
#包括
#包括
#包括
char getch();
无效获取光标位置(int*x,int*y);
无效重置_终端_模式();
结构termios g_termios;
int main(int arc,字符**argv)
{
字符c;
int x,y;
结构术语新术语;
printf(“测试STDOUT/STDIN查询”);
//设置原始终端
printf(“设置原始终端模式…\n”);
tcgetattr(0和g_termios);
memcpy(&new_termios,&g_termios,sizeof(struct termios));
atexit(重置终端模式);
cfmakeraw(和新术语);
新术语c of lag |=OPOST | ONLCR;
tcSettTR(0、TCSANOW和new_termios);
//主回路
printf(“启动主循环…\n”);
printf(“(按[=]中止)\n”);
做{
c=getch();
printf(“0x%02X”,c);
获取光标位置(&x和&y);
printf(“”,x,y);
}而(c),;
//端环
printf(“\nEnd\n”);
返回退出成功;
}
char getch()
{
字符c;
读(0,&c,sizeof(c));
返回c;
}
无效获取光标位置(int*x,int*y)
{
*x=0;
*y=0;
printf(“\033[6n”);
扫描频率(“\033[%d;%dR”,y,x);
}
无效重置\终端\模式()
{
printf(“重置终端模式…\n”);
tcsetattr(0、TCSANOW和g_termios);
}
你能解释一下是什么吗


提前感谢

您不能使用
getch()
,如前所述,捕获
主页
箭头
键,因为键代码是多字节代码。您必须更改
getch()
处理单字节和多字节输入的函数,以捕获使用多字节代码的键。有关处理多字节输入的例程的详细说明和示例,请参阅。

程序的用户应该输入转义序列?似乎您对VT100转义序列的用途有一些误解…当您在某些模式下点击功能键或数字键盘时,就会发生这种情况。这听起来像是设计错误。当我编写ncurses应用程序时,通常只在数据输入的小字段中回响用户输入。其余的是屏幕上的菜单/键入键和导航,因为应用程序知道它们要去哪里,所以没有QUERY要求,它只是将光标设置到一个位置,在屏幕上绘制(或者如果屏幕出现问题,通过重新绘制,当用户进行CNTL-L)谢谢你David,这很明显…我觉得有点傻…我在stdin中留下了一个字符,所以查询的第一个响应就是这个字符…非常感谢你花时间解释我。