深入理解指针(5)

发布于:2025-05-11 ⋅ 阅读:(23) ⋅ 点赞:(0)

目录

1 回调函数是什么?

2  qsort 使⽤举例

2.1 使⽤qsort函数排序整型数据

2.2 使⽤qsort排序结构数据

3 qsort函数的模拟实现


回调函数是什么?

如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。

//回调函数

int Add(int x, int y)
{
    return x + y;
}

void test(int (*pf)(int, int))
{
    int r = pf(10, 20);
    printf("%d\n", r);
}

int main()
{
    test(Add);

    return 0;
}

改写计算器代码 

void menu()
{
    printf("****************************\n");
    printf("****** 1. add  2. sub ******\n");
    printf("****** 3. mul  4. div ******\n");
    printf("****** 0. exit        ******\n");
    printf("****************************\n");
}

int Add(int x, int y)
{
    return x + y;
}

int Sub(int x, int y)
{
    return x - y;
}

int Mul(int x, int y)
{
    return x * y;
}

int Div(int x, int y)
{
    return x / y;
}

//函数的参数是函数指针,可以接收不同函数的地址
//接收的地址不同,调用的函数就不同
//这个函数根据参数的不同就能完成不同的功能
void Calc(int (*pf)(int, int))
{
    int x = 0;
    int y = 0;
    int r = 0;
    printf("请输入两个操作数:");
    scanf("%d %d", &x, &y);
    //r = (*pf)(x, y);
    r = pf(x, y);
    printf("%d\n", r);
}

int main()
{
    int input = 0;

    do
    {
        menu();
        printf("请选择:");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            Calc(Add);
            break;
        case 2:
            Calc(Sub);
            break;
        case 3:
            Calc(Mul);
            break;
        case 4:
            Calc(Div);
            break;
        case 0:
            printf("退出计算器\n");
            break;
        default:
            printf("选择错误,重新选择\n");
            break;
        }
    } while (input);

    return 0;
}

 qsort 使⽤举例

2.1 使⽤qsort函数排序整型数据

qsort是c语言中提供的一个排序函数

quick sort是基于快速排序算法思想的一种排序算法

qsort的好处:

1.现成的排序算法,学会了直接就能使用 ,不需要自己实现了

2.大部分的情况下效率都比冒泡排序高的

3. qsort函数可以排序任意类型的数据

我们自己实现过的冒泡排序函数,只能排序整型 

利用冒泡排序来演示

冒泡排序

void bubble_sort(int arr[], int sz)
{
    //1. 趟数
    //2. 一趟内部的比较:比较的对数
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1]) //交换
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

void print_arr(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
void test1()
{
    int arr[] = { 3,1,5,8,7,9,2,4,6,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    print_arr(arr, sz);
    bubble_sort(arr, sz);
    print_arr(arr, sz);
}
int main()
{
    test1();
    return 0;
}

使用qsort函数排序整型数据
void qsort(void* base, //是指针,指向了被排序数组的第一个元素
          size_t num, //base指向的被排序数组的元素个数
          size_t size, //base指向的被排序数组的元素的大小(长度),单位是字节
          int (*compar)(const void*, const void*)//是什么?函数指针,指针指向的函数是用来比较被排序数组中的两个元素的
          );
 

//cmp_int函数是用来比较两个整型数据的大小的
//p1指向了一个整型数据
//p2指向了一个整型数据
//升序
//int cmp_int(const void* p1, const void*p2)
//{
//    if (*(int*)p1 > *(int*)p2)
//        return 1;
//    else if (*(int*)p1 < *(int*)p2)
//        return -1;
//    else
//        return 0;
//}

//降序
//int cmp_int(const void* p1, const void* p2)
//{
//    if (*(int*)p2 > *(int*)p1)
//        return 1;
//    else if (*(int*)p2 < *(int*)p1)
//        return -1;
//    else
//        return 0;
//}

//升序
int cmp_int(const void* p1, const void* p2)
{
    return (*(int*)p1 - *(int*)p2);
}
//降序
//int cmp_int(const void* p1, const void* p2)
//{
//    return (*(int*)p2 - *(int*)p1);
//}

#include <stdlib.h>//qsort函数的头文件
//打印
void print_arr(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}


//测试qsort函数,排序整型数组
void test2()
{
    int arr[] = { 3,1,5,8,7,9,2,4,6,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    print_arr(arr, sz);
    //排序
    //使用qsort函数的程序员,就得自己写一个比较函数,来比较两个整型数据的大小
    qsort(arr, sz, sizeof(arr[0]), cmp_int);
    print_arr(arr, sz);
}
int main()
{
    test2();
    return 0;
}

2.2 使⽤qsort排序结构数据

介绍结构指针和结构体成员访问操作符 ->

//一
struct Stu
{
    char name[30];
    int age;
};

void test(struct Stu* ps)
{
    //printf("%s\n", (*ps).name);
    //printf("%d\n", (*ps).age);

    printf("%s\n", ps->name);//结构体成员访问操作符:->       结构体指针->成员名
    printf("%d\n", ps->age);
}

void test3()
{
    struct Stu s = { "zhangsan", 20 };
    //printf("%s\n", s.name);
    //printf("%d\n", s.age);
    test(&s);
}
int main()
{
    test3();
    return 0;
}

//二
//年龄
struct Stu
{
    char name[30];
    int age;
};
//按照年龄来比较
//p1指向了一个结构体变量
//p2指向了一个结构体变量
//int cmp_stu_by_age(const void* p1, const void* p2)
//{
//    return (*(struct Stu*)p1).age - (*(struct Stu*)p2).age;
//}

int cmp_stu_by_age(const void* p1, const void* p2)
{
    return (((struct Stu*)p1)->age - ((struct Stu*)p2)->age);
}

//打印
void print_stu(struct Stu arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%s: %d\n", arr[i].name, arr[i].age);
    }
    printf("\n");
}

//测试qsort函数排序结构体数据
void test4()
{
    struct Stu arr[] = { {"zhangsan", 20},{"lisi", 38},{"wangwu", 18} };
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
    print_stu(arr, sz);
}
int main()
{
    test4();
    return 0;
}

//三
//名字
//strcmp的头文件#include <string.h>
struct Stu
{
    char name[30];
    int age;
};
//两个字符串在比较大小的时候,不能使用> >= < <= == !=
//应该使用strcmp()
int cmp_stu_by_name(const void* p1, const void* p2)
{
    //return strcmp(((struct Stu*)p2)->name, ((struct Stu*)p1)->name);//降序
    return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);//升序
}
//打印
void print_stu(struct Stu arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%s: %d\n", arr[i].name, arr[i].age);
    }
    printf("\n");
}
//测试qsort函数排序结构体数据
void test5()
{
    struct Stu arr[] = { {"zhangsan", 20},{"lisi", 38},{"wangwu", 18} };
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
    print_stu(arr, sz);
}
int main()
{
    test5();
    return 0;
}

