库函数sqort的模拟实现
库函数sqort的原型
void my_sqort(void* base, size_t num, size_t width, int(*compare)(const void* e1,const void* e2))
- 该函数返回类型是void,我们只需要在sqort函数中排好序打印即可。
- 第一个参数base是需要排序的数据的首地址,因为该函数本身并不知道需要排什么类型的数据,所以类型是void,以便后续的强制类型转换。
- 第二个参数num需是要排序数据元素的个数,类型是无符号整型size_t。
- 第三个参数width是需要排序数据元素本身的宽度,单位为字节,类型是无符号整型size_t。
- 第四个参数是一个函数指针,该函数指针指向的函数的作用是来比较两个数据元素的大小。由于不同的数据类型不一样,所以只能用函数指针来调用对应的函数,到时候排序只需要传对应的函数就可以了。调用的函数的返回类型是int,它有两个参数e1和e2,这两个参数是需要排序的数据的两个元素,由于我们不希望这两个参数被改变,且后期对应的函数排序时,函数本身并不知道要排序什么类型的数据,还要强制类型转换成对应的类型,所以参数的类型都是const void*。
这里模拟用my_sqort函数模拟库函数sqort
主函数代码如下
int main()
{
//test1(); //比较整形数组
//test2(); //比较结构体成员姓名
test3(); //比较结构体成员年龄
return 0;
}
main函数中不同test函数代码如下
void test1()
{
int arr[] = { 1,2,3,5,9,8,7 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_sqort(arr, sz, 4, cmp_arr_int);
print(arr,sz);
}
void test2()
{
struct sta arr[] = { {"张三", 18, 20000153 },{"李四",19,20036548},{"王五",20,20207695} };
int sz = sizeof(arr) / sizeof(arr[0]);
my_sqort(arr, sz, sizeof(arr[0]), cmp_str_name);
}
void test3()
{
struct sta arr[] = { {"张三", 21, 20000153 },{"李四",19,20036548},{"王五",20,20207695} };
int sz = sizeof(arr) / sizeof(arr[0]);
my_sqort(arr, sz, sizeof(arr[0]), cmp_str_age);
}
排序函数my_sqort如下
void my_sqort(void* base, size_t num, size_t width, int(*compare)(const void* e1,const void* e2))
{
for (size_t i = 0; i < num; i++)
{
for (size_t j = 0; j < num - 1 - i; j++)
{
if (compare((char*)base + j * width, (char*)base + (j + 1) * width)>0)
{
_swap((char*)base + j * width , (char*)base + (j + 1) * width, width);
}
}
}
}
比较数据元素函数代码如下
//比较整形数组大小
int cmp_arr_int(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
//比较结构体的成员姓名大小
int cmp_str_name(const void* e1, const void* e2)
{
return strcmp(((struct sta*)e1)->name, ((struct sta*)e2)->name);
}
//比较结构体的成员年龄大小
int cmp_str_age(const void* e1, const void* e2)
{
return (*(struct sta*)e1).age -(*(struct sta*)e2).age;
}
交换函数-swap代码如下
void _swap(char* e1, char* e2,int width)
{
for (int i = 0; i < width; i++)
{
char temp = *e1;
*e1 = *e2;
*e2 = temp;
e1++;
e2++;
}
}
对于整形数组打印的函数print代码如下
void print(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
全代码如下
#include<stdio.h>
#include<string.h>
struct sta
{
char name[20];
int age;
int num;
}a[10];
void print(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
void _swap(char* e1, char* e2,int width)
{
for (int i = 0; i < width; i++)
{
char temp = *e1;
*e1 = *e2;
*e2 = temp;
e1++;
e2++;
}
}
void my_sqort(void* base, size_t num, size_t width, int(*compare)(const void* e1,const void* e2))
{
for (size_t i = 0; i < num; i++)
{
for (size_t j = 0; j < num - 1 - i; j++)
{
if (compare((char*)base + j * width, (char*)base + (j + 1) * width)>0)
{
_swap((char*)base + j * width , (char*)base + (j + 1) * width, width);
}
}
}
}
//比较整形数组大小
int cmp_arr_int(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
//比较结构体的成员姓名大小
int cmp_str_name(const void* e1, const void* e2)
{
return strcmp(((struct sta*)e1)->name, ((struct sta*)e2)->name);
}
//比较结构体的成员年龄大小
int cmp_str_age(const void* e1, const void* e2)
{
return (*(struct sta*)e1).age -(*(struct sta*)e2).age;
}
void test1()
{
int arr[] = { 1,2,3,5,9,8,7 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_sqort(arr, sz, 4, cmp_arr_int);
print(arr,sz);
}
void test2()
{
struct sta arr[] = { {"张三", 18, 20000153 },{"李四",19,20036548},{"王五",20,20207695} };
int sz = sizeof(arr) / sizeof(arr[0]);
my_sqort(arr, sz, sizeof(arr[0]), cmp_str_name);
}
void test3()
{
struct sta arr[] = { {"张三", 21, 20000153 },{"李四",19,20036548},{"王五",20,20207695} };
int sz = sizeof(arr) / sizeof(arr[0]);
my_sqort(arr, sz, sizeof(arr[0]), cmp_str_age);
}
int main()
{
//test1(); //比较整形数组大小
//test2(); //比较结构体成员姓名
test3(); //比较结构体成员年龄
return 0;
}
下面是运行结果展示
由于结果体打印繁琐,下面在调试中查看结构体的成员比较
- 排序整形数组
- 排序结构体的成员年龄
- 排序结构体的成员姓名