netlib.narod.ru< Назад | Оглавление | Далее >

7.6. Управление ошибками (stderr и exit)

Обработку ошибок в программе cat нельзя признать идеальной. Беда в том, что если файл по какой-либо причине недоступен, сообщение об этом мы получим вместе с выходными данными программы. Это нас устроило бы, если бы вывод отправлялся только на экран, а не в файл или по конвейеру другой программе.

Чтобы лучше справиться с этой проблемой, программе помимо стандартного вывода stdout дается еще один выходной поток, называемый stderr. Данные, выводимые в stderr обычно отправляются на экран, даже если вывод stdout перенаправлен в другое место.

Перепишем программу cat так, чтобы сообщения об ошибках отправлялись в stderr.

  #include <stdio.h>

  /* cat: конкатенация файлов, версия 2 */
  main(int argc, char *argv[])
  {
      FILE *fp;
      void filecopy(FILE *, FILE *);
      char *prog = argv[0]; /* имя программы */

      if (argc == 1)  /* нет аргументов, копируем стандартный ввод */
          filecopy(stdin, stdout);
      else
          while (--argc > 0)
              if ((fp = fopen(*++argv, "r")) == NULL) {
                  fprintf(stderr, "%s: не могу открыть файл %s\n",
                          prog, argv);
                  exit(1);
              } else {
                  filecopy(fp, stdout);
                  fclose(fp);
               }
      if (ferror(stdout)) {
          fprintf(stderr, "%s: ошибка записи в stdout\n", prog);
          exit(2);
      }
      exit (0);
  }

Программа сигнализирует об ошибках двумя способами. Первый — сообщение об ошибке с помощью fprintf посылается в stderr, чтобы оно попало на экран, а не оказалось на конвейере или в другом файле вывода. Имя программы, хранящееся в argv[0], мы включили в сообщение, чтобы в случаях, когда данная программа работает совместно с другими, был ясен источник ошибки.

Второй способ указать на ошибку — обратиться к библиотечной функции exit, завершающей работу программы. Аргумент функции exit доступен некоторому процессу, вызвавшему данный процесс. Следовательно, успешное или ошибочное завершение программы можно проконтролировать с помощью некоей программы, которая рассматривает эту программу в качестве подчиненного процесса. По общей договоренности возврат нуля сигнализирует о том, что работа прошла нормально, в то время как ненулевые значения обычно говорят об ошибках. Чтобы опорожнить буфера, накопившие информацию, для всех открытых файлов вывода функция exit вызывает fclose.

Инструкция return выражение в главной функции main эквивалентна обращению к функции exit (выражение). Последний вариант (с помощью exit) имеет то преимущество, что он пригоден для выхода и из других функций, и, кроме того, слово exit легко обнаружить с помощью программы контекстного поиска, похожей на ту, которую мы рассматривали в главе 5.

Функция ferror выдает ненулевое значение, если в файле fp была обнаружена ошибка.

  int ferror(FILE *fp)

Хотя при выводе редко возникают ошибки, все же они встречаются (например, оказался переполненым диск); поэтому в программах широкого пользования они должны тщательно контролироваться.

Функция feof (FILE *) аналогична функции ferror; она возвращает ненулевое значение, если встретился конец указанного в аргументе файла.

  int feof(FILE *fp)

В наших небольших иллюстративных программах мы не заботились о выдаче кода завершения, т.е. возврате некоторого числа, характеризующего состояние программы в момент завершения и отвечающего на вопросы: работа закончилась нормально или прервана из-за ошибки? Если работа прервана в результате ошибки, то какой? Любая серьезная программа должна возвращать код завершения.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz