Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Linux ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 47

Автор ΠΡ€Π½ΠΎΠ»ΡŒΠ΄ Роббинс

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)

  return 0;

 else

  return 1;

}

Π›ΠΎΠ³ΠΈΠΊΠ° здСсь проста: сначала ΡΡ€Π°Π²Π½ΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ„Π°ΠΌΠΈΠ»ΠΈΠΈ, Π·Π°Ρ‚Π΅ΠΌ ΠΈΠΌΠ΅Π½Π°, Π° Π·Π°Ρ‚Π΅ΠΌ Π½ΠΎΠΌΠ΅Ρ€Π° ID, Ссли Π΄Π²Π° ΠΈΠΌΠ΅Π½ΠΈ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‚. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ для строк strcmp(), ΠΌΡ‹ автоматичСски ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅/Π½ΡƒΠ»Π΅Π²ΠΎΠ΅/ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ для возвращСния.

ΠŸΡ€ΠΈ сравнСнии ID сотрудников нСльзя просто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π²Ρ‹Ρ‡ΠΈΡ‚Π°Π½ΠΈΠ΅: ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΡŒΡ‚Π΅, Ρ‡Ρ‚ΠΎ long 64-разрядный, Π° int 32-разрядный, Π° Π΄Π²Π° значСния ΠΎΡ‚Π»ΠΈΡ‡Π°ΡŽΡ‚ΡΡ лишь Π² ΡΡ‚Π°Ρ€ΡˆΠΈΡ… 32 Π±ΠΈΡ‚Π°Ρ… (скаТСм, младшиС 32 Π±ΠΈΡ‚Π° Ρ€Π°Π²Π½Ρ‹ Π½ΡƒΠ»ΡŽ). Π’ Ρ‚Π°ΠΊΠΎΠΌ случаС Π²Ρ‹Ρ‡ΠΈΡ‚Π°Π½ΠΈΠ΅ автоматичСски ΠΏΡ€ΠΈΠ²Π΅Π»ΠΎ Π±Ρ‹ ΠΊ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΈΡŽ Ρ‚ΠΈΠΏΠ° ΠΊ int с отбрасываниСм ΡΡ‚Π°Ρ€ΡˆΠΈΡ… 32 Π±ΠΈΡ‚ΠΎΠ² ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ΠΌ Π½Π΅Π²Π΅Ρ€Π½ΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.

Π—ΠΠœΠ•Π§ΠΠΠ˜Π•. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, ΠΌΡ‹ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΠ»ΠΈΡΡŒ ΠΏΡ€ΠΈ сравнСнии ΠΈΠΌΠ΅Π½, Π² этом случаС всС сотрудники с ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠΌΠΈ фамилиями ΠΈ ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ оказались Π±Ρ‹ сгруппированы, Π½ΠΎ Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ отсортированы

Π­Ρ‚ΠΎ Π²Π°ΠΆΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ qsort() Π½Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½ΠΎΠΉ сортировки. Π‘Ρ‚Π°Π±ΠΈΠ»ΡŒΠ½Π° сортировка, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ, Ссли Π΄Π²Π° элСмСнта Ρ€Π°Π²Π½Ρ‹ Π½Π° основС значСния ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π»ΠΈΠ±ΠΎ ΠΊΠ»ΡŽΡ‡Π°(-Π΅ΠΉ), ΠΎΠ½ΠΈ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ свой ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ порядок Π΄Ρ€ΡƒΠ³ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π΄Ρ€ΡƒΠ³Π° Π² ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΌ отсортированном массивС. НапримСр, рассмотритС Ρ‚Ρ€Π΅Ρ… сотрудников с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌΠΈ фамилиями ΠΈ ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ ΠΈ с Π½ΠΎΠΌΠ΅Ρ€Π°ΠΌΠΈ 17, 42 ΠΈ 81. Π˜Ρ… порядок Π² ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΌ массивС. Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π±Ρ‹Π» 42, 81 ΠΈ 17 (Π§Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ сотрудник 42 находится ΠΏΠΎ индСксу с мСньшим Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, Ρ‡Π΅ΠΌ сотрудник 81, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, находится ΠΏΠΎ индСксу с мСньшим Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, Ρ‡Π΅ΠΌ сотрудник 17). ПослС сортировки порядок ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ 81, 42 ΠΈ 17. Если ΠΎΡ‚ΠΎ прСдставляСт ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° сравнСния Π΄ΠΎΠ»ΠΆΠ½Π° Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ всС Π²Π°ΠΆΠ½Ρ‹Π΅ ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ значСния (Наша Ρ‚Π°ΠΊ ΠΈ Π΄Π΅Π»Π°Π΅Ρ‚.)

