Смекни!
smekni.com

Методические указания к выполнению контрольных работ по дисциплине "Основы программирования" (стр. 40 из 40)

9.7. Обработка ошибок: stderr и exit

Обработка ошибок в программе cat неидеальна. Неудобство заключается в том, что если один из файлов по некоторой причине оказывается недоступным, диагностическое сообщение об этом печатается в конце объединенного вывода. Это приемлемо, если вывод поступает на терминал, но не годится, если вывод поступает в некоторый файл или через поточный (pipeline) механизм в другую программу.

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

Пример 9-5. Давайте переделаем программу cat таким образом, чтобы сообщения об ошибках писались в стандартный файл ошибок.

// cat: Объединить (от англ. concatenate) файлы

#include <stdio.h>

main(int argc, char *argv)

{

FILE *fp, *fopen();

if(argc==1) // Нет аргументов: копировать stdin

filecopy(stdin);

else

while (--argc > 0)

if((fp=fopen(*++argv,"r"))== NULL)

{

printf(stderr, "cat: не открыть %s&bsol;n", argv);

exit(1);

}

else

{

filecopy(fp);

}

exit(0);

}

Программа сообщает об ошибках двумя способами. Диагностическое сообщение, выдаваемое функцией fprintf, поступает в stderr и, таким образом, оказывается на терминале пользователя, а не исчезает в потоке (pipeline) или в выходном файле.

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

Функция exit вызывает функцию fclose для каждого открытого выходного файла, с тем чтобы вывести всю помещенную в буферы выходную информацию, а затем вызывает функцию _exit. Функция _exit приводит к немедленному завершению без очистки каких-либо буферов; конечно, при желании к этой функции можно обратиться непосредственно.

9.8. Ввод и вывод строк

Стандартная библиотека содержит функцию fgets, совершенно аналогичную функции getline, которую мы использовали на всем протяжении книги. В результате обращения fgets(line, maxline, fp) следующая строка ввода (включая символ новой строки) считывается из файла fp в символьный массив line; самое большое maxline_1 символ будет прочитан. Результирующая строка заканчивается символом &bsol;0. Нормально функция fgets возвращает line; в конце файла она возвращает NULL. (Наша функция getline возвращает длину строки, а при выходе на конец файла – нуль).

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

fputs(line, fp) .

Пример 9-6. Чтобы показать, что в функциях типа fgets и fputs нет ничего таинственного, мы приводим их ниже, скопированными непосредственно из стандартной библиотеки ввода-вывода:

// fgets: получить не более n символов из файла iop

#include <stdio.h>

char *fgets(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)=='&bsol;n')

break;

*cs = '&bsol;0';

return((c== EOF && cs==s) 7 NULL : s);

}

// fputs: посылает строку в файл iop

fputs(register char *s, register FILE *iop)

{

register int c;

while (c = *s++)

putc(c,iop);

}

Упражнение 8-3. напишите программу сравнения двух файлов, которая будет печатать первую строку и позицию символа, где они различаются.

Упражнение 8-4. Переделайте программу поиска заданной комбинации символов из главы 6 таким образом, чтобы в качестве ввода использовался набор именованных файлов или, если никакие файлы не указаны как аргументы, стандартный ввод. Следует ли печатать имя файла при нахождении подходящей строки?

Упражнение 8-5. Напишите программу печати набора файлов, которая начинает каждый новый файл с новой страницы и печатает для каждого файла заголовок и счетчик текущих страниц.

9.9. Несколько разнообразных функций

Стандартная библиотека предоставляет множество разнообразных функций, некоторые из которых оказываются особенно полезными. Мы уже упоминали функции для работы со строками: strlen, strcpy, strcat и strcmp. Вот некоторые другие.

9.9.1. Проверка вида символов и преобразования. Некоторые макросы выполняют проверку символов и преобразования. Возврат ненулевого значения – это true (истина), а ненулевого значения – false (ложь). Например, для переменой int n справедливо:

