我也已经阅读过有关此问题的先前问题。 fflush(stdin)对我来说在这种情况下不起作用。 我希望我的程序从管道标准输入读取,并从中间的键盘输入继续。
int main()
{
int userin = 3;
read_input();
userin = print_menu();
userin = parse_input(userin);
return 0;
}
我想从文件中读取数据,该文件作为像
这样的pipied stding传递给程序int read_input(){
char line[200];
char word[MAX_STRING+1];
int line_number = 0;
while(fgets(line, sizeof(line), stdin) != NULL ){
//do something
printf("%s",line);
line_number++;
}
}
现在read_input必须从管道输入完成读取。 ' print_menu'必须继续从键盘上读取。
int print_menu()
{
int userinput;
char c;
char num[4];
while((c=getchar()) != '\n' && c != EOF && c != '\r');
printf("\n1. Choice 1 \n");
printf("2. Choice 2\n");
printf("3. Exit\n");
printf("Enter your choice (1-3): ");
/* scanf("%d", &userinput); */
/* fgets(num,80,stdin); */
scanf("%s", num);
userinput = atoi(num);
return userinput;
}
int parse_input(int userinput)
{
char num[4];
while( userinput > 3 || userinput < 1 ){
printf("Sorry, that is not a valid option\n");
printf("Enter your choice (1-3): ");
scanf("%s", num);
userinput = atoi(num);
/* scanf("%d", &userinput); */
/* while( (c = getchar()) == '\n'); */
}
return userinput;
}
我的输出是
的无限循环Enter your choice (1-3): Sorry, that is not a valid option
当我删除read_input方法和管道stdin程序工作正常。 我无法弄清楚这个,有人有想法......
答案 0 :(得分:3)
管道(通常由shell控制)通常在文件描述符0
上,这是标准输入。您可以使用dup2()
来&#34;移动&#34;对于不同的文件描述符,并使用freopen()
继续读取它。您也可以打开/dev/tty
设备(或tty
程序知道的任何设备),然后 您的标准输入。
dialog程序为--gauge
(进度条)选项执行此操作。它之所以这样做是因为对话框是curses应用程序(默认情况下使用标准输入和输出)。实际的管道文件描述符也是可选的,因此从manual page引用会给出一些提示:
- input-fd fd
从给定文件描述符中读取键盘输入。大多数对话框 脚本从标准输入读取,但仪表小部件读取 管道(始终是标准输入)。有些配置可以 对话框尝试重新打开终端时无法正常工作。使用 这个选项(有适当的文件描述符杂耍)if 您的脚本必须在这种类型的环境中工作。
实现此目的的逻辑位于util.c
,来自init_dialog
函数。以下是其中的主要部分,以了解如何使用这些函数:
dialog_state.pipe_input = stdin;
if (fileno(input) != fileno(stdin)) {
if ((fd1 = dup(fileno(input))) >= 0
&& (fd2 = dup(fileno(stdin))) >= 0) {
(void) dup2(fileno(input), fileno(stdin));
dialog_state.pipe_input = fdopen(fd2, "r");
if (fileno(stdin) != 0) /* some functions may read fd #0 */
(void) dup2(fileno(stdin), 0);
} else {
dlg_exiterr("cannot open tty-input");
}
close(fd1);
} else if (!isatty(fileno(stdin))) {
if ((fd1 = open_terminal(&device, O_RDONLY)) >= 0) {
if ((fd2 = dup(fileno(stdin))) >= 0) {
dialog_state.pipe_input = fdopen(fd2, "r");
if (freopen(device, "r", stdin) == 0)
dlg_exiterr("cannot open tty-input");
if (fileno(stdin) != 0) /* some functions may read fd #0 */
(void) dup2(fileno(stdin), 0);
}
close(fd1);
}
free(device);
}
答案 1 :(得分:1)
如果您希望程序接受键盘输入,请不要重定向其标准输入。如果您重定向程序的标准输入,请不要期望能够通过键盘提供数据。
如果你的程序需要接受来自文件和键盘的输入,那么给它作为参数的文件名,让它打开并读取该文件。
如果你必须处理需要通过stdin
,和提供输入的某种不可修改的库函数,你希望输入来自一个文件,和你想在其他地方接受键盘输入,然后你可以用dup2()
文件描述符来玩游戏,让它运行起来。一旦你开始工作,考虑解雇负责该库功能的白痴。
答案 2 :(得分:1)
我写的一个程序与stdin
读取二进制数据(从其他程序的stdout
管道输入)的情况几乎相同,但是我想添加键盘命令(通过{{ 3}})。显然,同时阅读管道数据和键盘会导致一些奇怪的结果。
这是我的代码,工作和测试:
FILE * fp; int fd; fd = dup(fileno(stdin)); fp = fdopen(fd, "r"); (void) freopen("/dev/tty", "r", stdin);
现在,我的程序从fp(一个FILE*
对象)读取其二进制数据,同时读取stdin
(现在与"/dev/tty"
关联)以进行击键。
请注意,我会从freopen
(FILE*
对象)中丢弃返回值,因为如果需要,我可以通过stdin
引用它。我的经验是,无需close()
或fclose()
标准文本流。我在阅读二进制数据结束时fclose(fp)
。