• Некоторые библиотечные функции возвращают информацию об ошибке точно таким же образом, что и системные вызовы: возвращают значение –1, а значение переменной errno указывает на конкретную ошибку. Примером такой функции может послужить remove(), удаляющая файл (используя системный вызов unlink()) или каталог (используя системный вызов rmdir()). Ошибки из этих функций могут определяться точно так же, как и ошибки из системных вызовов.
• Некоторые библиотечные функции возвращают при ошибке значение, отличное от –1, но все-таки устанавливают значение для переменной errno, чтобы указать на конкретные условия возникновения ошибки. Например, функция fopen() в случае ошибки возвращает нулевой указатель и устанавливает для переменной errno значение в зависимости от того, какой из положенных в основу ее работы системных вызовов завершился неудачно. Для определения типа таких ошибок могут применяться функции perror() и strerror().
• Другие библиотечные функции вообще не используют переменную errno. Метод определения наличия и причин ошибок зависит от конкретной функции и задокументирован на посвященной ей странице руководства. Для таких функций применение errno, perror() или strerror() с целью определения типа ошибок будет неприемлемо.
В этом разделе будут рассмотрены различные соглашения и характерные особенности, которые обычно применяются к примерам программ, приводимым в книге.
3.5.1. Ключи и аргументы командной строки
Многие примеры программ в книге основаны на использовании ключей и аргументов командной строки, определяющих их поведение.
Традиционные ключи командной строки UNIX состоят из начального дефиса, буквы, идентифицирующей ключ, и необязательного аргумента. (Утилиты GNU предоставляют расширенный синтаксис ключей, состоящий из двух начальных дефисов, за которыми следует строка, идентифицирующая ключ, и необязательный аргумент.) Для анализа этих ключей используется стандартная библиотечная функция getopt().
Каждый из наших примеров, где есть неочевидный синтаксис командной строки, снабжен простым вспомогательным средством для пользователя. При вызове с ключом — help программа выводит сообщение о порядке своей работы, показывая синтаксис для ключей и аргументов командной строки.
3.5.2. Типовые функции и заголовочные файлы
Большинство примеров программ включают заголовочный файл, содержащий необходимые в большинстве случаев определения, и в них также используется набор типовых функций. В этом разделе будут рассмотрены заголовочный файл и функции.
Типовой заголовочный файл
В листинге 3.1 приведен заголовочный файл, используемый практически в каждой программе, показанной в книге. Он включает различные другие заголовочные файлы, используемые во многих примерах программ, определяет тип данных Boolean и определяет макрос для вычисления минимума и максимума двух числовых значений. Применение данного файла позволяет немного сократить размеры примеров программ.
Листинг 3.1. Заголовочный файл, используемый в большинстве примеров программ
lib/tlpi_hdr.h
#ifndef TLPI_HDR_H
#define TLPI_HDR_H /* Предотвращает случайное двойное включение */
#include
многими программами */
#include
#include
функций плюс константы EXIT_SUCCESS
и EXIT_FAILURE */
#include
#include
#include
#include "get_num.h" /* Объявление наших функций для обработки числовых
аргументов (getInt(), getLong()) */
#include "error_functions.h" /* Объявление наших функций обработки ошибок */
typedef enum { FALSE, TRUE } Boolean;
#define min(m,n) ((m) < (n)? (m): (n))
#define max(m,n) ((m) > (n)? (m): (n))
#endif
lib/tlpi_hdr.h
Функции определения типа ошибок
Чтобы упростить обработку ошибок в наших примерах программ, мы используем функции определения типа ошибок. Объявление такой функции показано в листинге 3.2.
Листинг 3.2. Объявление для наиболее востребованных функций обработки ошибок
lib/error_functions.h
#ifndef ERROR_FUNCTIONS_H
#define ERROR_FUNCTIONS_H
void errMsg(const char *format…);
#ifdef __GNUC__
/* Этот макрос блокирует предупреждения компилятора при использовании