;

;

;

;

;

.

Кроме того, существуют две полезные функции:

int n = oupper(c) – преобразует букву c в прописную;

int n = olower(c) – преобразует букву c в строчную.

Такие функции мы уже научились создавать сами.

9.9.2. Функция ungetc. Стандартная библиотека содержит довольно ограниченную версию функции ungetch, написанной нами в главе 5 она называется ungetch. В результате обращения:

ungetc(c,fp)

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

9.9.3. Обращение к системе. Функция system(s) выполняет команду, содержащуюся в символьной строке s, и затем возобновляет выполнение текущей программы. Содержимое s сильно зависит от используемой операционной системы. В качестве тривиального примера, укажем, что на системе Unix строка:

system("date");

приводит к выполнению программы date, которая печатает дату и время дня.

9.9.4. Управление памятью. Функция calloc весьма сходна с функцией alloc, использованной нами в предыдущих главах. В результате обращения:

calloc(n, sizeof(objcct))

возвращается либо указатель пространства, достаточного для размещения n объектов указанного размера, либо NULL, если запрос не может быть удовлетворен. Отводимая память инициализируется нулевыми значениями.

Указатель обладает нужным для рассматриваемых объектов выравниванием, но ему следует приписывать соответствующий тип, как в:

char *calloc();

int *ip;

ip=(int*) calloc(n,sizeof(int));

Функция cfree(p) освобождает пространство, на которое указывает p, причем указатель p певоначально должен быть получен в результате обращения к calloc. Здесь нет никаких ограничений на порядок освобождения пространства, но будет неприятнейшей ошибкой освободить что-нибудь, что не было получено обращением к calloc.

Данные функции управления памятью есть в составе операционной системы. Однако, язык C++ предоставляет удобный оператор new, который обеспечивает то же самое. Реализация программы распределения памяти, подобной calloc, в которой размещенные блоки могут освобождаться в произвольном порядке, продемонстрирована в главе 8 с помощью операторов new и sizeof.

ЛИТЕРАТУРА

1. Болски М.И. Язык программирования Си: Справочник. – М.: Радио и связь, 2000. – 96 с.

2. Керниган Б., Пайк Р. Практика программирования. – СПб.: Невский диалект, 2001. – 381 с.

3. Керниган Б., Ритчи Д. Язык программирования Си. – СПб.: Невский диалект, 2001 + М.: Финансы и статистика, 2001. – 352 с.

4. Кнут Д. Искусство программирования. Том 1. – М.: Статистика, 1975. – 568 с.

5. Круглински Д. Дж., Уингоу С., Шеферд Дж. Программирование на Microsoft Visual С++ 6.0 для профессионалов. – СПб.: Питер; М.: Русская редакция, 2001. – 864 с.

6. Крупник А.Б. Изучаем Си. – СПб.: Питер, 2002. – 256 с.

7. Крупник А.Б. Изучаем С++. – СПб.: Питер, 2002. – 251 с.

8. Шилдт Г. Программирование на С и С++ для Windows. – К.: Торгово-издательское бюро BHV, 2001. – 408 с.


* См. А. Крупник «Изучаем C++». – Глава 1. Что такое программирование. – СПб.: Питер, 2003. –
251 с.

5 Слова «ячейка» и «байт» обозначают одно и то же – восемь по­следовательных битов.

* Именно в честь Августы Ады дано название одному из современных языком программирования: АДА

* Определение деления с остатком в этом случае содержится в доказательстве, которое нужно выполнить в упражнении 1.15.

*) Конечно, «оператор» может состоять из нескольких операторов – блока, заключенного в фигурные скобки

* См.: Емельянов А.А. Власова Е.А., Дума Р.В. Имитационное моделирование экономических процессов. – М.: Финансы и статистика, 2003. – 368 с.

* Эта особенность есть только в Unix