Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Программное обеспечение » Linux программирование в примерах - Арнольд Роббинс

Linux программирование в примерах - Арнольд Роббинс

Читать онлайн Linux программирование в примерах - Арнольд Роббинс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 103 104 105 106 107 108 109 110 111 ... 165
Перейти на страницу:

По этим причинам всегда следует использовать вашу библиотечную версию memcmp() вместо прокручивания своей собственной. Велика вероятность, что автор библиотеки знает машину лучше вас

12.2.4. Поиск байта с данным значением: memchr()

Функция memchr() сходна с функцией strchr(): она возвращает местоположение определенного значения внутри произвольного буфера. Как и в случае memcmp() против strcmp(), основной причиной для использования memchr() является использование произвольных двоичных данных.

GNU wc использует memchr() при подсчете лишь строк и байтов[124], и это позволяет wс быть быстрой. Из wc.c в GNU Coreutils:

257  else if (!count_chars && !count_complicated)

258  {

259   /* Использует отдельный цикл при подсчете лишь строк или строк и байтов -

260      но не символов или слов. */

261  while ((bytes_read = safe_read(fd, buf, BUFFER_SIZE)) > 0)

262  {

263   register char *p = buf;

264

265   if (bytes_read == SAFE_READ_ERROR)

266   {

267    error(0, errno, "%s", file);

268    exit_status = 1;

269    break;

270   }

271

272   while ((p = memchr(p, 'n', (buf + bytes_read) - p)))

273   {

274    ++p;

275    ++lines;

276   }

277   bytes += bytes_read;

278  }

279 }

Внешний цикл (строки 261–278) читает блоки данных из входного файла. Внутренний цикл (строки 272–276) использует memchr() для поиска и подсчета символов конца строки. Сложное выражение '(buf + bytes_read) - р' сводится к числу оставшихся байтов между текущим значением p и концом буфера.

Комментарии в строках 259–260 нуждаются в некотором объяснении. Вкратце, современные системы могут использовать символы, занимающие более одного байта в памяти и на диске. (Это несколько более подробно обсуждается в разделе 13.4 «Не могли бы вы произнести это для меня по буквам?».) Таким образом, wc должна использовать другой код, если она различает байты и символы: этот код имеет дело со случаем подсчета байтов.

12.3. Временные файлы

Временный файл является в точности тем, что звучит в его названии: файл, в котором при исполнении программы хранятся данные, которые больше не нужны после завершения программы. sort читает со стандартного ввода, если в командной строке не указаны файлы или вы используете в качестве имени файла '-'. Тем не менее, sort должна прочесть все свои входные данные, прежде чем сможет вывести отсортированные результаты. (Подумайте об этом немного, и вы увидите, что это так.) Когда читается стандартный ввод, данные должны быть где-то сохранены, прежде чем sort сможет их отсортировать; это отличное применение для временного файла. sort использует временные файлы также для хранения промежуточных результатов сортировки.

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

12.3.1. Создание временных имен файлов (плохо)

Имеются три функции, назначением которых является создание имени уникального, не существующего файла. Получив такое имя, вы можете использовать его для создания временного файла. Поскольку имя уникально, вам «гарантируется» исключительное использование файла. Вот объявления функций:

#include <stdio.h>

char *tmpnam(char *s); /* ISO С */

char *tempnam(const char *dir, const char *pfx); /* XSI */

char *mktemp(char *template); /* ISO С */

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

char *tmpnam(char *s)

Генерирует уникальное имя файла. Если s не равен NULL, он должен быть размером по крайней мере L_tmpnam байтов, и в него копируется уникальное имя. Если s равен NULL, имя генерируется во внутреннем статическом буфере, который может быть переписан при последующих вызовах. Префикс каталогов в пути будет P_tmpdir. Как P_tmpdir, так и L_tmpnam определены в <stdio.h>.

char *tempnam(const char *dir, const char *pfx)

Подобно tmpnam() дает вам возможность указать префикс каталогов. Если dir равен NULL, используется P_tmpdir. Аргумент pfx, если он не равен NULL, определяет до пяти символов для использования в качестве начальных символов имени файла tempnam() выделяет память для имен файлов, которые она генерирует. Возвращенный указатель может впоследствии использоваться с free() (и это следует сделать, если хотите избежать утечек памяти).

