【问题标题】:unix: main() interactive, command line, piping & redirection in C?unix:C 中的 main() 交互式、命令行、管道和重定向?
【发布时间】:2016-08-11 22:04:50
【问题描述】:

虽然使用 文件重定向管道 以及交互式用户输入读取有一种简单的方法,但 main(),如这段C代码sn-p...

#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 源代码兼容且简单的方法来以编程方式实现 Cmain() 中的三种可能性中的任何一种,具体取决于上下文? p>

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

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

我看到使用 stdinfile 输入或 pipe 输入非常不言自明。但是,读取命令行参数是另一回事。这是我通常如何编码的演示,但它看起来有点笨拙并且对我来说是黑客攻击。此外,在带有选项的更复杂的场景中,这可能会变成一段非常混乱的代码。我也不确定这是多么安全或万无一失......

#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;
}

提前致谢!

【问题讨论】:

  • 您发布的片段可能会溢出。
  • 为什么这些事情不可能?只需编写 switch 语句来处理这三个条件。
  • 程序通常不知道stdin是指终端控制台、文件、套接字还是您能想到的任何其他流。
  • 请问有人能解释一下问这个问题有什么问题吗?
  • @user3078414:代码的sn-p只使用stdin。它没有说明您还期望做什么,问题的其余部分也没有说明。

标签: c unix command-line


【解决方案1】:

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

让我们以 /bin/sh 作为我们的第一个例子。如果您直接调用它,它会启动一个交互式 shell,但如果您将某些内容输入其中,它将作为一个非交互式读取 shell 启动。两者的主要区别在于,如果它不是交互式的,则不会显示 $ 提示符。但是,如果它真的是交互式的,可以使用 -i 选项启动它,以使其在通常决定其他情况时假定它是交互式的。

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

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

【讨论】:

  • 感谢您的宝贵意见。我也“在这条路上”。目前,我正在研究所有情况下的信号处理,因为我编写的一些符合此要求的程序也会进行一些非常密集的数字运算并具有实时优先级线程。
【解决方案2】:

我不知道 C 库的副手会让您提到的三个特定案例看起来相同(尽管有人这样做,请回答,因为我也想知道!)。我认为您正在寻找与 the diamond &lt;&gt; operator in Perl 不同的东西,而是寻找单个参数而不是包含参数的文件。

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

现在,对您的挑战是:将这三个操作封装在一个库中并使其开源,以便我们其他人受益! :)

【讨论】:

  • 感谢@cxw。我知道getopt() 曾经是 gnu-C 的一部分。我已经检查过了,它也是 NetBSD (Darwin, OSX) 的一部分。一些测试给出了有希望的结果。我接受这个答案,因为它最有助于找到我的问题的解决方案。如果我有机会成功编写一个提议的库,我一定会开源发布它!
  • @user3078414 非常感谢,祝你好运!如果你想到它,一旦你发布,用链接评论回来,我会检查出来:)。
猜你喜欢
  • 2013-09-19
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 1970-01-01
  • 2015-12-25
  • 1970-01-01
  • 2014-12-11
相关资源
最近更新 更多