使用函数指针,完成一个sort()函数,能对任何类型的数组元素进行排序: 回调函数 以及 memcpy ()原型实现
2014-05-30 14:27
1106 查看
进来复习了一下C语言指针,一直没有写过太多关于函数指针的代码,而且对回调函数的理解一直都是在理论上,基本上没有太写过关于它的代码,进来得空,写了一个小程序加深下自己对回调函数和函数指针的理解。
问题描述: 编写一个sort()函数,使它能够对任何类型的数组元素进行排序。
下面是我写的代码:
首先从结果可以看出,整个程序的设计符合题目的要求。
这里主要说说sort() 函数:
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 * 不能解引用 必须强制转化char *
函数入口参数合法性检测
返回值的设计(当返回dst时,可以完成连续赋值操作,但当你没有返回值时,就不可能实现连续赋值操作)
问题描述: 编写一个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个元素的数组,分别为A和B,编程实现相同位置的元素, 如果 B 的元素小于 A 的元素进行数值交换:(使用回调函数实现)
- 那些年我们刷过的算法题(排序)---有一个只由0,1,2三种元素构成的整数数组,请使用交换、原地排序而不是使用计数进行排序
- (PHP实现剑指offer)在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- PHP实现在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 使用回调函数实现一个通用的冒泡排序,可以排序不同的数据类型。
- 1、使用快速枚举语法实现: //构建一个NSSMutableArray数组,用@”1”至@”100”进行填充。以NSLog依次打印数组中的内容,将此数组分为奇偶两数组,再打印两新数组中的元素。
- (PHP实现剑指offer)在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- Go语言:使用sort包对任意类型元素的集合进行排序
- 参考C语言的qsort函数实现一个一个能对任意数据类型(包括结构体)的数组进行排序的函数(里面用的不是快速排序)
- 个有10个元素的整型一维数组,用户输入9个数据,调用函数,对数组元素进行从小到大排序后,在函数中输入一个数,插入到数组中正确的位置,并输出
- 编写一个使用数组类模板Array对数组进行排序、求最大值和求元素和的程序,并采用相关数据进行测试。
- 自己实现一个bubble_sort(冒泡排序),可以完成不同类型数据的排序
- 【php数组函数序列】之sort() - 对数组的元素值进行升序排序
- 使用JavaScript完成一个对字符串数组进行排序的小程序
- C Primer plus 10.2 初始化一个double类型的数组,然后把该数组的内容拷贝至3个其它的数组中,使用带数组的表示方法的函数进行第一份拷贝,使用带指针表示方法和指针递增的函..
- System提供了一个静态方法arraycopy(),我们可以使用它来实现数组之间的复制。 其函数原型是: public static void arraycopy(Object src, int
- 有两个10个元素的数组,分别为A和B,编程实现相同位置的元素, 如果 B 的元素小于 A 的元素进行数值交换:(使用回调函数实现)
- Go语言使用sort包对任意类型元素的集合进行排序的方法
- 第一次发博客,新手初试啊,题目如下:有两个10个元素的数组,分别为A和B,编程实现相同位置的元素, 如果 B 的元素小于 A 的元素进行数值交换:(使用回调函数实现)