|
|
Ввод и вывод
7.7. Обработка ошибок - STDERR и EXIT
Обработка ошибок в cat неидеальна. Неудобство заключается в том, что если один из файлов по некоторой причине оказывается недоступным, диагностическое сообщение об этом печатается в конце объединенного вывода. Это приемлемо, если вывод поступает на терминал, но не годится, если вывод поступает в некоторый файл или через поточный ( pipeline ) механизм в другую программу.
Чтобы лучше обрабатывать такую ситуацию, к программе точно таким же образом, как stdin и stdout, присоединяется второй выходной файл, называемый stderr. Если это вообще возможно, вывод, записанный в файле stderr, появляется на терминале пользователя, даже если стандартный вывод направляется в другое место.
Давайте переделаем программу cat таким образом, чтобы сообщения об ошибках писались в стандартный файл ошибок.
"include <stdio.h>
main(argc,argv) /*cat: concatenate files*/
int argc;
char *argv[];
{
file *fp, *fopen();
if(argc==1) /*no args; copy standard input*/
filecopy(stdin);
else
while (--argc > 0)
if((fp=fopen(*++argv,"r#))==null) {
fprintf(stderr,
"cat: can't open,%s\n", argv);
exit(1);
} else {
filecopy(fp);
}
exit(0);
}Программа сообщает об ошибках двумя способами. диагностическое сообщение, выдаваемое функцией printf, поступает в stderr и, таким образом, оказывается на терминале пользователя, а не исчезает в потоке ( pipeline ) или в выходном файле.
Программа также использует функцию exit из стандартной библиотеки, обращение к которой вызывает завершение выполнения программы. Аргумент функции exit доступен любой программе, обращающейся к данной функции, так что успешное или неудачное завершение данной программы может быть проверено другой программой, использующей эту в качестве подзадачи. По соглашению величина 0 в качестве возвращаемого значения свидетельствует о том, что все в порядке, а различные ненулевые значения являются признаками ненормальных ситуаций.
функция exit вызывает функцию fclose для каждого открытого выходного файла, с тем чтобы вывести всю помещенную в буферы выходную информацию, а затем вызывает функцию _exit. функция _exit приводит к немедленному завершению без очистки каких-либо буферов; конечно, при желании к этой функции можно обратиться непосредственно.
7.8. Ввод и вывод строк
Стандартная библиотека содержит функцию fgets, совершенно аналогичную функции getline, которую мы использовали на всем протяжении книги. В результате обращения
fgets(line, maxline, fp)
следующая строка ввода (включая символ новой строки ) считывается из файла fp в символьный массив line ; самое большое maxline-1 символ будет прочитан. Результирующая строка заканчивается символом \0. Нормально функция fgets возвращает line ; в конце файла она возвращает null. (Наша функция getline возвращает длину строки, а при выходе на конец файла - нуль).
Предназначенная для вывода функция fputs записывает строку (которая не обязана содержать символ новой строки ) в файл:
fputs(line, fp)
Чтобы показать, что в функциях типа fgets и fputs нет ничего таинственного, мы приводим их ниже, скопированными непосредственно из стандартной библиотеки ввода-вывода:
#include <stdio.h>
char *fgets(s,n,iop) /*get at most n chars from iop*/
char *s;
int n;
register file *iop;
{
register int c;
register char *cs;
cs = s;
while(--n>0&&(c=getc(iop)) !=EOF)
if ((*cs++ = c)=='\n')
break;
*cs = '\0';
return((c==EOF && cs==s) ? null : s);
}
fputs(s,iop) /*put string s on fils iop*/
register char *s;
register file *iop;
{
register int c;
while (c = *s++)
putc(c,iop);
}Упражнение 7-3
Напишите программу сравнения двух файлов, которая будет печатать первую строку и позицию символа, где они различаются.
Упражнение 7-4
Переделайте программу поиска заданной комбинации символов из "лекции №5" таким образом, чтобы в качестве ввода использовался набор именованных файлов или, если никакие файлы не указаны как аргументы, стандартный ввод. Следует ли печатать имя файла при нахождении подходящей строки?
Упражнение 7-5
Напишите программу печати набора файлов, которая начинает каждый новый файл с новой страницы и печатает для каждого файла заголовок и счетчик текущих страниц.
