通过管道输入文件在 C 中专门使用标准输入

Using stdin in C exclusively through a piped in file

我为一个项目编写了一个文件解析器,用于解析命令行上提供的文件。

但是,我想允许用户也通过标准输入输入他们的输入,但是只能通过命令行重定向。

使用基于 Linux 的命令提示符,以下命令 应该会产生相同的结果

  1. ./check infile.txt(通过命令行输入文件名)
  2. ./check < infile.txt
  3. cat infile.txt | ./check

可执行文件应接受文件名作为第一个也是唯一的命令行参数。如果没有指定文件名,它应该从标准输入读取。

编辑:我意识到它真的很简单,并发布了一个答案。我会把它留给其他在某些时候可能需要它的人。

我想我的大脑被炸了,因为这是一个非常基本的问题,我在发布它后立即意识到了这一点。我会把它留给可能需要它的其他人。

答案:

您可以从标准输入 fgets,然后检查文件的结尾您仍然可以使用 feof 作为标准输入:

while(!feof(stdin))

这非常接近 "Please write my program for me"。或者它甚至可能越过了那条线。不过,这是一个非常简单的程序。

我们假设您有一个解析器,它接受一个 FILE* 参数并解析该文件。 (如果您编写了一个采用 const char* 文件名的解析函数,那么这是为了解释为什么这是一个坏主意。函数应该只做一件事,而 "open a file and then parse it" 是两件事。一旦你写了一个函数来做两件不相关的事情,你会立即遇到你真的只想做其中一件的情况(比如只解析一个流而不打开文件。)

所以我们还剩下:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "myparser.h"
/* Assume that myparser.h includes
 *    int parseFile(FILE* input);
 * which returns non-zero on failure.
 */

int main(int argc, char* argv[]) {
  FILE* input = stdin;  /* If nothing changes, this is what we parse */
  if (argc > 1) {
    if (argc > 2) {
      /* Too many arguments */
      fprintf(stderr, "Usage: %s [FILE]\n", argv[0]);
      exit(1);
    }
    /* The convention is that using `-` as a filename is the same as
     * specifying stdin. Just in case it matters, follow the convention.
     */
    if (strcmp(argv[1], "-") != 0) {
      /* It's not -. Try to open the named file. */
      input = fopen(argv[1], "r");
      if (input == NULL) {
        fprintf(stderr, "Could not open '%s': %s\n", argv[1], strerror(errno));
        exit(1);
      }
    }
  }

  return parse(input);
}

最好将上述大部分内容打包成一个函数,该函数接受一个文件名和 returns 一个打开的 FILE*.