无法读取 C 语言中标准/STDIN_FILENO 的输入?



我有这个命令行参数 -

cat file_name | ./a.out 

问题不在于从 C 程序中的 cat 命令读取,因为我们可以使用read()fgets()fgetc()来做到这一点,但我面临的实际问题是在从cat读取数据后,我无法使用fgets从用户那里获取输入。

这是我的示例代码

while(fgets(buffer, BUFSIZ, stdin ) != NULL )
puts( buffer ); // Here I have tried strtok( buffer, "n" ) too.
memset( buffer, 0, BUFSIZ );`

问题是在这一行之后,它没有像下面这样要求输入不起作用-

puts("Name: ");
fgets( buffer, BUFSIZ, stdin );

帮我解决这里发生了什么问题?

当你这样做cat file_name | ./a.out程序的标准输入被绑定到一个管道,将其连接到cat的输出。您的程序将永远无法看到用户输入 - 它到达的流已被上述管道替换。

请注意,我怀疑通过一些可怕的POSIX特定技巧,您可以直接为tty设备重新打开它,但这只是糟糕的设计。如果您需要从文件中读取接受交互式用户输入,只需接受文件作为命令行参数并使用 stdin 与用户交互。

编辑

这是可以尝试的Unix特定kludges的一个例子,假设进程仍然有一个控制终端。阅读完所有原始标准后,我打开/dev/tty(这是进程的控制终端(并重新链接到stdin它。

免责声明:这仅用于娱乐目的,不要真的这样做

#include <stdio.h>
#include <stdlib.h>
void die(const char *msg) {
fprintf(stderr, "%sn", msg);
fputs(msg, stderr);
exit(1);
}
int main() {
/* Read all of stdin and count the bytes read (just to do something with it) */
int ch;
unsigned long count = 0;
while((ch = getchar())!=EOF) {
count++;
}
printf("Read %lu bytes from stdinn", count);
/* Open the controlling terminal and re-link it to the relevant C library FILE *
* Notice that the UNIX fd for stdin is still the old one (it's
* surprisingly complex to "reset" stdio stdin to a new UNIX fd) */
if(freopen("/dev/tty", "r", stdin) == NULL) {
die("Failed freopen");
}
/* Do something with this newly gained console */
puts("How old are you?");
fflush(stdout);
int age = -1;
if(scanf("%d", &age)!=1) {
die("Bad input");
}
printf("You are %d years oldn", age);
return 0;
}

(以前我有一个解决方案,可以检查stderrstdout是否仍然是控制台,这更是一个难题;感谢@rici提醒我POSIX具有"控制终端"的概念,可以通过/dev/tty访问(

如果需要使用stdin进行用户交互,则需要使用不同的文件描述符来读取输入流。

您可以使用特定的预打开文件描述符和文档(例如,">输入流应连接到 fd 3"(,但通常的方法是接受文件名作为命令行参数。 然后,可以提供命名管道作为参数;像 Bash 这样的 shell 提供了过程替换,使这变得容易:

./a.out <(cat file_name)

当它像这样交互式运行时,stdin 仍然连接到终端,并且可以与来自连接命令的流同时使用。

(显然,如果命令实际上使用单个参数cat,那么您只需提供文件名本身作为参数,但我假设这是一个涉及更多管道的占位符(。

最新更新