利用排序那点事来说说函数指针好在哪里?

          看了一下有些人写的关于函数指针的文章,对于初学者学习起来有点费力,原因很简单——没有具体的代码演示,理解的自然而然不那么深刻强烈,总感觉有点空洞。我今天用大家很清楚的排序代码来说说函数指针好在哪里?

         先提一下函数指针与指针函数以免搞混淆,其实很好区分,就按照字面意思来理解,           

         函数指针:一个指向函数的指针,本质是指针。     

     void  (*fun)(int a,int b);
    指针函数:一个返回值为指针的函数,本质是函数。

     void  *fun(int a,int b);

   数组指针和指针数组也是一样的道理,不在赘述。

   应用场景:我想要写一个排序的代码,不仅可以实现整数排序、字符排序、小数排序,还可以升序、降序。如果实现这些功能,确实so easy,连续写6个排序的代码。但是这样子造成了大量的冗余代码,如果以后需要继续增加功能的话,又要在里面源代码里面修修改改,违反“开闭原则”,而且代码看起来也不美观。

   解决办法:为什么会出现冗余?冗余在哪里了?问题是出在数据类型上,多一个数据类型,就要多写一遍排序的代码。如果我们采用一种办法可以把数据类型和排序代码(算法框架)隔离开,那么再多的数据类型,我们也就写一遍排序代码。 这个时候就需要函数指针登场了。考虑到通用性(屏蔽数据类型)用函数指针隔离变化,用一个接口可以实现升序、降序和不同类型的排序,让用户自己选择怎么去排序。
/*
     函数指针简单实现通用通用排序测试用例
  */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//函数指针隔离变化
typedef int (*Cmp_number)(void *a,void *b);
typedef void (*Print)(void *value);
//关于int
// int类型的数据从小到大
int int_cmp(void *a,void *b)
{
    return *(int *)a - *(int *)b;
}
// int类型的数据从大到小
int int_reverse_cmp(void *a,void *b)
{
    return *(int *)b - *(int *)a;
}
//打印int类型的数据
void print_int(void *value)
{
   printf("%d ",*(int *)value);
}

//关于double
// 关于double类型的数据从小到大
int  double_cmp(void *a,void *b)
{
    return (int)(*(double *)a - *(double*)b);
}
// 关于double类型的数据从大到小
int  double_reverse_cmp(void *a,void *b)
{
    return (int)(*(double *)b - *(double*)a);
}
//打印double类型的数据
void print_double(void *value)
{
   printf("%.2f ",*(double *)value);
}


//关于char的
int char_cmp(void *a,void *b)
{
    return (int)(*(char  *)a - *(char *)b);
}
int  char_reverse_cmp(void *a,void *b)
{
    return (int)(*(char *)b - *(char *)a);
}
void  print_char(void *value)
{
   printf("%c ",*(char *)value);
}

// 优化选择排序
void select_sort(void **array,int n,Cmp_number cmp)
{
    int i = 0;
    int j = 0;
    int k = 0;
    void *data = NULL;

    if(array == NULL || n <= 1){
        return ;
    }
    for(i = 0; i < n -1; i++){
        k = i;
       for(j = i+1; j < n; j++){
           if(cmp(array[k],array[j]) > 0){
              k = j;
           }
       }//end for 
       data = array[i];
       array[i] = array[k];
       array[k] = data;
    }//end for

}

//输出
void print_sort(void **array,int n,Print print_int)
{
    int i = 0;

    for(i = 0; i < n; i++){
      // printf("%d ",*(int**)array[i]);
      print_int(array[i]);
    }
    printf("\n");
}

//主函数
int main(int argc,char *argv[])
{
    int    i = 0;
    void   **array = NULL;
    int     a[10] = {5,2,1,1,2,5,125,521,2,2};
    double  b[10] = {2.5,5.2,1.1,5.21,2.5,5.21,2.51,1.0,9.1,5.21};
    char    c[10] = {'r','y','g','d','a','c','h','a','x','g'};

    array = malloc(sizeof(void *) *10);
  
    //关于整数的降序
    for(i = 0; i < 10; i++){
        array[i] = a + i;
    }
    select_sort(array,10,int_reverse_cmp);
    printf("整数降序:");
    print_sort(array,10,print_int);

    //关于小数的升序
    memset(array,0x00,sizeof(array));
    for(i = 0; i < 10; i++){
        array[i] = b + i;
    }
    select_sort(array,10,double_cmp);
    printf("小数升序: ");
    print_sort(array,10,print_double);

    //关于字符的升序
    memset(array,0x00,sizeof(array));
    for(i = 0; i < 10; i++){
        array[i] = c + i;
    }
    select_sort(array,10,char_cmp);
    printf("字符升序: ");
    print_sort(array,10,print_char);

    return 0;
}

  上面的排序代码(算法框架)就一个,只是对于不同的类型数据有专门的处理代码,而这些代码可以专门写在一个文件里面,不必在核心代码中出现。

typedef int (*Cmp_number)(void *a,void *b);    //比较不同类型的数

typedef void (*Print)(void *value);          //打印不同的类型的数

   知道了上面这些int ,double, char函数, 通过select_sort(array,array_num,func)接口,只选择合适的func函数调用,用户自己选择。



运行环境



运行结果


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值