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;
}