2

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

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

其中SOMETHING,如果文件是用 传递的<,则计算为 1,否则计算为 0。

如果可能的话,我正在寻找一个在标准 C 中工作的解决方案。

4

3 回答 3

3

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

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

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

您还可以将参数设为可选,如果缺少,则打开默认文件,忽略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 < file情况,同时将情况(交互式输入)标记program为无效,则需要上述特定于平台的技巧。

于 2014-01-17T23:07:06.130 回答
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);
}
于 2014-01-17T23:09:00.673 回答
0

可能这个答案会有所帮助:它说,

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

#include <unistd.h>

if (isatty(STDIN_FILENO)) {
    // not redirected
} else {
    // redirected
}
于 2014-01-17T23:10:08.487 回答