Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

Все процедуры разделяют общий лейтмотив; данные управляются через указатели

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

Поскольку ни один алгоритм не работает

одинаково хорошо для всех приложений, имеются несколько различных наборов библиотечных процедур для сопровождения искомых коллекций данных. Данная глава рассматривает лишь один простой интерфейс для поиска. Другой, более развитый интерфейс описан в разделе 14.4 «Расширенный поиск с использованием двоичных деревьев». Более того, мы намеренно не объясняем лежащие в основе алгоритмы, поскольку данная книга об API, а не об алгоритмах и структурах данных. Важно понять, что API можно рассматривать как «черные ящики», выполняющие определенную работу без необходимости понимания подробностей их работы.

6.2.1. Сортировка:

qsort

Сортировка выполняется с помощью

qsort
:

#include <stdlib.h> /* ISO С */

void qsort(void *base, size_t nmemb, size_t size,

 int (*compare)(const void*, const void*));

Название

qsort
происходит от алгоритма машинного поиска Хоара Quicksort (C.A.R. Hoare's Quicksort algorithm), который использовался в первоначальной реализации Unix. (Ничто в стандарте POSIX не требует использования этого алгоритма для
qsort
. Реализация GLIBC использует высоко оптимизированную комбинацию Quicksort и Insertion Sort.)

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

void *base

Адрес начала массива.

size_t nmemb

Общее число элементов в массиве.

size_t size

Размер каждого элемента массива. Лучший способ получения этого значения — оператор С

sizeof
.

int (*compare)(const void*, const void*)

Возможно устрашающее объявление указателя функции. Оно говорит, что «

compare
указывает на функцию, которая принимает два параметра '
const void*
' и возвращает
int
».

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

strcmp
: меньше нуля, если первое значение «меньше» второго, ноль, если они равны, и больше нуля, если первое значение «больше» второго. Именно функция сравнения определяет значения «больше» и «меньше» для всего, что вы сравниваете. Например, для сравнения двух значений
double
мы могли бы использовать эту функцию:

int dcomp(const void *d1p, const void *d2p) {

 const double *d1, *d2;

 d1 = (const double*)d1p; /*
Привести указатели к нужному типу */

 d2 = (const double*)d2p;

 if (*d1 < *d2) /* Сравнить и вернуть нужное значение */

return -1;

 else if (*d1 > *d2)

return 1;

 else if (*d1 == *d2)

return 0;

 else

return -1; /* NaN сортируется до действительных чисел */

}

Это показывает общий стереотип для функций сравнения: привести тип аргументов от

void*
к указателям на сравниваемый тип, а затем вернуть результат сравнения.

Для чисел с плавающей точкой простое вычитание, подобное '

return *d1 - *d2
', не работает, особенно если одно значение очень маленькое или одно или оба значения являются специальными значениями «не число» или «бесконечность». Поэтому нам приходится осуществлять сравнение вручную, принимая во внимание нечисловое значение (которое даже не равно самому себе!)

6.2.1.1. Пример: сортировка сотрудников

Для более сложных структур требуются более сложные функции. Например, рассмотрите следующую (довольно тривиальную)

struct employee
:

struct employee {

char lastname[30];

char firstname[30];

long emp_id;

time_t start_date;

};

Мы могли бы написать функцию для сортировки сотрудников по фамилии, имени и идентификационному номеру:

int emp_name_id_compare(const void *e1p, const void *e2p) {

 const struct employee *e1, *e2;

 int last, first;

 e1 = (const struct employee*)e1p; /* Преобразовать указатели */

 e2 = (const struct employee*)e2p;

 if ((last = strcmp(e1->lastname, e2->lastname)) != 0)

/* Сравнить фамилии */

return last; /* Фамилии различаются */

 /* фамилии совпадают, сравнить имена */

 if ((first = strcmp(e1->firstname, e2->firstname)) != 0)

/* Сравнить имена */

return first; /* Имена различаются */

 /* имена совпадают, сравнить номера ID */

 if (e1->emp_id < e2->emp_id) /* Сравнить ID сотрудника */

return -1;

 else if (e1->emp_id == e2->emp_id)

Поделиться:
Популярные книги

Леди Малиновой пустоши

Шах Ольга
Любовные романы:
любовно-фантастические романы
6.20
рейтинг книги
Леди Малиновой пустоши

Гримуар темного лорда IX

Грехов Тимофей
9. Гримуар темного лорда
Фантастика:
попаданцы
альтернативная история
аниме
фэнтези
5.00
рейтинг книги
Гримуар темного лорда IX

Шайтан Иван 2

Тен Эдуард
2. Шайтан Иван
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Шайтан Иван 2

Твое сердце будет разбито. Книга 1

Джейн Анна
Любовные романы:
современные любовные романы
5.50
рейтинг книги
Твое сердце будет разбито. Книга 1

Вечный. Книга II

Рокотов Алексей
2. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга II

За Горизонтом

Вайс Александр
8. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
За Горизонтом

Зодчий. Книга III

Погуляй Юрий Александрович
3. Зодчий Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Зодчий. Книга III

Охотник за головами

Вайс Александр
1. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Охотник за головами

Третий Генерал: Том X

Зот Бакалавр
9. Третий Генерал
Фантастика:
городское фэнтези
аниме
сказочная фантастика
попаданцы
5.00
рейтинг книги
Третий Генерал: Том X

Золушка вне правил

Шах Ольга
Любовные романы:
любовно-фантастические романы
6.83
рейтинг книги
Золушка вне правил

Убийца

Бубела Олег Николаевич
3. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Убийца

Локки 5. Потомок бога

Решетов Евгений Валерьевич
5. Локки
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Локки 5. Потомок бога

Студент из прошлого тысячелетия

Еслер Андрей
2. Соприкосновение миров
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Студент из прошлого тысячелетия

Первый среди равных. Книга XIII

Бор Жорж
13. Первый среди Равных
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Первый среди равных. Книга XIII