第13讲:深入理解指针(4)

1.回调函数

2.strcmp函数

3.qsort函数

1.回调函数

假设有函数A和函数B

将函数A的地址作为参数传给函数B,如果在函数B内通过函数A的地址调用函数A,那么函数A就叫回调函数。

2.strcmp函数

2.1strcmp的使用

参数:两字符串首元素的地址或两字符数组首元素地址。

返回值类型:返回值类型是整型

功能:比较的是字符的ASCLL码值,如果两字符串或字符数组的第一个字符相同,就会比较第二个字符,直到字符不同或遇到空字符,如果同时遇到空字符(\0),也就是两字符相等的时候,返回0,如果不同时遇到空字符,那么谁先遇到谁就比较小。(详情看上图)

所以,我们就可以利用strcmp函数比较字符串,再对其排序

2.2strcmp函数使用举例

前三个字符相同,比较到第4个字符,g的ASCLL码值大于f的ASCLL码值,返回一个正整数

前三个字符相同,arr1先遇到了空字符,arr1比较小,返回一个负整数

遇到空字符后,后面的将不再比较

比较完了字符数组内的所有元素还没有遇到'\0',接着访问,后面的情况就都是不确定的了。(越界访问)

当然,这种写法是不对的。

3.qsort函数

3.1qsort函数的使用

头文件:stdlib.h

功能:对数组元素进行排序

返回值:void

参数和参数类型:

参数1:数组首元素的地址,参数类型为void指针类型

参数2:数组元素的个数

参数3:数组每个元素在内存中的大小(同数组每个元素大小都一样,一般取首元素的大小)

参数4:一个函数的指针,该函数提供排序的方式,该函数由自己提供,我们记这个由自己提供的函数为A函数

函数A:

参数:两个参数类型都是const void*,qsort函数会将要比较的两个数据上传上去

返回值:当函数A返回正数时,会将两数据的位置交换

qsort函数实现排序的基本逻辑(以将一个整型数组的元素从小到大排序为例,假设元素有2个):qsort会将两元素的地址上传到函数A,在A内部比较,如果第一个元素较大,就返回一个正数,交换两元素的位置,如果第二个数较大,就返回0或负数,不进行任何操作,然后就排序完成了

我们将冒泡思想融入,就能实现多元素排序了(qsort的实现实际上用的使快速排序,但是qsort函数也是可以用冒泡排序理解和实现的)

qsort函数实现排序的基本逻辑(以将一个整型数组的元素从小到大排序为例,假设元素有N个):qsort会将第一个元素和第二个元素的地址传给函数A,在函数A内比较,如果第一个元素大于第二个元素,使函数A返回正数,交换两元素位置,否则返回0或负数,不进行任何操作,然后对第二个元素和第三个元素操作,直到操作完第N-1和第N个元素,就可以使最大的数排到最后面,完成一次冒泡,然后对剩下N-1个元素进行一样的处理,使第二大的元素排到最后面的前一位,以此类推。

题目1:将一个整型数组的元素排序

#include <stdio.h>
#include <stdlib.h>
int test(const void*p1,const void*p2)
{
	int* p1a = (int*)p1;
	int* p2a = (int*)p2;
	if (*p1a > *p2a)
		return 1;//交换
	else
		return 0;//不交换
}
int main()
{
	int arr[] = { 1,3,5,7,4,3,6,4,2,5,0 }, i;
	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), test);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
		printf("%d ", arr[i]);
	return 0;
}

void*类型的数据使不能解引用的,要先进行类型转换

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int test(const void*p1,const void*p2)
{
	return (*(int*)p1 - *(int*) p2);
}
int main()
{
	int arr[] = { 1,3,5,7,4,3,6,4,2,5,0 }, i;
	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), test);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
		printf("%d ", arr[i]);
	return 0;
}

这是优化后的写法:如果第一个元素较大,第一个元素和第二个元素的差也就是正数,直接返回第一个元素和第二个元素的差就可以了。如果第一个元素较小或两元素相等,第一个元素和第二个元素的差也就是负数或0,直接返回第一个元素和第二个元素的差就可以了。

综上,直接返回第一个元素和第二个元素的差就可以了。

题目二:排列数组的元素(元素是结构体)

现有一个数组,数组的元素是结构体变量,请根据结构体成员排列数组元素

1.根据年龄从小到大排列

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
struct stu
{
	int age;
	char name[15];
}arr[] = { {16,"zhansan"},{13,"lisi"},{15,"wangwu"},{11,"cuihua"},{18,"lihua"} };
int test(const void* p1, const void* p2)
{
	return (((struct stu*)p1)->age - ((struct stu*)p2)->age);
}
int main()
{
	int i;
	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), test);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i].age);
		printf("%s ", arr[i].name);
		putchar('\n');
	}
	return 0;
}

2.根据名字排序

要求:使用strcmp比较

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu
{
	int age;
	char name[15];
}arr[] = { {16,"zhansan"},{13,"lisi"},{15,"wangwu"},{11,"cuihua"},{18,"lihua"} };
int test(const void* p1, const void* p2)
{
	return (strcmp(((struct stu*)p1)->name , ((struct stu*)p2)->name));
}
int main()
{
	int i;
	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), test);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i].age);
		printf("%s ", arr[i].name);
		putchar('\n');
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

INUYACHA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值