unix:main() interactive, Command line, pipeping & redirection in C?



虽然有一种简单的方法可以同时使用文件重定向管道,以及使用main()进行交互式用户输入读取,如此C代码片段所示。。。

#define  SIZ 1024
#include <stdio.h>
extern void do_something_with_the_array(float *a[], int *n);
int main(int argc, const char * argv[])
{
    float f[SIZ];
    int k = 0;
    while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) {
      k++;
    }
    do_something_with_the_array(f, k);
    return 0;
}

…我不确定是否有一种现代的UNIX源代码兼容且简单的方法可以在C中的main()中以编程方式实现这三种可能性中的任何一种,具体取决于上下文?

  • 交互式读取一串数字作为用户输入
  • 读取与命令行参数相同的数字字符串
  • 文件重定向和管道

我知道管道和重定向"属于"在程序开始执行之前拦截程序的shell,而命令行参数和交互式读取"属于"main()本身,因此可能没有简单的方法来做到这一点。

我认为使用stdinfile输入或管道的输入非常不言自明。然而,读取命令行参数是另一回事。这是一个我通常如何编码的演示,但对我来说,它看起来有点严厉和被黑客入侵。此外,在有选项的更复杂的场景中,这可能会成为一段相当混乱的代码。我也不确定这是如何防故障或防傻瓜的…

#define  SIZ 1024
#include <stdio.h>
#include <stdlib.h>
extern void do_something_with_the_array(float *, int);
int main(int argc, const char * argv[])
{
    float f[SIZ];
    int k = 0;
    if(argc > 2){
        for(k = 0; k < argc - 1; k++) 
            f[k] = (float)atof(argv[k+1]);
    }
    else while ((scanf("%f", &f[k]) == 1)&&(k < SIZ))
        k++;
    do_something_with_the_array(f, k);
    return 0;
}

提前感谢!

我不知道有什么C库会让你提到的三个特定案例看起来相同(尽管有人知道,但请回答,因为我也想知道!)。我认为您正在寻找与Perl中的菱形<>运算符没有什么不同的东西,而是针对单个参数,而不是包含参数的文件。

我认为@David Hoelzer的想法是正确的:分别处理这三个案件。例如,在处理命令行或文件参数时,不要生成可能打印用于交互式输入的"输入值"提示。对于命令行处理,getopt是一个很好的起点。

现在,你面临的一个挑战是:将这三项操作打包到一个库中,并使其开源,这样我们其他人都可以从中受益!:)

相当多的程序关心它们是用键盘输入还是用文件输入调用,包括shell本身。

让我们以/bin/sh作为我们的第一个例子。如果你直接调用它,它会启动一个交互式shell,但如果你把一些东西导入其中,它会以非交互式阅读shell的形式启动。两者之间的主要区别在于,如果它不是交互式的,它就不会显示$提示。然而,如果它真的是交互式的,可以用-i选项启动它,使它在正常情况下做出其他决定时假设它是交互式的。

这里涉及的魔法是isatty();参见man 3 isatty

此外,一些程序喜欢在处理重定向的标准输入时接收键盘输入。有两种普遍受欢迎的方法可以做到这一点;根据上下文打开和读取/dev/tty或读取标准错误。交互式启动的管道中的大多数内容都没有重定向标准错误,因此这通常会很好地工作(读取重定向的标准错误会立即产生错误,因为句柄没有打开以供读取)。如果你想让它潜在地完全自动化,你可以阅读标准错误,否则你可以阅读/dev/tty

最新更新