使用函数指针,完成一个sort()函数,能对任何类型的数组元素进行排序: 回调函数 以及 memcpy ()原型实现

进来复习了一下C语言指针,一直没有写过太多关于函数指针的代码,而且对回调函数的理解一直都是在理论上,基本上没有太写过关于它的代码,进来得空,写了一个小程序加深下自己对回调函数和函数指针的理解。


问题描述: 编写一个sort()函数,使它能够对任何类型的数组元素进行排序。

下面是我写的代码:

/*
 使用函数指针的回调函数技巧,设计一个能排序int 和char 数组的sort()函数
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define   FALSE  0
#define   TRUE   1
//sort 函数
void sort(const void *,const int number,unsigned width,int(*compare)(void  *,void  *),void (*swap)(void  *,void  *));
int compare_int(void  *,void  *);
int compare_char(void  *,void  *);
void swap_int(void  *,void  *);
void swap_char(void  *,void  *);
void print(const void *_tmp,int num,int width,void (*_printf)(const void *));
void print_int(const void * );
void print_char(const void *);
 


int main(void)
{
    int  num=10;
    int  a_int[10]={9,2,3,8,1,5,6,4,7,12};
    char c_char[10]={'g','h','t','a','d','w','q','b','m','c'};
    //使用sort对上述两个数组进行排序
    sort(a_int ,num,sizeof (int),compare_int ,swap_int ); 
    sort(c_char,num,sizeof(char),compare_char,swap_char); 
   //打印排序结果
    print(a_int,num,sizeof (int),print_int);
    print(c_char,num,sizeof(char),print_char);
}


//the sort function
/*sort排序函数使用普通的选择排序*/
void sort(const void *_tmp,const int number,unsigned width,int(*compare)(void *,void *),void (*swap)(void *,void *))
{
    int i,j,small;
     for(i=0;i<number-1;i++)
       {
        small=i;
        for(j=i+1;j<number;j++)
              if(compare((((char *)_tmp)+j*width),(((char *)_tmp)+small*width)))//if(_tmp+j<_tmp_small) return TURE;
                    small=j;
        if(small!=i)         
           swap((((char *)_tmp)+i*width),(((char *)_tmp)+small*width));
       } 
}
//compare int function
int compare_int( void * tmp_a, void *tmp_b)
{
      if(*(int *)tmp_a<*(int *)tmp_b)
           return TRUE;
      else
           return FALSE;                    
}
//compare char  function 
int compare_char( void * tmp_a, void *tmp_b)
{
      if(*(char *)tmp_a<*(char *)tmp_b) //使用char的比较方式或其他strcmp()函数 
           return TRUE;
      else
           return FALSE;                    
} 
//swap int function
void swap_int( void * tmp_a, void *tmp_b)
{
         int temp;
             temp           =  *(int *)tmp_a;
             *(int *)tmp_a  =  *(int *)tmp_b;
             *(int *)tmp_b  =  temp;                 
}
//swap char function
void swap_char( void * tmp_a, void *tmp_b)
{
         char temp;
             temp           =  *(char *)tmp_a;
             *(char *)tmp_a =  *(char *)tmp_b;
             *(char *)tmp_b =  temp;                 
}
//printf function
void print(const void *_tmp,int num ,int width, void (*_printf)(const void *))
{
    int  i;
    for(i=0;i<num;i++)
         _printf(((char *)_tmp+i*width)); 
   printf("\n"); 
}

void print_int(const void *_tmp)
{
   printf("%d",*(int*)_tmp);  
} 

void print_char(const void *_tmp)
{
   printf("%c",*(char*)_tmp);
}
这是运行结果的:

[trageday@trageday C_test]$ gcc   -o  sort  callback_sort.c
[trageday@trageday C_test]$ ./sort
1 2 3 4 5 6 7 8 9 12 
a b c d g h m q t w 

首先从结果可以看出,整个程序的设计符合题目的要求。

这里主要说说sort() 函数:

void sort(const void *,const int number,unsigned width,int(*compare)(void  *,void  *),void (*swap)(void  *,void  *));

sort函数共有5个参数,参数1:  const void *   由于需要对int[],char[]数组进行排序,所以使用void * 指针作为参数,可以接受任何类型指针。

                                         参数2:  const int  number , 是数组元素的个数。

                                         参数3:  unsigned int  width , 由于数组通过void * 传入函数,函数无法确定类型,(或一个元素占用的内存)

                                         参数4: int(*compare)(void * ,void *),函数指针,使用void * 作为函数指针参数,就可以实现任何类型参数传递

                                         参数5:void  (*swap)(void * ,void *), 函数指针,遇上面一致

其实函数指针调用那个函数进行比较,完成交换都是作为参数传递进函数的,其实最主要的还是sort() 中使用(width参数) 获取不同类型数组中每一个元素的过程。

使用(char*) 原子级内存操作

compare((((char *)_tmp)+j*width),(((char *)_tmp)+small*width))

先把void * 强制转化为 char * ,然后按照 width  i 的 关系,提取出具体的元素。 (void * 不能解引用,且占用4字节,虽然刚巧可以对int 进行访问,但不能满足char[] 的要求,这也就是为啥要传递 width的原因。)

其实这个有点像memcpy函数,

下面是我自己实现的一个memcpy()函数

void * memcpy(void *dst ,const void * src ,int num)
{
  assert((NULL!=src)&&(NULL!=dst));
  assert(num>0);
  char *tmp_dst=(char *)dst;
  char *tmp_src=(char *)src;
  while(num--)
     *tmp_dst++=*tmp_src++;
  return dst; 
}

 这个函数要注意的几点: void * 不能解引用  必须强制转化char *

                                             函数入口参数合法性检测

                                             返回值的设计(当返回dst时,可以完成连续赋值操作,但当你没有返回值时,就不可能实现连续赋值操作)






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值