При запуске Си-программы операционная система всегда открывает три файла и обеспечивает три файловые ссылки на них. Этими файлами являются: стандартный ввод, стандартный вывод и стандартный файл ошибок; соответствующие им указатели называются stdin, stdout и stderr; они описаны в <stdio.h>. Обычно stdin соотнесен с клавиатурой, а stdout и stderr - с экраном. Однако stdin и stdout можно связать с файлами или, используя конвейерный механизм, соединить напрямую с другими программами, как это описывалось в параграфе 7.1.
С помощью getc, putc, stdin и stdout функции getchar и putchar теперь можно определить следующим образом:
#define getchar() getc(stdin) #define putchar(c) putc((c), stdout)
Форматный ввод-вывод файлов можно построить на функциях fscanf и fprintf. Они идентичны scanf и printf с той лишь разницей, что первым их аргументом является указатель на файл, для которого осуществляется ввод-вывод, формат же указывается вторым аргументом.
int fscanf(FILE *fp, char *format, ...) int fprintf(FILE *fp, char *format, ...)
Вот теперь мы располагаем теми сведениями, которые достаточны для написания программы cat, предназначенной для конкатенации (последовательного соединения) файлов. Предлагаемая версия функции cat, как оказалось, удобна для многих программ. Если в командной строке присутствуют аргументы, они рассматриваются как имена последовательно обрабатываемых файлов. Если аргументов нет, то обработке подвергается стандартный ввод.
#include <stdio.h> /* cat: конкатенация файлов, версия 1 */ main(int argc, char *argv[]) { FILE *fp; void filecopy(FILE *, FILE *);
if (argc == 1) /* нет аргументов; копируется стандартный ввод */ filecopy(stdin, stdout); else while (--argc > 0) if ((fp = fopen(*++argv, "r")) == NULL) { printf("cat: не могу открыть файл %s\n", *argv); return 1; } else { filecopy(fp, stdout); fclose(fp); } return 0; }
/* filecopy: копирует файл ifp в файл ofp */ void filecopy(FILE *ifp, FILE *ofp) { int c; while ((c = getc(ifp)) != EOF) putc(c, ofp); }