指针2(冒泡排序的使用,库函数中qsort排序函数的使用方法,void*的用法,编写一个自己的qsort排序函数,回调函数)

发布于:2023-01-04 ⋅ 阅读:(238) ⋅ 点赞:(0)

回调函数
首先利用冒泡排序将一个整形数组进行排序(降序)
void compare(int arr[],int sz)
{
    int i = 0;
    for (i = 0; i <= sz - 1; i++)
    {
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            int temp = 0;
            if (arr[j] < arr[j + 1])
            {
                int temp =arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
void print(int arr[],int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
}
int main()
{
    int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    compare(arr, sz);
    print(arr, sz);
    return 0;
}

掌握对于qsort(库函数中的比较函数)的使用
#include<stdlib.h>//引用sqrt函数需要引的头文件
/*
对于void*的用法:
void*类型的指针可以接收任意类型的地址
void*类型的指针不能进行解引用操作
void*类型的指针不能进行+-整数的操作
*/

int compare(const void* e1, const void* e2)//compare函数的固定书写格式
{
    return  (*(int*)e1 - *(int*)e2);//由于void*是空类型指针,所以需要进行强制类型转换之后才能进行比较
}
int compare1(const void* e1, const void* e2)//e1,e2为待比较的两个元素的地址
{
    return (int)(*(float*)e1 - *(float*)e2);
}
struct stu//创建一个结构体
{
    char name[20];
    int age;
    char schoolnumber[20];
};
#include<string.h>;
引用strcmp函数需要引的头文件
int compare2(const void* e1, const void* e2)
{
    对于字符串的比较,不能直接使用><=来直接比较,而应使用strcmp函数
    return strcmp(((struct stu*)e1)->name , ((struct stu*)e2)->name);
}
int compare3(const void* e1, const void* e2)
{
    
    return strcmp(((struct stu*)e1)->schoolnumber, ((struct stu*)e2)->schoolnumber);
}
int compare4(const void* e1, const void* e2)
{

    return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
void print(int* p,int sz)//自主创建的一个打印函数
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", p[i]);
    }
}
void print1(float* p, int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%f ", p[i]);
    }
}
void print2(struct stu* p, int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%s ", (p+i)->name);
    }
    printf("\n");
}
void print3(struct stu* p, int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%s ", (p + i)->schoolnumber);
    }
    printf("\n");
}
void print4(struct stu* p, int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", (p + i)->age);
    }
    printf("\n");
}
 
int main()
{
    int arr[] = { 0,5,2,8,9,4,5,3 }; 
    float arr1[] = { 1.0,5.0,3.0,4.0,7.0,8.0,6.0 };
    struct stu s[3] = { {"zhangsan",20,"2009010125"},{"lisi",25,"2009010120"},{"wangwu",18,"2009010230"} };//创建一个结构体变量数组s
    int sz = sizeof(arr) / sizeof(arr[0]);
    int sz = sizeof(arr1) / sizeof(arr1[0]);
    int sz = sizeof(s) / sizeof(s[0]);
    
    qsort(arr, sz, sizeof(arr[0]), compare);//qsort第一个参数是目标数组的起始位置(待排数组的首元素地址)
    print(arr, sz);
    qsort(arr1, sz, sizeof(arr1[0]), compare1);第二个参数是目标数组的元素个数
    print1(arr1, sz);
    qsort(s,sz,sizeof(s[0]),compare2);//第三个参数是数组每个元素的大小(字节数)
    print2(s, sz);
    qsort(s, sz, sizeof(s[0]), compare3);//第四个参数是比较目标数组的比较函数(自己设计)
    print3(s, sz);
    qsort(s, sz, sizeof(s[0]), compare4);
    print4(s, sz);
    return 0;
}

利用冒泡排序原理,创建一个自己的qsort函数,将所需要的值进行排序
void swap(char* x,char* y,int width)
/*
char类型的指针交换时只能交换一个字节因此计算机不知道是只需要交换一个字节还是需要交换传过来的x和y的总的字节数,
因此需要告诉计算机总共需要交换多少个字节,所以还需要将元素的宽度传进去。
*/

{
    int i = 0;
    for (i = 0; i < width; i++)
    {
        char temp = *x;
        *x = *y;
        *y = temp;
        x++;
        y++;
    }
}
int compare(const void* e1,const void* e2)
{
    return *(int*)e1 - *(int*)e2;//'*'号的优先级比'-'号高
}
int compare1(const void* e1, const void* e2)
{
    return (int)(*(float*)e1 - *(float*)e2);
}
struct tea//定义结构体的类型必须放在结构体函数之前,否则会出现函数参数未定义的情况
{
    int age;
    char name[20];

};
int compare2(const void* e1,const void* e2)
{
    return strcmp(((struct tea*)e1)->name, ((struct tea*)e2)->name);//->的优先级高于(struct tea*)
}
void my_qsort(void* arr,int sz,int width,int(*comp)(const void* e1, const void* e2))
由于arr是void*类型的指针,因此不清楚arr中每个元素的大小(字节),因此需要创建一个width来提示计算机
//int(*comp)(const void* e1, const void* e2)是一个函数指针,comp即为回调函数
//comp是一个函数,my_qsort也是一个函数,在my_qsort函数里面通过函数指针调用comp函数。此时comp函数则称为是回调函数
{
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            if (comp((char*)arr + j * width, (char*)arr + (j + 1)*width) >0)//引用compare函数并将待排数组排成降序
/*(char*)arr + j * width——将数组的首元素地址的指针强制转换成char*类型,并加上被比较的数组的元素类型的宽度(首次j=0,不加上宽度),以便后续能移动指针
(char*)arr + (j + 1)*width——将数组的首元素地址的指针强制转换成char*类型,并加上至少一个宽度*/

            {
                swap((char*)arr + j * width, (char*)arr + (j + 1)*width,width);//第一个和第二个参数为需要交换的两个元素,第三个参数为元素宽度
            }
        }
    }
}
void print(int* p,int sz)//打印整形
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", *(p + i));
    }
    printf("\n");
}
void print1(float arr1[], int count)//打印浮点型
{
    int i = 0;
    for (i = 0; i < count ; i++)
    {
        printf("%f ", arr1[i]);
    }
    printf("\n");
}

void print2(struct tea* t,int count1)//打印结构体里的元素
{
    int i = 0;
    for (i = 0; i < count1; i++)
    {
        printf("%s ", (t+i)->name);
    }
    printf("\n");
}
int main()
{
    int arr[] = { 2,5,7,3,4,6,1,9,8 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    float arr1[] = { 2.0,5.0,4.0,1.0,3.0,9.0,8.0,6.0,7.0 };
    int count = sizeof(arr1) / sizeof(arr1[0]);
    struct tea t[4] = { {26,"zhangsan"},{24,"lisi"},{30,"wangwu"},{28,"zhaoliu"} };//创建结构体变量数组t[],并将其进行初始化
    int count1 = sizeof(t) / sizeof(t[0]);
    my_qsort(arr,sz,sizeof(arr[0]),compare);
    print(arr,sz);
    my_qsort(arr1, count, sizeof(arr1[0]), compare1);
    print1(arr1, count);
    my_qsort(t, count1, sizeof(t[0]), compare2);
    print2(t, count1);
    return 0;
}

回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到