void *bsearch(const void *key, const void *base, size_t nmemb,
size_t size, int (*compare)(const void*, const void*));
Параметры и их назначение сходны с таковыми для
qsort()
:
const void *key
Объект, который ищется в массиве.
const void *base
Начало массива.
size_t nmemb
Число элементов в массиве.
size_t size
Размер каждого элемента, полученный с помощью
sizeof
.
int (*compare)(const void*, const void*)
Функция сравнения. Она должна работать таким же образом, как функция сравнения для
qsort()
, возвращая отрицательные/нулевые/положительные значения в соответствии с тем, меньше/равен/больше первый параметр по сравнению со вторым.
Если объект не найден,
bsearch()
возвращает
NULL
. В противном случае она возвращает указатель на найденный объект. Если
key
соответствует более одного объекта, какой из них будет возвращен, не определено. Поэтому, как и в случае с
qsort()
, убедитесь, что функция сравнения принимает во внимание все существенные части искомой структуры данных.
ch06-searchemp.c
показывает
bsearch()
на практике, расширяя использованный ранее пример
struct employee
:
1 /* ch06-searchemp.с ---- Демонстрация bsearch(). */
2
3 #include <stdio.h>
4 #include <errno.h>
5 #include <stdlib.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_id_compare --- сравнение по ID */
15
16 int emp_id_compare(const void *e1p, const void *e2p)
17 {
18 const struct employee *e1, *e2;
19
20 e1 = (const struct employee*)e1p;
21 e2 = (const struct employee*)e2p;
22
23 if (e1->emp_id < e2->emp_id)
24 return -1;
25 else if (e1->emp_id == e2->emp_id)
26 return 0;
27 else
28 return 1;
29 }
30
31 /* print_employee --- напечатать структуру сотрудника */
32
33 void print_employee(const struct employee *emp)
34 {
35 printf("%s %s\t%d\t%s", emp->lastname, emp->firstname,
36 emp->emp_id, ctime(&emp->start_date));
37 }
Строки 7–12 определяют
struct employee
; она та же, что и раньше. Строки 16–29 служат в качестве функции сравнения как для
qsort()
, так и для
bsearch()
. Они сравнивают лишь ID сотрудников. Строки 33–37 определяют
print_employee()
, которая является удобной функцией для печати структуры, поскольку это делается из разных мест.
39 /* main --- демонстрация сортировки */
40
41 int main(int argc, char **argv)
42 {
43 #define NPRES 10
44 struct employee presidents[NPRES];
45 int i, npres;
46 char buf[BUFSIZ];
47 struct employee *the_pres;
48 struct employee key;
49 int id;
50 FILE *fp;
51
52 if (argc != 2) {
53 fprintf(stderr, "usage: %s datafile\n", argv[0]);
54 exit(1);
55 }
56
57 if ((fp = fopen(argv[1], "r")) == NULL) {
58 fprintf(stderr, "%s: %s: could not open: %s\n", argv[0],
59 argv[1], strerror(errno));
60 exit(1);
61 }
62
63 /* Очень простой код для чтения данных: */
64 for (npres = 0; npres < NPRES && fgets(buf, BUFSIZ, fp) != NULL;
65 npres++) {
66 sscanf(buf, "%s %s %ld %ld",
67 presidents[npres].lastname,
68 presidents[npres].firstname,
69 &presidents[npres].emp_id,
70 &presidents[npres].start_date);
71 }
72 fclose(fp);
73
74 /* В npres теперь число действительно прочитанных строк. */
75
76 /* Сначала отсортировать по id */
77 qsort(presidents, npres, sizeof(struct employee), emp_id_compare);