1.回調函數
回調函數就是通過函數指針調用的函數。
將函數的指針(地址)作為一個參數傳遞給另一個函數,當這個指針被調用其所指向的函數時,被調用的函數就是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外一方調用的,用于對該事件或條件進行響應。
計算器的實現:
menu()
{printf("********************\n");printf("*** 1.add 2.sub ***\n");printf("*** 3.mul 4.div ***\n");printf("*** 0.exit ***\n");printf("********************\n");
}int Add(int x, int y)
{return x + y;
}int Sub(int x, int y)
{return x - y;
}int Mul(int x, int y)
{return x * y;
}int Div(int x, int y)
{return x / y;
}void calc(int(*pf)(int,int))//傳過來的是函數的地址,要用函數指針變量來接收
{int x = 0;int y = 0;int ret = 0;printf("請輸入兩個操作數:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("%d\n", ret);
}int main()
{int input = 0;do{menu();printf("請選擇:");scanf("%d", &input);switch (input){case 1://calc功能強大了calc(Add);//完成相應的計算 加法、減法、乘法、除法 通過傳函數的地址來實現對應的計算,需要函數指針來接收break;case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;case 0:printf("退出計算器\n");break;default:printf("請重新選擇\n");break;}} while (input);return 0;
}
?
2.qsort使用舉例
2.1使用 qsort 函數排序整形數據
#include<stdlib.h>
void print_arr(int arr[],int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");
}//cmp_int 這個函數是用來比較p1和p2指向元素的大小// cmp—函數的使用者提供,誰使用誰提供//cmp函數中的參數類型必須和 test() 函數中的qsort中的第四個參數類型保持一致才可以傳過去
int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;}//測試qsort排序整型數據
void test1()
{int arr[10] = { 5,3,2,1,0,9,8,4,7,6 };int sz = sizeof(arr) / sizeof(arr[0]);print_arr(arr,sz);qsort(arr, sz, sizeof(arr[0]), cmp_int);//qsort 函數底層用的是快速排序print_arr(arr,sz);
}
int main()
{test1();//用來實現整型數據的排序return 0;
}
2.2使用qsort排序結構數據
//測試qsort排序結構體數據struct Stu
{char name[20];int age;};//比較2個結構體的數據???
//不能直接使用 < > == 來比較
//
//1.按照名字來比較
//2.按照年齡來比較//按照年齡來比較
int cmp_stu_by_age(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;//升序// p2 p1 //降序//(*(struct Stu*)p1).age
}
//-> 僅限于結構體指針運用
//結構體指針->成員名
//結構體變量.成員名#include<string.h>
//按照姓名來比較:比較對應位置上的字母相對應的ASCII碼值
//兩個字符串是不能使用 > < == 來進行比較的
//比較字符串是 strcmp - string compare 返回類型和
//int cmp_stu_by_name(const void* p1, const void* p2) 一樣: <0 >0 =0
//所以直接 return 0 返回
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}test2()
{struct Stu arr[] = { {"xiaoming",14},{"xiaohong",16},{"xiaolan",17} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);}test3()
{struct Stu arr[] = { {"xiaoming",14},{"xiaohong",16},{"xiaolan",17} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);}
int main()
{test1();//用來實現整型數據的排序test2();//用來實現結構體指針數據的排序test3();//按照結構體年齡來排序return 0;
}
3.qsort函數的模擬實現
使用回調函數,模擬實現qsort的功能(采用冒泡排序)
代碼中使用 void * 的指針,是方便接收任何類型的地址,以此來實現任何類型的排序
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>int cmp_int(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}void Swap(char *buf1, char *buf2, size_t width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}}
//參照qsort(arr, sz,sizeof(arr[0]),cmp_int);來寫bubble_sort2函數
void bubble_sort2(void* base, size_t sz, size_t width, int(*cmpar)(const void* p1, const void* p2))
//只希望接收p1和p2的地址,不想由任何的改變,所以加上const
{int i = 0;for (i = 0; i < sz; i++)//趟數不變,這個不變{int j = 0;for (j = 0; j < sz - 1 - i; j++)//每相鄰的元素的比較不變,這個也不變{//if (arr[j] > arr[j + 1]) 不再是數組—>改變if(cmpar((char*)base+j*width,(char*)base+(j+1)*width)>0){/*int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;*///交換-->也變Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);}}}
}void test3()
{int arr[10] = { 2,6,4,8,9,3,0,1,7,5 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort2(arr, sz, sizeof(arr[0]), cmp_int);print_arr(arr, sz);
}struct Stu //學生
{char name[20];int age;
};
int cmp_stu_by_age(const void*p1,const void*p2)
{return ((struct Stu*)p1)->age - ((struct Stu *)p2)->age;
}int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name,((struct Stu*)p2)->name);
}
void test4()
{struct Stu arr[] = { {"mingxiao",25},{"hongxiao",27},{"lanxiao",23} };int sz = sizeof(arr) / sizeof(arr[0]);//bubble_sort2(arr, sz, sizeof(arr[0]), cmp_stu_by_name);bubble_sort2(arr, sz, sizeof(arr[0]), cmp_stu_by_age);//打印數組內容int i = 0;for (i = 0; i < sz; i++){printf("%s %d\n", arr[i].name, arr[i].age);}}int main()
{//test1();//冒泡排序實現數組的升序//test2();//用qsort函數來實現數組的升序test3();//自己用bubble_sort2來實現qsort函數的功能,以此來達到實現能夠排序任意類型數據的目的//1.先實現bubble_sort2()函數,再進行后續的操作//2.bubble_sort2()函數里面兩個相鄰函數的比較以及交換test4();//用bubble_sort2()函數來實現結構體的中數據的排序return 0;
}
?在Swap中用 char * 來接收是為了方便交換,特別是結構體類型的數據,大小是不確定的,可能是4字節、16字節、23字節等等,根據使用者自己編寫的代碼來分配大小,一個一個字節的交換可以實現單數(9)字節大小的單位的類型交換,來達到實現任意類型數據的交換。