我想在我的C程序中读取箭头按键,并用其他字符串替换它们(立即在终端本身中)。我正在尝试在UNIX终端中实现bash历史记录功能。我写了这段代码。
int
main(int argc, char *argv[])
{
char c;
char str[1024];
int i = 0;
while((c = fgetc(stdin)) != '\n'){
if(((int)c) == 27){
c=fgetc(stdin);
c=fgetc(stdin);
if (c == 'A')
{
printf("%c[A%c[2K",27, 27);
printf("UP");
}
}
str[i++] = c;
}
printf("\n");
return 0;
}
但是,这不起作用,因为终端等待换行符或EOF将输入缓冲区发送到stdin。因此,我必须按Enter / Return键来分析用户输入。
用户在此回答中提到要使用,system("/bin/stty raw");
但这将替换所有默认的终端行为(例如,退格键,删除等)。
因此,如果检测到箭头按键,有什么办法可以直接读取/操作终端输入缓冲区并调整缓冲区本身?
环境-Ubuntu(Linux)
更新1: 是否有一种方法可以改变信号/中断(默认是按Enter键),从而使终端将存储的输入发送到缓冲区?这也可以帮助我实现相同的行为。
最终代码:
我通过检查的输出发现了特定按键的ASCII字符 strace bash
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define ESCAPE '\33'
#define BACKSPACE '\177'
#define DELETE '~'
int main(){
struct termios termios_p;
struct termios termios_save;
tcgetattr(0, &termios_p);
termios_save = termios_p;
termios_p.c_lflag &= ~(ICANON|ECHO);
tcsetattr(0,TCSANOW, &termios_p);
char buff;
while(read(0, &buff, 1) >= 0){
if(buff > 0){
if(buff == ESCAPE){
read(0, &buff, 1);
read(0, &buff, 1);
if(buff == 'A'){
write(2, "up", 2);
}else if(buff == 'B'){
write(2, "down", 4);
}else if(buff == 'C'){
write(2, "\33[C", 3);
}else if(buff == 'D'){
write(2, "\10", 2);
}
}else if(buff == BACKSPACE){
write(2, "\10\33[1P", 5);
}else if(buff == DELETE){
write(2, "\33[1P", 4);
}else{
write(2,&buff,1);
}
// write(2,&buff,1);
if(buff == 'q'){
break;
}
}
}
tcsetattr(0,TCSANOW, &termios_save);
return 0;
}
看来您正在寻找这样的东西。
该程序实际上等待用户输入。如果按下向上箭头键,程序将打印“按下箭头键”,然后退出。如果按下了其他任何按钮,它将等待用户完成键入的内容并打印出来,然后退出。
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
struct termios oldt, newt;
char ch, command[20];
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
while(1)
{
ch = getchar();
if (ch == '\033')
{ printf("Arrow key\n"); ch=-1; break;}
else if(ch == -1) // by default the function returns -1, as it is non blocking
{
continue;
}
else
{
break;
}
}
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch,stdin);ith
putchar(ch);
scanf("%s",command);
printf("\n%s\n",command);
return 1;
}
return 0;
}
问题内容: 我写了一个非常简单的函数,可以从给定的URL下载图像,调整图像大小并上传到S3(使用’gm’和’knox’),我不知道我是否在正确地将流读取到缓冲区中。(一切正常,但这是正确的方法吗?) 另外,我想了解一些有关事件循环的知识,如何知道该函数的一次调用不会泄漏任何内容,也不会将’buf’变量更改为另一个已经运行的调用(否则这种情况是不可能的,因为回调是匿名的功能?) 问题答案: 总的来说
问题内容: 我有一个Java程序,它将一些文本输出到控制台。它使用,和其他一些方法来执行此操作。 在程序的最后,我想读取控制台中的所有文本并将其复制到String缓冲区中。我该如何用Java做到这一点?我需要阅读和独立。 问题答案: 好的,这是一个有趣的问题。似乎不是一种同时解决所有方法的优雅方法。(不幸的是没有。) 我确实写了一个丑陋的基于反射的解决方法(我想不要在生产代码中使用它:) …可以像
如何更改仍为3M的缓冲区 当前启动命令: ffmpeg-f dshow-i video=“屏幕捕获录像机”-vcodec libx264-预设:v ultrafast-过滤器:v“crop=480:270:0:0”-vf tpad=start_duration=30-r 30-g 60-keyint_min 60-sc_阈值0-b:v 1G-最大速率2500k-bufsize 1G-rtbufsi
本文向大家介绍Java缓冲读取器,包括了Java缓冲读取器的使用技巧和注意事项,需要的朋友参考一下 示例 介绍 该BufferedReader班是以外的包装Reader是有两个主要目的类: ABufferedReader为包装的提供缓冲Reader。这允许应用程序一次读取一个字符,而不会产生过多的I / O开销。 一个BufferedReader用于一次读取文本行提供的功能。 使用Buffered
我想在JAVA程序中执行一个EXE文件。 它工作正常,但我希望EXE的输出立即在我的JAVA程序的文本区域中。 目前,我在“ping”命令完全完成后得到输出(因此JAVA程序挂起了大约3秒)。但是我想马上有结果... 我做错了什么? 突击队向后。 好吧,我想使用这个程序:https://iperf.fr/iperf-download.php 输出如下所示: 不过,我只有在iperf运行后才能得到这
问题内容: 为了寻求帮助,我目前已编写了HTTP服务器。目前,它可以很好地处理GET请求。但是,在使用POST时,缓冲的读取器似乎挂起。当请求停止时,其余输入流将通过缓冲的读取器读取。我在Google上找到了一些东西。我尝试将CRLF和协议版本从1.1更改为1.0(浏览器会自动将请求发送为1.1),任何想法或帮助将不胜感激。谢谢 问题答案: 这不安全!但是显示了如何在初始HTTP标头之后的输入流中