【问题标题】:There's something from stdin or not?有没有来自标准输入的东西?
【发布时间】:2014-02-07 11:19:34
【问题描述】:

可以编写一个识别文件是否被传递的代码,如下所示:

program.out < file.dat

我为此寻找答案,因为我想编写代码来做这样的事情:

int main (int argc, char *argv[])
{
    char filename[50];

    if ( argc > 1 )
    {
        strcpy (filename, argv[1]);
    }

    else if ( SOMETHING )
    {
        /* copy the stdin into fin (?) */
    }

    FILE *fin;

    fin = fopen (filename, "r");

    /* ... */

    fclose(fin);

    }

    return 0;
}

如果文件以&lt; 传递,则SOMETHING 的计算结果为1,否则为0。

如果可能,我正在寻找使用标准 C 的解决方案。

【问题讨论】:

  • 通常的约定是用户将文件名作为参数传递,如果他们不提供从标准输入读取的文件名参数。你为什么违反这个?
  • @Barmar。我没有违反这一点,我是在问我应该怎么做才能做到你所说的!仅当 “他们不提供文件名参数” 时,我如何才能从标准输入读取?
  • 不,你正在做相反的事情。如果他们不重定向输入,您正在从硬编码的文件名中读取。
  • 现在我已经编辑了代码。

标签: c file stdin argv argc


【解决方案1】:

我们无法在 ISO C 中检测到这一点(也就是说,不借助平台扩展,例如在 POSIX 上使用 fileno 获取文件描述符,然后通过使用 fstat 获取属性对其运行一些测试等等。)

如果stdin 流连接到交互式设备,则 ISO C 要求它进行行缓冲。然而,这对我们没有帮助,因为没有可移植的函数来查询FILE * 的缓冲模式:只有“setter”,没有“getter”。 GNU C 库有一个 __flbf (FILE *stream) 报告流是否是行缓冲的,但它是一个明显的扩展,在 &lt;stdio_ext.h&gt; 标头中声明。

如果您的程序必须使用文件,而不是来自交互式设备的标准输入,那么一个好的解决方案是强制程序的参数。使其需要文件名参数并始终打开该文件。然后你确定你有这个文件。

您也可以将参数设为可选,如果缺少,则打开默认文件,忽略 stdin

您也可以使用freopen 使stdin 指向一个文件。然后隐式使用stdin 的代码将从该文件中获取输入:

伪代码:

name = "some default"

if we have an argument
  name = that argument

if (freopen(name, mode, stdin) == 0)
   handle error
else
   stdin is now a file; process it

如果您确实必须支持program &lt; file 情况,同时将program 情况(交互式输入)标记为无效,则需要上述特定于平台的技巧。

【讨论】:

    【解决方案2】:

    如果您对特定于 Unix 的解决方案感到满意,可以使用 isatty():

    FILE *fin;
    int need_to_close;
    
    if (isatty(fileno(STDIN))) { // I/O not redirected
        fin = fopen("file.dat", "r");
        need_to_close = 1;
    } else {
        fin = stdin;
        need_to_close = 0;
    }
    
    /* ... */
    
    if (need_to_close) {
        fclose(fin);
    }
    

    【讨论】:

      【解决方案3】:

      可能是this answer 可以帮助: 它说,

      在 Posix 系统上,您可以测试 cin 是否来自 终端或使用isatty重定向

      #include <unistd.h>
      
      if (isatty(STDIN_FILENO)) {
          // not redirected
      } else {
          // redirected
      }
      

      【讨论】:

        猜你喜欢
        • 2020-02-04
        • 1970-01-01
        • 2014-06-19
        • 1970-01-01
        • 2021-11-10
        • 2021-01-16
        • 2023-03-07
        • 2016-04-02
        • 2023-04-05
        相关资源
        最近更新 更多