qsort函数的模拟实现

使⽤回调函数,模拟实现qsort(采⽤冒泡的⽅式)。

//一
//升序
int cmp_int(const void* p1, const void* p2)
{
    return (*(int*)p1 - *(int*)p2);
}

void Swap(char* buf1, char* buf2, size_t width)
{
    int i = 0;
    char tmp = 0;
    for (i = 0; i < width; i++)
    {
        tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}

//排序任意类型的数据 - 泛型编程
//但是底层还是冒泡排序的算法思想
void bubble_sort2(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{
    //1. 趟数
    //2. 一趟内部的比较:比较的对数
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            //if (arr[j] > arr[j + 1]) //交换
            if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                //交换arr[j], arr[j + 1]
                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
            }
        }
    }
}
//打印
void print_arr(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
void test6()
{
    int arr[] = { 3,1,5,8,7,9,2,4,6,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    print_arr(arr, sz);
    bubble_sort2(arr, sz, sizeof(arr[0]), cmp_int);
    print_arr(arr, sz);
}
int main()
{
    test6();
    return 0;
}

//二
//年龄
struct Stu
{
    char name[30];
    int age;
};
void Swap(char* buf1, char* buf2, size_t width)
{
    int i = 0;
    char tmp = 0;
    for (i = 0; i < width; i++)
    {
        tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}
int cmp_stu_by_age(const void* p1, const void* p2)
{
    return (((struct Stu*)p1)->age - ((struct Stu*)p2)->age);
}


//排序任意类型的数据 - 泛型编程
//但是底层还是冒泡排序的算法思想
void bubble_sort2(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{
    //1. 趟数
    //2. 一趟内部的比较:比较的对数
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            //if (arr[j] > arr[j + 1]) //交换
            if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                //交换arr[j], arr[j + 1]
                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
            }
        }
    }
}
//打印
void print_stu(struct Stu arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%s: %d\n", arr[i].name, arr[i].age);
    }
    printf("\n");
}

void test7()
{
    struct Stu arr[] = { {"zhangsan", 20},{"lisi", 38},{"wangwu", 18} };
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort2(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
    print_stu(arr, sz);
}


int main()
{
    test7();
    return 0;
}

//三
//名字
struct Stu
{
    char name[30];
    int age;
};
void Swap(char* buf1, char* buf2, size_t width)
{
    int i = 0;
    char tmp = 0;
    for (i = 0; i < width; i++)
    {
        tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}
//两个字符串在比较大小的时候,不能使用> >= < <= == !=
//应该使用strcmp()
int cmp_stu_by_name(const void* p1, const void* p2)
{
    return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}

//排序任意类型的数据 - 泛型编程
//但是底层还是冒泡排序的算法思想
void bubble_sort2(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{
    //1. 趟数
    //2. 一趟内部的比较:比较的对数
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            //if (arr[j] > arr[j + 1]) //交换
            if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                //交换arr[j], arr[j + 1]
                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
            }
        }
    }
}
//打印
void print_stu(struct Stu arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%s: %d\n", arr[i].name, arr[i].age);
    }
    printf("\n");
}

void test8()
{
    struct Stu arr[] = { {"zhangsan", 20},{"lisi", 38},{"wangwu", 18} };
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort2(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
    print_stu(arr, sz);
}


int main()
{
    test8();
    return 0;
}


网站公告

今日签到

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