{
if (fgets(line, max, stdin) == NULL)
return 0;
else
return strlen(line);
}
Упражнение 7.6. Напишите программу, сравнивающую два файла и печатающую первую строку, в которой они различаются.
Упражнение 7.7. Модифицируйте программу поиска по образцу из главы 5 таким образом, чтобы она брала текст из множества именованных файлов, а если имен файлов в аргументах нет, то из стандартного ввода. Будет ли печататься имя файла, в котором найдена подходящая строка?
Упражнение 7.8. Напишите программу, печатающую несколько файлов. Каждый файл должен начинаться с новой страницы, предваряться заголовком и иметь свою нумерацию страниц.
7.8 Другие библиотечные функции
В стандартной библиотеке представлен широкий спектр различных функций. Настоящий параграф содержит краткий обзор наиболее полезных из них. Более подробно эти и другие функции описаны в приложении B.
7.8.1 Операции со строками
Мы уже упоминали функции 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, приведенную к нижнему регистру.
7.8.3 Функция ungetc
В стандартной библиотеке содержится более ограниченная версия функции ungetch по сравнению с той, которую мы написали в главе 4. Называется она ungetc. Эта функция, имеющая прототип
int ungetc(int с, FILE *fp)
отправляет символ c назад в файл fp и возвращает c, а в случае ошибки EOF. Для каждого файла гарантирован возврат не более одного символа. Функцию ungetc можно использовать совместно с любой из функций ввода вроде scanf, getc, getchar и т. д.
7.8.4 Исполнение команд операционной системы
Функция system(char *s) выполняет команду системы, содержащуюся в строке s, и затем возвращается к выполнению текущей программы.
Содержимое s, строго говоря, зависит от конкретной операционной системы. Рассмотрим простой пример: в системе UNIX инструкция
system("date");
вызовет программу date, которая направит дату и время в стандартный вывод. Функция возвращает зависящий от системы статус выполненной команды. В системе UNIX возвращаемый статус - это значение, переданное функцией exit.
7.8.5 Управление памятью
Функции malloc и calloc динамически запрашивают блоки свободной памяти. Функция malloc
void *malloc(size_t n)
возвращает указатель на n байт неинициализированной памяти или NULL, если запрос удовлетворить нельзя. Функция calloc
void *calloc(size_t n, size_t size)
возвращает указатель на область, достаточную для хранения массива из n объектов указанного размера (size), или NULL, если запрос не удается удовлетворить. Выделенная память обнуляется.
Указатель, возвращаемый функциями malloc и calloc, будет выдан с учетом выравнивания, выполненного согласно указанному типу объекта. Тем не менее к нему должна быть применена операция приведения к соответствующему типу (Как уже отмечалось (см. примеч. в параграфе 6.5), замечания о приведении типов значений, возвращаемых функциями malloc или calloc, - неверно. - Примеч. авт.), как это сделано в следующем фрагменте программы:
int *ip;
ip = (int *) calloc(n, sizeof(int));
Функция free(p) освобождает область памяти, на которую указывает p, - указатель, первоначально полученный с помощью malloc или calloc. Никаких ограничений на порядок, в котором будет освобождаться память, нет, но считается ужасной ошибкой освобождение тех областей, которые не были получены с помощью calloc или malloc.
Нельзя также использовать те области памяти, которые уже освобождены. Следующий пример демонстрирует типичную ошибку в цикле, освобождающем элементы списка.
for (p = head; p != NULL; p = p-›next) /* НЕВЕРНО */
free(p);
Правильным будет, если вы до освобождения сохраните то, что вам потребуется, как в следующем цикле:
for (p = head; p != NULL; p = q) {
q = p-›next;
free(p);
}
В параграфе 8.7 мы рассмотрим реализацию программы управления памятью вроде malloc, позволяющую освобождать выделенные блоки памяти в любой последовательности.
7.8.6 Математические функции
В ‹math.h› описано более двадцати математических функций. Здесь же приведены наиболее употребительные. Каждая из них имеет один или два аргумента типа double и возвращает результат также типа double.
sin(x) - синус x, x в радианах
cos(x) - косинус x, x в радианах
atan2(y,x) - арктангенс y/x, y и x в радианах
exp(x) - экспоненциальная функция e в степени x
log(x) - натуральный (по основанию e) логарифм x (x›0)
log10(x) - обычный (по основанию 10) логарифм x (x›0)
pow(x,y) - x в степени y
sqrt(x) - корень квадратный x (x › 0)
fabs(x) - абсолютное значение x
7.8.7 Генератор случайных чисел
Функция rand() вычисляет последовательность псевдослучайных целых в диапазоне от нуля до значения, заданного именованной константой RAND_MAX, которая определена в ‹stdlib.h›. Привести случайные числа к значениям с плавающей точкой, большим или равным 0 и меньшим 1, можно по формуле
#define frand() ((double) rand() / (RAND_MAX+1.0))
(Если в вашей библиотеке уже есть функция для получения случайных чисел с плавающей точкой, вполне возможно, что ее статистические характеристики лучше указанной.)
Функция srand(unsigned) устанавливает семя для rand. Реализации rand и srand, предлагаемые стандартом и, следовательно, переносимые на различные машины, рассмотрены в параграфе 2.7.
Упражнение 7.9. Реализуя функции вроде isupper, можно экономить либо память, либо время. Напишите оба варианта функции.
Глава 8. Интерфейс с системой UNIX
Свои услуги операционная система UNIX предлагает в виде набора системных вызовов, которые фактически являются ее внутренними функциями и к которым можно обращаться из программ пользователя. В настоящей главе описано, как в Си-программах можно применять некоторые наиболее важные вызовы. Если вы работаете в системе UNIX, то эти сведения будут вам полезны непосредственно и позволят повысить эффективность работы или получить доступ к тем возможностям, которых нет в библиотеке. Даже если вы используете Си в другой операционной системе, изучение рассмотренных здесь примеров все равно приблизит вас к пониманию программирования на Си; ана