用回调函数来完成多种数据类型的插入排序

做了《Linux C一站式编程》中的一道习题,通过回调函数实现了对多种数据类型的插入排序。

如下例,在实现选择排序函数insertion_sort( )的时候,通过指向比较函数的指针cmp来比较大小。待比较的数据的数据类型在insertion_sort( )实现的时候是不知道的,在insertion_sort( )在main.cpp中被调用的时候才知道,所以cmp具体指向的比较函数(如cmp_int, cmp_float, cmp_char)在insertion_sort( )被调用的地方(main.cpp)才得到具体实现。

下面是头文件

/* generic_sort.h */
/*
* 目标: 实现回调函数版本的插入排序
* 1 对data[]的处理方法。data是一个数组,每个元素是void*类型,所以data数组名字是指向void*的指针,是一个指向指针的指针。
*
*/
#ifndef GENERIC_SORT_H
#define GENERIC_SORT_
typedef int (*cmp_t)(void *, void *);
extern void *insertion_sort(void *data[], int num, cmp_t cmp);
#endif

下面是实现文件

/*generics_sort.cpp */
//目标: 实现回调函数版本的插入排序
#include "generic_sort.h"

void * insertion_sort(void *data[], int num, cmp_t cmp) 
//注意第1个参数是一个指向指针的指针,data[]表示说明是数组类型,所以是指针。数组中的元素是void*型,所以是指向指针的指针。
{ 

	for ( int j = 1; j < num; j++)
    {
        int m = j-1;
        void* key = data[j];
        while( m>=0 &&(cmp(key,data[m])==-1) ) {
            data[m+1] = data[m];
            m--;
        }
        data[m+1]=key;
    }
	
	return data[0];
}
下面是main.cpp文件

/* main.cpp */
//目标:实现回调函数版本的插入排序
#include <iostream>
#include <stdio.h>
#include "generic_sort.h"

void print_num_int_p(int** arr, int len){
    for(int i=0;i<len;i++)
        std::cout<<*arr[i]<<"\t";
    std::cout<<std::endl;
    return;
}

void print_num_double_p(double** arr, int len){
    for(int i=0;i<len;i++)
        std::cout<<*arr[i]<<"\t";
    std::cout<<std::endl;
    return;
}

void print_num_char_p(char** arr, int len){
    for(int i=0;i<len;i++)
        std::cout<<*arr[i]<<"\t";
    std::cout<<std::endl;
    return;
}


int cmp_int(void *a, void *b)
{ 
  if( (*(int *)a) > (*(int *)b) ) 
        return 1;   
    else if( (*(int *)a) == (*(int *)b) ) 
        return 0; 
    else 
        return -1;
}

int cmp_double(void *a, void *b)
{ 
	if( (*(double *)a) > (*(double *)b) )  
        return 1; 
    else if( (*(double *)a) == (*(double *)b) )
        return 0; 
    else 
        return -1;
}

int cmp_char(void *a, void *b)
{ 
	if( (*(char*)a) > (*(char *)b) )  
        return 1; 
    else if( (*(char*)a) == (*(char *)b) )
        return 0; 
    else 
        return -1;
}

int main(void){ 
        int list_a[4] = {3,7,5,1}; 
	double list_b[4] = {0.3,7.2,5.6,1.9}; 
	char list_c[4] = {'b','c','B','e',}; 
        int *plist_a[4] = {&list_a[0], &list_a[1], &list_a[2], &list_a[3]}; 
	double *plist_b[4] = {&list_b[0], &list_b[1], &list_b[2], &list_b[3]}; 
	char *plist_c[4] = {&list_c[0], &list_c[1], &list_c[2], &list_c[3]}; 

	print_num_int_p(plist_a,4);
	insertion_sort((void**)plist_a,4,cmp_int);    
	print_num_int_p(plist_a,4);

	print_num_double_p(plist_b,4);
	insertion_sort((void**)plist_b,4,cmp_double);    
	print_num_double_p(plist_b,4);

	print_num_char_p(plist_c,4);
	insertion_sort((void**)plist_c,4,cmp_char);    
	print_num_char_p(plist_c,4);

	int a = getchar();

        return 0;
}

下面是输出结果



简单地讲,回调函数就是具有类似下面这样的功能的函数。

在function_a实现的时候, 通过函数指针指向了了函数function_b,

对于function_a而言,它并不知道function_b内部具体是怎样实现的,它只知道function_b的输入输出。它会给function_b传入数据,并且根据function_b的输出结果进一步做事情。

对于function_a的调用者而言(如在main.cpp中调用的时候),调用者需要体用具体的function_b的实现。

这样的情况下,function_b就被称作为回调函数。称作为"回调"是因为,在function_a的实现中,只是通过一个指针调用了function_b,function_a并不知道function_b的内部实现。function_b的真正实现是在function_a被调用的地方具体指明的(如在main.cpp中),绕了一个圈子,所以有回调(call back)的意思。

书中还有更多更清楚的讲解和例子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值