Linux программирование в примерах
$ <b>ch06-sortemp < presdata.txt</b>Sorted by name:Bush George 41 Fri Jan 20 13:00:00 1989Bush George 43 Sat Jan 20 13:00:00 2001Carter James 39 Thu Jan 20 13:00:00 1977Clinton William 42 Wed Jan 20 13:00:00 1993Reagan Ronald 40 Tue Jan 20 13:00:00 1981 \Sorted by seniority:Carter James 39 Thu Jan 20 13:00:00 1977Reagan Ronald 40 Tue Jan 20 13:00:00 1981Bush George 41 Fri Jan 20 13:00:00 1989Clinton William 42 Wed Jan 20 13:00:00 1993Bush George 43 Sat Jan 20 13:00:00 2001(Мы использовали 1 час пополудни как приблизительное время, когда все президенты начали работать.) [66]
Стоит заметить одну вещь:
переставляет данные в массиве. Если каждый элемент массива представляет собой большую структуру, при сортировке массива большое количество данных будут копироваться туда-сюда. Вместо этого может оказаться выгодным создать отдельный массив указателей, каждый из которых указывает на один элемент массива. Затем использоватьqsort()для сортировки массива указателей, получая доступ к несортированным данным через сортированные указатели.qsort()Платой за это является дополнительная память для размещения указателей и модификация функций сравнения для дополнительного перенаправления указателей при сравнении структур. Полученной выгодой может стать значительное ускорение работы, поскольку на каждом шаге перемещается лишь четырех- или восьмибайтный указатель вместо большой структуры. (Наша
имеет размер по крайней мере 68 байтов. При обмене четырехбайтных указателей перемещается в 17 раз меньше данных, чем при обмене структур.) Для тысяч размещенных в памяти структур разница мажет быть существенной.struct employeeЗАМЕЧАНИЕ. Если вы являетесь программистом С++, знайте!
может быть опасной для использования с массивами объектов!qsort()осуществляет простые перемещения памяти, копируя байты. Она совершенно ничего не знает о конструкциях С++, таких, как конструкторы копирования или функцииqsort(). Вместо этого используйте одну из функций сортировки STL [67] или используйте методику отдельного массива указателей.operator=()6.2.1.2. Пример: сортировка содержимого каталога
В разделе 5.3 «Чтение каталогов» мы продемонстрировали, как элементы каталогов возвращаются в физическом порядке каталога. В большинстве случаев гораздо полезнее иметь содержимое каталога отсортированным каким-нибудь образом, например, по имени или по времени изменения. Хотя и не стандартизованные POSIX, несколько процедур упрощают это, используя
в качестве лежащего в основе сортирующего агента:qsort()#include <dirent.h> /* Обычный */int scandir(const char *dir, struct dirent ***namelist,int (*select)(const struct dirent*),int (*compare)(const struct dirent **, const struct dirent **));int alphasort(const void *a, const void *b);int versionsort(const void *a, const void *b); /* GLIBC */Функции
иscandir()были сделаны доступными в 4.2 BSD и широко поддерживаются [68],alphasort()является расширением GNU.versionsort()читает каталог, имя которого дано вscandir(), создает с использованиемdirмассив указателейmalloc()и устанавливаетstruct dirent, чтобы он указывал на начало этого массива. Как массив указателей, так и указываемые структуры*namelistвыделяются с помощьюstruct dirent; вызывающий код должен использоватьmalloc(), чтобы избежать утечек памяти.free()Для выбора нужных элементов используйте указатель функции
. Когда это значение равноselect, все действительные элементы каталога включаются в конечный массив. В противном случаеNULLвызывается для каждого элемента, и те элементы, для которых она возвращает ненулевое (истинное) значение, включаются в массив.(*select)()Указатель функции compare сравнивает два элемента каталога. Он передается функции
для использования при сортировке.qsort()лексикографически сравнивает имена файлов. Она использует для сравнения функциюalphasort().strcoll()похожа наstrcoll(), но учитывает связанные с местной спецификой правила сортировки (см. раздел 13.4 «Не могли бы вы написать это для меня по буквам?»).strcmp()является расширением GNU, которое использует для сравнения имен файлов функцию GNUversionsort()(см. strverscmp(3).) Короче говоря, эта функция понимает обычные соглашения по версиям имен файлов и сравнивает их соответствующим образом.strverscmp()В
приведена программа, похожая наch06-sortdir.c. Однако, она использует для работыch04-catdir.cиscandir().alphasort()1 /* ch06-sortdir.c --- Демонстрирует scandir(), alphasort(). */23 #include <stdio.h> /* для printf() etc. */4 #include <errno.h> /* для errno */5 #include <sys/types.h> /* для системных типов */6 #include <dirent.h> /* для функций каталогов */78 char *myname;9 int process(const char *dir);1011 /* main --- перечислить аргументы каталога */12