【C】——コールバック関数実現汎用アルゴリズム
8067 ワード
コールバック関数の典型的な応用はC++のような汎用アルゴリズムを実現することである.(Generics Algorithm).以下に実装される
max
関数は、任意のオブジェクトのセットの中で最大値を見つけることができ、int
のセット、char
のセット、または構造体のセットであってもよいが、実装者は2つのオブジェクトのサイズをどのように比較するか分からず、呼び出し者は比較操作を行うコールバック関数を提供する必要がある. 1 /* generics.h */
2 #ifndef GENERICS_H
3 #define GENERICS_H
4
5 typedef int (*cmp_t)(void *, void *);
6 extern void *max(void *data[], int num, cmp_t cmp);
7
8 #endif/* generics.c */
9 #include "generics.h"
10
11 void *max(void *data[], int num, cmp_t cmp)
12 {
13 int i;
14 void *temp = data[0];
15 for(i=1; i<num; i++) {
16 if(cmp(temp, data[i])<0)
17 temp = data[i];
18 }
19 return temp;
20 }/* main.c */
21 #include <stdio.h>
22 #include "generics.h"
23
24 typedef struct {
25 const char *name;
26 int score;
27 } student_t;
28
29 int cmp_student(void *a, void *b)
30 {
31 if(((student_t *)a)->score > ((student_t *)b)->score)
32 return 1;
33 else if(((student_t *)a)->score == ((student_t *)b)->score)
34 return 0;
35 else
36 return -1;
37 }
38
39 int main(void)
40 {
41 student_t list[4] = {{"Tom", 68}, {"Jerry", 72},
42 {"Moby", 60}, {"Kirby", 89}};
43 student_t *plist[4] = {&list[0], &list[1], &list[2], &list[3]};
44 student_t *pmax = max((void **)plist, 4, cmp_student);
45 printf("%s gets the highest score %d
", pmax->name, pmax->score);
46
47 return 0;
48 }
max
関数が任意のタイプのオブジェクトのセットを操作できるのは、max
に渡されるのは、オブジェクト自体が構成する配列ではなく、オブジェクトを指すポインタで構成された配列であることが重要である.このようにmax
は、オブジェクトがどのようなタイプなのかを気にする必要がなく、比較関数cmp
に転送し、比較結果に基づいて対応する操作を行うだけでよい.cmp
は、呼び出し元が提供するコールバック関数であり、呼び出し元は、オブジェクトがどのようなタイプであるか、およびどのように比較されるかを当然知っている.