「2」指针进阶——详解
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
🐰回调函数(通过函数指针调用函数)
🐰快速排序
🌸冒泡排序
🌸qsort()
🐰用冒泡排序类似实现qsort
🐰指向函数指针数组的指针(很少用,了解)
#include<stdio.h> void Add(int ,int) {printf("%d\\n",1+1); } void Sub(int ,int) {printf("%d\\n",1-1); } int main() {int (*pf)(int,int)=Add;//函数指针int (*pfArr[4])(int,int)={Add,Sub};//函数指针数组int (*(*ppfArr)[4])(int,int)=&pfArr;//ppfArr就是指向函数的指针数组的指针return 0; }
🐰回调函数(通过函数指针调用函数)
通过回调函数实现 两个操作数的加减乘除:#include<stdio.h> void Calc(int(*pf)(int,int)) {int x=0,y=0;printf("请输入两个操作数\\n");scanf("%d %d",&x,&y);int ret=pf(x,y);printf("%d\\n",ret); } 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 menu(void) {printf(" 两位数的计算器 \\n");printf(" 1.Add 2.Sub \\n");printf(" 3.Mul 4.Div \\n");printf(" 0.exit \\n"); } int main() {int input=0;do{menu();printf("请选择\\n");scanf("%d",&input);switch(input){case 1:Calc(Add);break;case 2:Calc(Sub);break;case 3:Calc(Mul);break;case 4:Calc(Div);break;case 0:printf("exit\\n");break;default:printf("输入错误\\n");}}while(input); }
🐰快速排序
qsort是一个库函数,是用来排序(使用的快速排序的方法)1.库函数里的,可以直接使用 2.可以排序任意类型的数据
🌸冒泡排序
#include<stdio.h>void Bubble(int arr[],int len) {int i=0,j=0;for(i=0;i<len-1;i++){for(j=0;j<len-1-i;j++){if(arr[i]>arr[j+1]){int temp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}}} } void Print(int arr[],int len) {for(int i=0;i<len;i++){printf("%d ",arr[i]);}printf("\\n"); } int main() {int arr[]={3,2,1,5,7,8,9,0};int len=sizeof(arr)/sizeof(arr[0]);Bubble(arr,len);Print(arr,len); }
🌸qsort()
qsort的原型:void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
void qsort (void* base//指向了待排序数组的第一个元素的地址, size_t num(无符号整形)//待排序的元素个数, size_t size(无符号整形)//每个元素的大小,单位是字节,int (*compar)(const void*,const void*)//这里是一个函数指针,指向一个函数,这个函数可以比较2个元素的大小);
比较函数:就是函数指针campar指向的函数,因为使用qsort时,要自己定义比较函数,以下是常见的比较函数比较整形变量时 int cmp_int(const void* e1, const void* e2) {return *(int*)e1 - *(int*)e2; }
比较浮点型变量时 int cmp_float(const void* e1, const void* e2) {return (int)(*(float*)e1 - *(float*)e2); }
比较字符串变量时 int cmp_str_size(const void* e1, const void* e2) {return strcmp((char*)e1,(char*)e2); }
比较字符串长度时 int cmp_str_len(const void* e1, const void* e2) {return strlen((char*)e1)-strlen((char*)e2); }
比较结构体变量时 int cmp_by_age(const void*e1, const void*e2) {return (int)((stu*)e1)->weight - ((stu*)e2)->weight)); }
cmp函数的返回值:返回值<0(不进行置换),>0(进行置换),0(不进行置换)。记得返回的结果一定是整形的,如果不是需要强制转为整形的
‼️注:void*的指针不能解引用,也不能算术运算下面是使用qsort排序整形变量和结构体变量的原码:#include<stdio.h> #include<stdlib.h> #include<string.h> int cmp_int(const void* e1,const void* e2)//对整形比较 {return *(int*)e1-*(int*)e2; }void test_1() {int arr[]={2,3,4,5,6,7,1};int sz=sizeof(arr)/sizeof(arr[0]);//计算出数组下标,就不用手动去数有多少个元素了//这里需要提供一个比较函数,这个比较函数能够比较2个整数的大小//qsort默认为升序qsort(arr,sz,sizeof(arr[0]),cmp_int);for(int i=0;i<sz;i++){printf("%d ",arr[i]);} } struct stu//定义了一个包含字符类型,整形,浮点型的结构体 {char name[20];int age;float weight; }; int sort_by_name(const void* e1,const void* e2)//对字符串的比较 {return strcmp(((struct stu*)e1)->name,((struct stu*)e2)->name); }int sort_by_age(const void* e1,const void* e2)//对整形的比较 {return ((struct stu*)e1)->age-((struct stu*)e2)->age; }int sort_by_weight(const void* e1,const void* e2)//对浮点型比较 {return ((struct stu*)e1)->weight-((struct stu*)e2)->weight; } void test_2()//对结构体进行排序 {struct stu s[3]={{"zhangsan",23,65.5},{"lisi",27,56.5},{"wangwu",24,64}};int sz=sizeof(s)/sizeof(s[0]);qsort(s, sz, sizeof(s[0]), sort_by_name);//对名字排序for(int i=0;i<sz;i++)//输出排序后的结果{printf("%s ",s[i].name);}printf("\\n");qsort(s, sz, sizeof(s[0]), sort_by_age);//对年龄排序for(int i=0;i<sz;i++){printf("%d ",s[i].age);}printf("\\n");qsort(s, sz, sizeof(s[0]), sort_by_weight);//对体重排序for(int i=0;i<sz;i++){printf("%.2f ",s[i].weight);}printf("\\n"); } int main() {test_1();test_2();return 0; }
🐰用冒泡排序类似实现qsort
qsort()的底层是快速排序,但是没有学过快速排序,可以使用冒泡排序来代替
#include<stdio.h> void swap(char* buf1,char*buf2,int width) //为什么不直接进行交换,而是交换每个字节的内容?这是因为这交换的不只是整形变量,这里还可以交换其它类型的变量{for(int i=0;i<width;i++){char temp=*buf1;*buf1=*buf2;*buf2=temp;buf1++;buf2++;} } void buble_sort(void* base,int sz,int width,int (*cmp)(const void*e1,const void*e2))//这里的函数指针可以方便调用各种类型比较,不同类型的变量比较,可以调用不同类型的比较函数 {int i=0,j=0;//sz个元素就有sz-1趟for(i=0;i<sz-1;i++){for(j=0;j<sz-1-i;i++){//两个元素的比较//arr[j] arr[j+1]if(cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)//为什么将base强制转化为(char*)呢?假如比较的是整形变量,我们将base转化为(char*),加上width(就是这里的整形变量的大小,4字节)就可以找到下个元素的地址,{//交换swap((char*)base+j*width,(char*)base+(j+1)*width,width);//然后把这个变量的地址传给交换函数}}} } int cmp_int(const void* e1,const void* e2)//对整形比较 {return *(int*)e1-*(int*)e2; } int main() {int arr[10]={2,3,4,5,6,7,1,9,13,10};int sz=sizeof(arr)/sizeof(arr[0]);buble_sort(arr,sz,sizeof(arr[0]),cmp_int);for(int i=0;i<sz;i++){printf("%d ",arr[i]);}return 0; }
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