Многие Linux утилиты позволяют передавать имя файла для чтения в качестве первого аргумента или чтения из stdin
по умолчанию. Это позволяет вам читать из заданного имени файла или направлять или перенаправлять вывод из другого процесса в ваш код на stdin
. Чтобы реализовать альтернативу, вы можете воспользоваться тем, что stdin
имеет тип FILE*
, и просто проверить, был ли задан аргумент имени файла для чтения (и если да, открыть и прочитать из этого файла), или прочитать из stdin
с помощью по умолчанию.
Например:
#include <stdio.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold entire line (adjust MAXC as needed) */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line of input */
int a, b; /* example variables */
if (sscanf (buf, "%d %d", &a, &b) == 2) { /* parse/validate values */
/* do what you need with your values */
printf ("a: %d b: %d\n", a, b);
}
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
return 0;
}
Выше fgets()
используется, чтобы гарантировать, что полная строка на входе потребляется при каждом чтении, предотвращая сохранение непонятных символов на вашем входе поток, который вызовет сбой чтения (или бесконечный l oop) при следующей попытке чтения. Любые значения, необходимые из строки, анализируются с sscanf
. Это позволяет избежать большого количества ловушек, в которые попадают новые C программисты, пытаясь читать напрямую с scanf
или fscanf
, прежде чем понять, как обнаружить и правильно обработать соответствующий или вход сбои из-за несоответствия между спецификатором формата и вводом или исчерпанием ввода до того, как произойдут все указанные преобразования.
Примеры
Ввод трубопровода stdin
:
$ printf "1 2\n3 4\n" | ./bin/readfileorstdin
a: 1 b: 2
a: 3 b: 4
Пример входного файла
$ cat dat/2x2.txt
2 4
3 5
Обработка файла напрямую или stdin
Чтение файла напрямую:
$ ./bin/readfileorstdin dat/2x2.txt
a: 2 b: 4
a: 3 b: 5
Перенаправление на stdin
:
$ /bin/readfileorstdin < dat/2x2.txt
a: 2 b: 4
a: 3 b: 5
Вам не нужно делать это таким образом, вы можете просто читать из stdin
напрямую и избегайте проверки, было ли задано имя файла - но этот метод обеспечивает большое удобство и гибкость для обработки ввода всего за несколько дополнительных строк кода.