Обработка ошибок - 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 приводит к немедленному завершению без очистки каких-либо буферов; конечно, при желании к этой функции можно обратиться непосредственно.