我也读过以前关于这个问题的问题。 fflush(stdin) 在这种情况下对我来说不起作用。 我希望我的程序从管道 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 2n");
printf("3. Exitn");
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 optionn");
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 程序工作正常时。 我想不通解决这个问题的方法,有人有想法吗..
管道(由shell控制)通常出现在文件描述符0
上,这是标准输入。 您可以使用dup2()
将其"移动"到其他文件描述符,并使用freopen()
继续从中读取。 您还可以打开/dev/tty
设备(或tty
程序知道的任何内容)并将其作为标准输入。
对话框程序对--gauge
(进度条)选项执行此操作。 它这样做的原因是对话框是一个curses应用程序(默认情况下使用标准输入和输出)。 实际的管道文件描述符也是可选的,因此引用其手册页给出了一些提示:
输入-FDFD
从给定的文件描述符读取键盘输入。 大多数对话框脚本从标准输入读取,但仪表小组件读取 管道(始终是标准输入)。 某些配置可以 对话框尝试重新打开终端时无法正常工作。 用 此选项(适当处理文件描述符)如果 脚本必须在该类型的环境中工作。
实现这一点的逻辑在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);
}
我编写的程序几乎相同,该程序用于从stdin
读取二进制数据(从其他程序的stdout
管道传入),但我想添加键盘命令(通过原始终端支持)。 显然,同时读取管道数据和键盘会导致一些奇怪的结果。
这是我的代码,工作和测试:
文件 * fp; 国际 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)
。
如果希望程序接受键盘输入,请不要重定向其标准输入。 如果重定向程序的标准输入,请不要期望能够通过键盘向其提供数据。
如果程序需要同时接受来自文件和键盘的输入,则为其提供文件名作为参数,并让它打开并读取该文件。
如果您必须处理某种不可修改的库函数,该函数需要通过stdin
提供输入,并且您希望该输入来自文件,并且您希望其他地方接受键盘输入,那么您可以使用dup2()
ing 文件描述符玩游戏以使其正常工作。 一旦你让它工作,考虑解雇负责该库函数的白痴。