【发布时间】:2017-04-09 20:09:54
【问题描述】:
我正在 Linux 环境中使用几个二进制文件,并且正在尝试编写用户输入的脚本。例如,对于第一个程序 prog1.c:
void get_input() {
int i;
char buffer[32];
i = 0;
while (i < 3) {
memset(buffer, 0, 32);
printf("Enter input: ");
fgets(buffer, 31, stdin);
printf("Your input: %s\n", buffer);
i++;
}
}
我可以运行 prog1 并直接从控制台输入输入,也可以编写输入脚本并将其通过管道传输到程序中。
直接从控制台输入:
# ./prog1
Enter input: Stuff1
Your input: Stuff1
Enter input: Stuff2
Your input: Stuff2
Enter input: Stuff3
Your input: Stuff3
#
脚本输入:
# perl -e 'print "Stuff1\n" . "Stuff2\n" . "Stuff3\n"' | ./prog1
Enter input: Your input: Stuff1
Enter input: Your input: Stuff2
Enter input: Your input: Stuff3
#
虽然输出的格式有点乱,但程序还是显示了预期的输出。
我的问题在于第二个二进制 prog2.c:
void get_input() {
int i;
char buffer[32];
i = 0;
while (i < 3) {
memset(buffer, 0, 32);
printf("Enter input: ");
read(0, buffer, 31);
printf("Your input: %s\n", buffer);
i++;
}
}
当我可以直接从控制台输入我的输入时:
# ./prog2
Stuff1
Enter input: Your input: Stuff1
Stuff2
Enter input: Your input: Stuff2
Stuff3
Enter input: Your input: Stuff3
#
输入输入的提示不仅在我输入输入后才会显示,而且我什至无法编写输入脚本:
# perl -e 'print "Stuff1\n" . "Stuff2\n" . "Stuff3\n"' | ./prog2
Enter input: Your input: Stuff1
Stuff2
Stuff3
Enter input: Your input:
Enter input: Your input:
#
我对@987654327@和read()之间的区别做了一些研究,发现:
-
fgets()是 C 函数,而read()是系统调用。 -
fgets()读取输入,直到遇到换行符或 EOF,而换行对read()系统调用没有相同的效果。 -
read()采用了某种fgets()没有的缓冲机制。
我认为第 2 点和第 3 点与手头的问题最相关,但它们并没有提示我如何解决我的问题。
我需要给这些程序的用户输入涉及不可打印的十六进制字节,这就是为什么直接从控制台输入这样的输入是不够的。我也无法将源代码修改为二进制文件,因此没有解决方法只能使用fgets() 来收集输入。
我的问题是,是否有任何方法可以将输入输入 prog2,以便获得与 prog1 相同的行为。
谢谢。
【问题讨论】:
-
寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建最小、完整和可验证的示例。
-
函数:
fgets()足够聪明,可以停止输入字节,同时仍有一个“备用”字节可供该函数在输入末尾放置 NUL ('\0') 字节.因此,缓冲区长度参数应该是缓冲区的实际长度 -
问题完全变了。
-
由于上面的 Olaf 的 cmets,它已被更改。基本问题仍然存在。
标签: c system-calls buffering