char *mktemp(char *template)

Генерирует уникальные имена файлов на основе шаблона. Последними шестью символами template должны быть 'ХХХХХХ'; эти символы замещаются уникальным суффиксом.

ЗАМЕЧАНИЕ. Аргумент template функции mktemp() переписывается. Поэтому он не должен быть строковой константой. Многие компиляторы, предшествовавшие стандарту С, помещают строковые константы в сегмент данных вместе с обычными глобальными переменными. Хотя в исходном коде они определены как константы, их можно переписать, таким образом, нередко встречался такой код:

/* Код в старом стиле: не используйте его */

char *tfile = mktemp("/tmp/myprogXXXXXX");

/* ...использование файла... */

На современных системах такой код. вероятно, завершится неудачей, в наши дни строковые константы находятся в сегментах памяти только для чтения.

Использование этих функций довольно просто. Файл ch12-mktemp.c демонстрирует mktemp(); нетрудно изменить его для использования других функций:

1  /* ch12-mktemp.с --- демонстрирует простое использование mktemp().

2     Для краткости проверка ошибок опущена */

3

4  #include <stdio.h>

5  #include <fcntl.h> /* для флагов открытия */

6  #include <limits.h> /* для PATH_MAX */

7

8  int main(void)

9  {

10  static char template[] = "/tmp/myfileXXXXXX";

11  char fname[PATH_MAX];

12  static char mesg[] =

13   "Here's lookin' at you, kid'n"; /* вместо "hello, world" */

14  int fd;

15

16  strcpy(fname, template);

17  mktemp(fname);

18

19  /* ОКНО СОСТОЯНИЯ ГОНКИ ОТКРЫВАЕТСЯ */

20

21  printf("Filename is %sn", fname);

22

23  /* ОКНО СОСТОЯНИЯ ГОНКИ ТЯНЕТСЯ ДОСЮДА */

24

25  fd = open(fname, O_CREAT|O_RDWR|O_TRUNC, 0600);

26  write(fd, mesg, strlen(mesg));

27  close(fd);

28

29  /* unlink(fname); */

30

31  return 0;

32 }

Переменная template (строка 10) определяет шаблон имени файла; 'ХХХХХХ' будет заменен уникальным значением. Строка 16 копирует шаблон в fname, которая не является константой: ее можно изменить. Строка 18 вызывает mktemp() для генерирования имени файла, а строка 21 выводит ее, так, чтобы мы могли видеть, что это такое. (Вскоре мы объясним комментарии в строках 19 и 23.)

Строка 25 открывает файл, создавая его при необходимости. Строка 26 записывает сообщение в mesg, а строка 27 закрывает файл. В программе, в которой файл должен быть удален после завершения работы с ним, строка 29 была бы не закомментирована. (Иногда временный файл не следует удалять; например, если файл после полной записи будет переименован.) Мы закомментировали ее, чтобы можно было запустить эту программу и посмотреть на файл впоследствии. Вот что происходит при запуске программы:

$ ch12-mktemp /* Запуск программы */

Filename is /tmp/myfileQES4WA /* Вывод имени файла */

$ cat /tmp/myfileQES4WA

Here's lookin' at you, kid' /* Содержит то, что ожидалось */

$ ls -l /tmp/myfileQES4WA /* To же с владельцем и доступом */

-rw------- 1 arnold devel 28 Sep 18 09:27 /tmp/myfileQES4WA

$ rm /tmp/myfileQES4WA /* Удалить его */

$ ch12-mktemp / * Используется ли повторно то же имя? */

Filename is /tmp/myfileic7xCy /* Нет. Это хорошо */

$ cat /tmp/myfileic7xCy /* Снова проверить содержание */

Here's lookin' at you, kid!

$ ls -l /tmp/myfileic7xCy /* Снова проверить владельца и доступ */

-rw------- 1 arnold devel 28 Sep 18 09:28 /tmp/myfileic7xCy

1 ... 103 104 105 106 107 108 109 110 111 ... 165
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Арнольд Роббинс.
Комментарии