在 C 中预填充标准输入
pre-fill stdin in C
我的程序应该让用户编辑文件的一行。用户编辑该行并按回车键将其发回。因此我想打印即将被编辑的当前行,但是在标准输入而不是标准输出上打印它。
我不知道如何解决的唯一问题是如何预填充标准输入。我已经试过了:
char cprefill[] = {"You may edit this line"};
char cbuffer[100];
fprintf(stdin, cprefill);
fgets(cbuffer, 100, stdin);
这似乎是最简单的解决方案,但可能过于简单而无法工作。 fprintf 不会向标准输入输出任何内容。正确的做法是什么?
编辑:
这是它应该的样子。请注意可以移动的光标。
首先你需要 libreadline developer 包。 (如果 libreadline
在您的系统上尚不可用,您可能还需要它)
在 Debian/Ubuntu 上是 apt install libreadline-dev
(加上 libreadline6
如果您还需要二进制文件 - 6
在您的平台上可能不同)
然后你可以添加一个历史到readline
,像这样
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
...
char cprefill[] = {"You may edit this line"};
add_history(cprefill);
char *buf = readline("Line: ");
printf("Edited line is %s\n", buf);
// free the line allocated by readline
free(buf);
系统会提示用户 "Line: ",并且必须执行 向上箭头 以获取和编辑历史记录,即 cprefill
行。
请注意,您必须 compile/link 和 -lreadline
readline
打印作为参数给出的提示,然后等待用户交互,允许行编辑,以及加载历史记录中存储的行的箭头。
然后必须释放 readline
返回的 char *
(因为该函数使用 malloc()
分配缓冲区)。
C 语言没有终端和行版的概念,因此无法以可移植的方式完成。您可以依靠像 [n]curses 这样的库来获得几乎可移植的解决方案,或者如果您只需要在一个 OS 上使用低级 OS 原语。
例如 Windows,您可以在阅读之前通过模拟按键输入适当的 window(例如通过发送 WM_CHAR 消息)来提供输入缓冲区,但是将是高度不可移植的 - 最后不再是 C 而是 Windows 解决方案...
您可以使用 GNU Readline。它在开始时调用 rl_startup_hook
指向的函数,在这里我们使用 rl_insert_text
将我们的文本放入行缓冲区。
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
int prefill(void)
{
rl_insert_text("You may edit this line");
return 0;
}
int main(void)
{
char *cbuffer;
puts("Please edit the following line");
rl_startup_hook = prefill;
if ((cbuffer = readline(NULL)) == NULL) /* if the user sends EOF, readline will return NULL */
return 1;
printf("You entered: %s\n", cbuffer);
free(cbuffer);
return 0;
}
有关详细信息,请参阅 GNU Readline manual。
我的程序应该让用户编辑文件的一行。用户编辑该行并按回车键将其发回。因此我想打印即将被编辑的当前行,但是在标准输入而不是标准输出上打印它。 我不知道如何解决的唯一问题是如何预填充标准输入。我已经试过了:
char cprefill[] = {"You may edit this line"};
char cbuffer[100];
fprintf(stdin, cprefill);
fgets(cbuffer, 100, stdin);
这似乎是最简单的解决方案,但可能过于简单而无法工作。 fprintf 不会向标准输入输出任何内容。正确的做法是什么?
编辑:
这是它应该的样子。请注意可以移动的光标。
首先你需要 libreadline developer 包。 (如果 libreadline
在您的系统上尚不可用,您可能还需要它)
在 Debian/Ubuntu 上是 apt install libreadline-dev
(加上 libreadline6
如果您还需要二进制文件 - 6
在您的平台上可能不同)
然后你可以添加一个历史到readline
,像这样
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
...
char cprefill[] = {"You may edit this line"};
add_history(cprefill);
char *buf = readline("Line: ");
printf("Edited line is %s\n", buf);
// free the line allocated by readline
free(buf);
系统会提示用户 "Line: ",并且必须执行 向上箭头 以获取和编辑历史记录,即 cprefill
行。
请注意,您必须 compile/link 和 -lreadline
readline
打印作为参数给出的提示,然后等待用户交互,允许行编辑,以及加载历史记录中存储的行的箭头。
然后必须释放 readline
返回的 char *
(因为该函数使用 malloc()
分配缓冲区)。
C 语言没有终端和行版的概念,因此无法以可移植的方式完成。您可以依靠像 [n]curses 这样的库来获得几乎可移植的解决方案,或者如果您只需要在一个 OS 上使用低级 OS 原语。
例如 Windows,您可以在阅读之前通过模拟按键输入适当的 window(例如通过发送 WM_CHAR 消息)来提供输入缓冲区,但是将是高度不可移植的 - 最后不再是 C 而是 Windows 解决方案...
您可以使用 GNU Readline。它在开始时调用 rl_startup_hook
指向的函数,在这里我们使用 rl_insert_text
将我们的文本放入行缓冲区。
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
int prefill(void)
{
rl_insert_text("You may edit this line");
return 0;
}
int main(void)
{
char *cbuffer;
puts("Please edit the following line");
rl_startup_hook = prefill;
if ((cbuffer = readline(NULL)) == NULL) /* if the user sends EOF, readline will return NULL */
return 1;
printf("You entered: %s\n", cbuffer);
free(cbuffer);
return 0;
}
有关详细信息,请参阅 GNU Readline manual。