ΠŸΡ€ΠΎΡΡ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Ρ€ΡƒΠ³ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΡ‚ΡΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ сотрудников ΠΏΠΎ ΡΡ‚Π°Ρ€ΡˆΠΈΠ½ΡΡ‚Π²Ρƒ:

int emp_seniority_compare(const void *e1p,

 const void *e2p) {

 const struct employee *e1, *e2;

 double diff;

 /* ΠŸΡ€ΠΈΠ²Π΅ΡΡ‚ΠΈ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ */

 e1 = (const struct employee*)e1p;

 e2 = (const struct employee*)e2p;

 /* Π‘Ρ€Π°Π²Π½ΠΈΡ‚ΡŒ Π²Ρ€Π΅ΠΌΠ΅Π½Π° */

 diff = difftime(e1->start_date, e2->start_date);

 if (diff < 0)

  return -1;

 else if (diff > 0)

  return 1;

 else

  return 0;

}

Для максимальной пСрСносимости ΠΌΡ‹ использовали difftime(), которая Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π°Π·Π½ΠΈΡ†Ρƒ Π² сСкундах ΠΌΠ΅ΠΆΠ΄Ρƒ двумя значСниями time_t. Для Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ случая ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΈΠ΅, Ρ‚Π°ΠΊΠΎΠ΅, ΠΊΠ°ΠΊ

return (int)difftime(e1->start_date, e2->start_date);

Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΡ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ значСния time_t находятся Π² ΠΏΡ€ΠΈΠ΅ΠΌΠ»Π΅ΠΌΠΎΠΌ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅, ΠΌΡ‹ вмСсто этого использовали ΠΏΠΎΠ»Π½Ρ‹ΠΉ трСхсторонний ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ if, просто ΠΈΠ· прСдостороТности.

Π’ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π° Π΄Π°Π½Π½Ρ‹Ρ… со списком пяти ΠΏΡ€Π΅Π·ΠΈΠ΄Π΅Π½Ρ‚ΠΎΠ² БША:

$ cat presdata.txt

/* Ѐамилия, имя, Π½ΠΎΠΌΠ΅Ρ€ ΠΏΡ€Π΅Π·ΠΈΠ΄Π΅Π½Ρ‚Π°, инаугурация */

Bush George 43 980013600

Clinton William 42 727552800

Bush George 41 601322400

Reagan Ronald 40 348861600

Carter James 39 222631200

Π’ ch06-sortemp.c ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π° простая ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°, которая считываСт этот Ρ„Π°ΠΉΠ» Π² массив struct employee, Π° Π·Π°Ρ‚Π΅ΠΌ сортируСт Π΅Π³ΠΎ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Π²Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Ρ‚ΠΎ прСдставлСнныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ сравнСния.

1   /* ch06-sortemp.c --- ДСмонстрируСт qsort() с двумя функциями сравнСния. */

2

3   #include <stdio.h>

4   #include <stdlib.h>

5   #include <time.h>

6

7   struct employee {

8    char lastname[30];

9    char firstname[30];

10   long emp_id;

11   time_t start_date;

12  };

13

14  /* emp_name_id_compare --- сравнСниС ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ, Π·Π°Ρ‚Π΅ΠΌ no ID */

15

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

17  {

     /* ...ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Ρ€Π°Π½Π΅Π΅, ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ для экономии мСста... */

39  }

40

41  /* emp_seniority_compare --- сравнСниС ΠΏΠΎ ΡΡ‚Π°Ρ€ΡˆΠΈΠ½ΡΡ‚Π²Ρƒ */

42

43  int emp_seniority_compare(const void *e1p, const void *e2p)

44  {

     /* ...ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Ρ€Π°Π½Π΅Π΅, ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ для экономии мСста... */

58  }

59

60  /* main --- дСмонстрация сортировки */

61

62  int main(void)

63  {

64   #define NPRES 10

65   struct employee presidents[NPRES];

66   int i, npres;

67   char buf[BUFSIZ];

68

69   /* ΠžΡ‡Π΅Π½ΡŒ простой ΠΊΠΎΠ΄ для чтСния Π΄Π°Π½Π½Ρ‹Ρ…: */

70   for (npres = 0; npres < NPRES && fgets(buf, BUFSIZ, stdin) != NULL;

71    npres++) {

72    sscanf(buf, "%s %s %ld %ld\n",

73     presidents[npres].lastname,

74     presidents[npres].firstname,

75     &presidents[npres].emp_id,

76     &presidents[npres].start_date);

77   }