Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии 


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




Обработку ошибок в cat нельзя признать идеальной. Беда в том, что если файл по какой-либо причине недоступен, сообщение об этом мы получим по окончании конкатенируемого вывода. Это нас устроило бы, если бы вывод отправлялся только на экран, a не в файл или по конвейеру другой программе. Чтобы лучше справиться с этой проблемой, программе помимо стандартного вывода 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 exp главной программы main эквивалентна обращению к функции exit(exp). Последний вариант (с помощью exit) имеет то преимущество, что он пригоден для выхода и из других функций, и, кроме того, слово exit легко обнаружить с помощью программы контекстного поиска, похожей на ту, которую мы рассматривали в главе 5. Функция ferror выдает ненулевое значение, если в файле fp была обнаружена ошибка.

int ferror(FILE *fp)

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

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

int feof(FILE *fp);

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

Ввод-вывод строк

В стандартной библиотеке имеется программа ввода fgets, аналогичная программе getline, которой мы пользовались в предыдущих главах.

char *fgets(char *line, int maxline, FILE *fp)

Функция fgets читает следующую строку ввода (включая и символ новой строки) из файла fp в массив символов line, причем она может прочитать не более MAXLINE-1 символов. Переписанная строка дополняется символом '\0'. Обычно fgets возвращает line, а по исчерпании файла или в случае ошибки - NULL. (Наша getline возвращала длину строки, которой мы потом пользовались, и нуль в случае конца файла.)

Функция вывода fputs пишет строку (которая может и не заканчиваться символом новой строки) в файл.

int fputs(char *line, FILE *fp)

Эта функция возвращает EOF, если возникла ошибка, и неотрицательное значение в противном случае.

Библиотечные функции gets и puts подобны функциям fgets и fputs. Отличаются они тем, что оперируют только стандартными файлами stdin и stdout, и кроме того, gets выбрасывает последний символ '\n', a puts его добавляет.

Чтобы показать, что ничего особенного в функциях вроде fgets и fputs нет, мы приводим их здесь в том виде, в каком они существуют в стандартной библиотеке на нашей системе.

/* fgets: получает не более n символов из iop */ char *fgets(char *s, int n, FILE *iop) { register int c; register char *cs; cs = s; while (--n > 0 && (с = getc(iop)) != EOF) if ((*cs++ = c) == '\n') break; *cs= '\0'; return (c == EOF && cs == s) ? NULL : s;} /* fputs: посылает строку s в файл iop */int fputs(char *s, FILE *iop){ int c; while (c = *s++) putc(c, iop); return ferror(iop) ? EOF : 0;}

Стандарт определяет, что функция ferror возвращает в случае ошибки ненулевое значение; fputs в случае ошибки возвращает EOF, в противном случае - неотрицательное значение.

С помощью fgets легко реализовать нашу функцию getline:

/* getline: читает строку, возвращает ее длину */int getline(char *line, int max){ if (fgets(line, max, stdin) == NULL) return 0; else return strlen(line);}

Упражнение 7.6. Напишите программу, сравнивающую два файла и печатающую первую строку, в которой они различаются.

Упражнение 7.7. Модифицируйте программу поиска по образцу из главы 5 таким образом, чтобы она брала текст из множества именованных файлов, а если имен файлов в аргументах нет, то из стандартного ввода. Будет ли печататься имя файла, в котором найдена подходящая строка?

Упражнение 7.8. Напишите программу, печатающую несколько файлов. Каждый файл должен начинаться с новой страницы, предваряться заголовком и иметь свою нумерацию страниц.

Другие библиотечные функции

В стандартной библиотеке представлен широкий спектр различных функций. Настоящий параграф содержит краткий обзор наиболее полезных из них. Более подробно эти и другие функции описаны в приложении B.

Операции со строками

Мы уже упоминали функции strlen, strcpy, strcat и strcmp, описание которых даны в <string.h>. Далее, до конца пункта, предполагается, что s и t имеют тип char *, c и n - тип int.

strcat(s,t) - приписывает t в конец s.
strncat(s,t,n) - приписывает n символов из t в конец s.
strcmp(s,t) - возвращает отрицательное число, нуль или положительное число для s < t, s == t или s > t, соответственно.
strncmp(s,t,n) - делает то же, что и strcmp, но количество сравниваемых символов не может превышать n
strcpy(s,t) - копирует t в s.
strncpy(s,t,n) - копирует не более n символов из t в s.
strlen(s) - возвращает длину s.
strchr(s,c) - возвращает указатель на первое появление символа c в s или, если c нет в s, NULL.
strrchr(s,c) - возвращает указатель на последнее появление символа c в s или, если c нет в s, NULL.

7.8.2 Анализ класса символов и преобразование символов

Несколько функций из библиотеки <ctype.h> выполняют проверки и преобразование символов. Далее, до конца пункта, переменная c - это переменная типа int, которая может быть представлена значением unsigned, char или EOF. Все эти функции возвращают значения типа int.

isalpha(c) - не нуль, если c - буква; 0 в противном случае.
isupper(c) - не нуль, если c - буква верхнего регистра; 0 в противном случае.
islower(c) - не нуль, если c - буква нижнего регистра; 0 в противном случае.
isdigit(c) - не нуль, если c - цифра; 0 в противном случае.
isalnum(c) - не нуль, если или isalpha(c), или isdigit(c) истинны; 0 в противном случае.
isspace(c) - не нуль, если c - символ пробела, табуляции, новой строки, возврата каретки, перевода страницы, вертикальной табуляции.
toupper(c) - возвращает c, приведенную к верхнему регистру.
tolower(c) - возвращает c, приведенную к нижнему регистру.

Функция ungetc

В стандартной библиотеке содержится более ограниченная версия функции ungetch по сравнению с той, которую мы написали в главе 4. Называется она ungetc. Эта функция, имеющая прототип

int ungetc(int с, FILE *fp)

отправляет символ c назад в файл fp и возвращает c, а в случае ошибки EOF. Для каждого файла гарантирован возврат не более одного символа. Функцию ungetc можно использовать совместно с любой из функций ввода вроде scanf, getc, getchar и т. д.





Рекомендуемые страницы:


Последнее изменение этой страницы: 2017-03-14; Просмотров: 243; Нарушение авторского права страницы


lektsia.com 2007 - 2020 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.008 с.) Главная | Обратная связь