回调函数和qsort,strcmp函数

有任何不懂的问题可以评论区留言,能力范围内都会一一回答

1.回调函数是什么?
回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

我们拿qsort函数举个例子

qsort函数的类型是

void qsort (void* base, size_t num, size_t size,
            int (*compar)(const void*,const void*));

void* base

指向要排序的数组的第一个对象的指针,将其转换为 .void*

size_t num

所指向的数组中的元素数。
是无符号整数类型。

size_t size 

数组中每个元素的大小(以字节为单位)。
是无符号整数类型。

int (*compar)(const void*,const void*)

指向比较两个元素的函数的指针。
重复调用此函数以比较两个元素。它应遵循以下原型:

也就是我们要自己写一个函去作为比较标准

当p1指向的元素比p2大时返回一个大于0的值

当p1指向的元素比p2小时返回一个小于0的值

当p1指向的元素比p2相等时返回一个等于0的值

qsort默认排列的是升序

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int comparation (const void*a, const void*b);
void print(void* c,int sz);
int main(void) {
	int arr[] = { 1,23,42,32,13312,2323,323,123 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), comparation);
	print(arr,sz);
	return 0;
}
int comparation(const void*a, const void*b) {
	return (*(int*)a-*(int*)b);
}
void print(void* c,int sz) {
	for (int i = 0; i < sz; i++)
{ 
	printf("%d\n", *((int *)c + i));
}
}

如上图我们在使用qsort函数的时候我们需要写一个函数作为比较标准

这个标准我们可以自己写,比如把上面的return (*(int*)a-*(int*)b);改成return (*(int*)b-*(int*)a);

我们就可以把qsort变成一个排列降序的函数

但是这里需要注意qsort函数和我们自己编写的函数的类型是确定的,

qosrt函数类型必须是

void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));

我们自己写的比较原则的函数类型必须是int (*compar)(const void*,const void*)

但是这个地方的void*是为了方便我们接收不同类型的数据,但是void*的数据无法直接使用必须强制转换成其它类型才能使用。

那么思考一下,字符串如何比较呢?字符串可不能像整数类型一样直接比较(> < <= >= = !=都无效),因此这个地方我们必须调用一个用来比较字符串的函数strcmp

strcmp比较的不是字符串的长度而是对应字符的大小

strcmp函数的头文件是#include <string.h>

函数定义 :int strcmp(const char *str1, const char *str2);
这里的 const char* 表示两个参数 str1 和 str2 都是指向字符的指针,并且这些字符都以空字符'\0'结尾。(\0的ASCII码值是0)

函数功能 :
strcmp函数会从两个字符串的首地址开始,逐个比较它们对应位置的字符的ASCII码值,直到遇到不同的字符或者其中一个字符串结束。如果 str1 小于 str2 ,则函数返回一个负值;如果两个字符串相同,函数返回0;如果 str1 大于 str2 ,则函数返回一个正值。

回调函数本质上是在一个函数中调用宁外一个函数,如上面那段代码中,我们在qsort函数中调用了comparation这个函数,comparation就是回调函数。

### qsort 中 `cmp` 函数的用法 在 C 语言标准库 `<stdlib.h>` 提供的功能中,`qsort` 是一种快速排序算法的实现。它允许用户通过自定义比较函数来指定如何对数组中的元素进行排序[^1]。 #### 参数说明 `qsort` 的原型如下所示: ```c void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); ``` 其中参数解释为: - `base`: 被排序数组的起始地址。 - `nmemb`: 数组中元素的数量。 - `size`: 单个元素所占字节数。 - `compar`: 用户提供的用于比较两个元素大小的回调函数指针。 #### 自定义比较函数 `cmp` 函数是一个指向比较函数的指针,其签名应遵循以下形式: ```c int compar(const void* a, const void* b); ``` 该函数接收两个指向待比较数据项的指针作为输入,并返回一个整数值表示它们之间的关系。具体规则如下: - 如果第一个参数小于第二个,则返回负数; - 若两者相等则返回零; - 当前者大于后者时需返回正数[^2]。 下面给出几个具体的例子展示不同类型的数组是如何利用这个机制完成升序排列操作的: #### 整型数组示例 对于简单的整数类型来说,可以直接强制转换回原生类型来进行运算处理。 ```c #include <stdio.h> #include <stdlib.h> // 定义比较函数 int compare_ints(const void* a, const void* b){ int arg1 = *(const int*)a; int arg2 = *(const int*)b; if(arg1 < arg2) return -1; else if (arg1 > arg2) return 1; else return 0; } int main(){ int numbers[] = {4, 8, 2, 7, 9}; size_t count = sizeof(numbers)/sizeof(numbers[0]); printf("Before sorting:\n"); for(size_t i=0;i<count;i++)printf("%d ",numbers[i]); putchar('\n'); // 调用qsort并传入compare函数 qsort(numbers,count,sizeof(int),compare_ints); printf("After sorting:\n"); for(size_t i=0;i<count;i++)printf("%d ",numbers[i]); putchar('\n'); } ``` #### 字符串数组示例 当涉及到字符串这样的复杂结构体成员变量时,可以借助C标准库里的strcmp辅助我们编写更加简洁明了的逻辑表达式。 ```c #include <string.h> /* For strcmp */ #include <stdio.h> #include <stdlib.h> /* 假设有一个字符串数组需要按字母顺序排序 */ char *strings[]={"banana","apple","pear","orange"}; static int cmpstrp(const void **a,const void **b){ return strcmp(*(char**)a ,*(char**)b ); } int main() { char *(*sp)[5]=&strings;//注意这里是指向指针的指针 puts("Unsorted:"); for(unsigned int i=0;i<4;++i){puts(strings[i]);} qsort((void *)sp,4,sizeof(char *),cmpstrp); puts("\nSorted:"); for(unsigned int j=0;j<4;++j){puts(strings[j]);} } ``` 以上展示了两种常见场景下如何正确设置以及调用相应的比较器以满足实际需求的情况介绍完毕之后再来看一些额外需要注意的地方吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值