「2」指针进阶——详解

news2024/9/29 9:27:33
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 

目录

🐰指向函数指针数组的指针(很少用,了解)

🐰回调函数(通过函数指针调用函数)

🐰快速排序

🌸冒泡排序

🌸qsort()

🐰用冒泡排序类似实现qsort


🐰指向函数指针数组的指针(很少用,了解)

#include<stdio.h>
void Add(int ,int)
{
    printf("%d\n",1+1);
}
void Sub(int ,int)
{
    printf("%d\n",1-1);
}
int main()
{
    int (*pf)(int,int)=Add;//函数指针
    int (*pfArr[4])(int,int)={Add,Sub};//函数指针数组
    int (*(*ppfArr)[4])(int,int)=&pfArr;//ppfArr就是指向函数的指针数组的指针
    return 0;
}

🐰回调函数(通过函数指针调用函数)

通过回调函数实现 两个操作数的加减乘除:
#include<stdio.h>
void Calc(int(*pf)(int,int))
{
    int x=0,y=0;
    printf("请输入两个操作数\n");
    scanf("%d %d",&x,&y);
    int ret=pf(x,y);
    printf("%d\n",ret);
}
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 menu(void)
{
    printf("****    两位数的计算器     ****\n");
    printf("****    1.Add   2.Sub   ****\n");
    printf("****    3.Mul   4.Div   ****\n");
    printf("****    0.exit          ****\n");
}
int main()
{

    int input=0;
    do
    {
        menu();
        printf("请选择\n");
        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("exit\n");
                break;
            default:
                printf("输入错误\n");
        }
    }while(input);
}

🐰快速排序

qsort是一个库函数,是用来排序(使用的快速排序的方法)
1.库函数里的,可以直接使用        2.可以排序任意类型的数据

🌸冒泡排序

在这里插入图片描述

 #include<stdio.h>

void Bubble(int arr[],int len)
{
    int i=0,j=0;
    for(i=0;i<len-1;i++)
    {
        for(j=0;j<len-1-i;j++)
        {
            if(arr[i]>arr[j+1])
            {
                int temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
}
void Print(int arr[],int len)
{
    for(int i=0;i<len;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
}
int main()
{
    int arr[]={3,2,1,5,7,8,9,0};
    int len=sizeof(arr)/sizeof(arr[0]);
    Bubble(arr,len);
    Print(arr,len);
}

🌸qsort()

qsort的原型:void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
void qsort (void* base//指向了待排序数组的第一个元素的地址
            , size_t num(无符号整形)//待排序的元素个数
            , size_t size(无符号整形)//每个元素的大小,单位是字节
            ,int (*compar)(const void*,const void*)//这里是一个函数指针,指向一个函数,这个函数可以比较2个元素的大小
            );
比较函数:就是函数指针campar指向的函数,因为使用qsort时,要自己定义比较函数,以下是常见的比较函数
比较整形变量时
int cmp_int(const void* e1, const void* e2)
{
 return *(int*)e1 - *(int*)e2;
}
比较浮点型变量时
int cmp_float(const void* e1, const void* e2)
{
 return (int)(*(float*)e1 - *(float*)e2);
}
比较字符串变量时
int cmp_str_size(const void* e1, const void* e2)
{
 return strcmp((char*)e1,(char*)e2);
}
比较字符串长度时
int cmp_str_len(const void* e1, const void* e2)
{
 return strlen((char*)e1)-strlen((char*)e2);
}
比较结构体变量时
int cmp_by_age(const void*e1, const void*e2)
{
 return (int)((stu*)e1)->weight - ((stu*)e2)->weight));
}

cmp函数的返回值:返回值<0(不进行置换),>0(进行置换),0(不进行置换)。记得返回的结果一定是整形的,如果不是需要强制转为整形的

‼️注:void*的指针不能解引用,也不能算术运算
下面是使用qsort排序整形变量和结构体变量的原码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int cmp_int(const void* e1,const void* e2)//对整形比较
{
    return *(int*)e1-*(int*)e2;
}

void test_1()
{
    int arr[]={2,3,4,5,6,7,1};
    int sz=sizeof(arr)/sizeof(arr[0]);//计算出数组下标,就不用手动去数有多少个元素了
    //这里需要提供一个比较函数,这个比较函数能够比较2个整数的大小
    //qsort默认为升序
    qsort(arr,sz,sizeof(arr[0]),cmp_int);
    for(int i=0;i<sz;i++)
    {
        printf("%d ",arr[i]);
    }
}
struct stu//定义了一个包含字符类型,整形,浮点型的结构体
{
    char name[20];
    int age;
    float weight;
};
int sort_by_name(const void* e1,const void* e2)//对字符串的比较
{
    return strcmp(((struct stu*)e1)->name,((struct stu*)e2)->name);
}

int sort_by_age(const void* e1,const void* e2)//对整形的比较
{
    return ((struct stu*)e1)->age-((struct stu*)e2)->age;
}

int sort_by_weight(const void* e1,const void* e2)//对浮点型比较
{
    return ((struct stu*)e1)->weight-((struct stu*)e2)->weight;
}
void test_2()//对结构体进行排序
{
    struct stu s[3]={{"zhangsan",23,65.5},{"lisi",27,56.5},{"wangwu",24,64}};
    int sz=sizeof(s)/sizeof(s[0]);
    qsort(s, sz, sizeof(s[0]), sort_by_name);//对名字排序
    for(int i=0;i<sz;i++)//输出排序后的结果
    {
        printf("%s ",s[i].name);
    }
    printf("\n");
    qsort(s, sz, sizeof(s[0]), sort_by_age);//对年龄排序
    for(int i=0;i<sz;i++)
    {
        printf("%d ",s[i].age);
    }
    printf("\n");
    qsort(s, sz, sizeof(s[0]), sort_by_weight);//对体重排序
    for(int i=0;i<sz;i++)
    {
        printf("%.2f ",s[i].weight);
    }
    printf("\n");
}
int main()
{
    test_1();
    test_2();
    return 0;
}

🐰用冒泡排序类似实现qsort

 qsort()的底层是快速排序,但是没有学过快速排序,可以使用冒泡排序来代替
#include<stdio.h>
void swap(char* buf1,char*buf2,int width)
//为什么不直接进行交换,而是交换每个字节的内容?这是因为这交换的不只是整形变量,这里还可以交换其它类型的变量

{
    for(int i=0;i<width;i++)
    {
        char temp=*buf1;
        *buf1=*buf2;
        *buf2=temp;
        buf1++;
        buf2++;
    }
}
void buble_sort(void* base,int sz,int width,int (*cmp)(const void*e1,const void*e2))//这里的函数指针可以方便调用各种类型比较,不同类型的变量比较,可以调用不同类型的比较函数
{
    int i=0,j=0;
    //sz个元素就有sz-1趟
    for(i=0;i<sz-1;i++)
    {
        for(j=0;j<sz-1-i;i++)
        {
            //两个元素的比较
            //arr[j] arr[j+1]
            if(cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)//为什么将base强制转化为(char*)呢?假如比较的是整形变量,我们将base转化为(char*),加上width(就是这里的整形变量的大小,4字节)就可以找到下个元素的地址,
            {
                //交换
                swap((char*)base+j*width,(char*)base+(j+1)*width,width);//然后把这个变量的地址传给交换函数
            }
        }
    }
}
int cmp_int(const void* e1,const void* e2)//对整形比较
{
    return *(int*)e1-*(int*)e2;
}
int main()
{
    int arr[10]={2,3,4,5,6,7,1,9,13,10};
        int sz=sizeof(arr)/sizeof(arr[0]);
        buble_sort(arr,sz,sizeof(arr[0]),cmp_int);
        for(int i=0;i<sz;i++)
        {
            printf("%d ",arr[i]);
        }
    return 0;
}

 🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/370947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Arduino 无刷电机控制教程】

【Arduino 无刷电机控制教程】 1. 概述2. 试验准备3. 实验原理4. Arduino 无刷电机控制 – 电路图4.1 实验组件4.2 用于 BLDC 电机控制的 Arduino 代码5. 实验验证5.1 电位计控制无刷电机速度5.2 电调校准在本教程中,我们将学习如何使用 Arduino 和 ESC 控制无刷电机。如果您想…

建议将com.alibaba:fastjson升级至1.2.83

问题 升级了gradle&#xff0c;改了文件存储位置&#xff0c;项目需要重新构建下载依赖文件&#xff0c;发现fastjson 1.2.66一直下载不下来一直卡在下载&#xff0c;就想着手动下载下试试&#xff0c;就去了mvnrepository网站找到fastjson时&#xff0c;发现了fastjson2 Note…

一文让你彻底了解Linux内核文件系统

一&#xff0c;文件系统特点 文件系统要有严格的组织形式&#xff0c;使得文件能够以块为单位进行存储。文件系统中也要有索引区&#xff0c;用来方便查找一个文件分成的多个块都存放在了什么位置。如果文件系统中有的文件是热点文件&#xff0c;近期经常被读取和写入&#xf…

数学不好,英语不行,非本专业,可以学IT吗?

很多小伙伴&#xff0c;都会问小青一些比较类似的问题。比如&#xff1a;不是计算机专业的&#xff0c;可以学编程吗&#xff1f;数学一直就不好&#xff0c;可以转行学IT吗&#xff1f;学编程开发&#xff0c;对英语的的要求会不会很高&#xff1f;01计算机不是计算机专业的&a…

C/C++开发,无可避免的内存管理(篇三)-规划好内存

一、用内存空间换效率 1.1 allocatoe类模板 在前面简述模板顺序容器时&#xff0c;就提到过&#xff0c;标准库中的 vector 类是通过预先分配额外内存以换取不不用每次添加元素都要重新分配内存和移动元素&#xff0c;而是将元素直接保存加入的预先分配的内存区域。在预先分配…

【Git】Git冲突与解决方法

目录 一、Git冲突如何产生&#xff1f; 二、解决Git冲突—手动修改冲突 【第一步】在 hot-fix 分支上增加如下代码&#xff0c;并且提交。 【第二步】在master 分支上同样的地方增加如下代码&#xff0c;并且提交。 【第三步】 我们现在在 master 分支上合并 hot-fix 分支&a…

慢雾:Discord 私信钓鱼手法分析

事件背景 5 月 16 日凌晨&#xff0c;当我在寻找家人的时候&#xff0c;从项目官网的邀请链接加入了官方的 Discord 服务器。在我加入服务器后立刻就有一个"机器人"(Captcha.bot)发来私信要我进行人机验证。这一切看起来相当的合理。我也点击了这个验证链接进行查看…

数据结构——顺序表讲解

作者&#xff1a;几冬雪来 时间&#xff1a;2023年2月25日 内容&#xff1a;数据结构顺序表内容讲解 目录 前言&#xff1a; 顺序表&#xff1a; 1.线性表&#xff1a; 2.什么是顺序表&#xff1a; 3.顺序表的概念和构成&#xff1a; 4.顺序表的书写&#xff1a; 1…

【Web逆向】万方数据平台正文的逆向分析(上篇--加密发送请求)—— 逆向protobuf

【Web逆向】万方数据平台正文的逆向分析&#xff08;上篇--加密发送请求&#xff09;—— 逆向protobuf声明一、了解protobuf协议&#xff1a;二、前期准备&#xff1a;二、目标网站&#xff1a;三、开始分析&#xff1a;我们一句句分析&#xff1a;先for循环部分&#xff1a;后…

Servlet笔记(11):Servletcontext对象

1、什么是ServletContext ServletContext是一个全局储存空间&#xff0c;随服务器的生命周期变化&#xff0c; Cookie&#xff0c;Session&#xff0c;ServletContext的区别 Cookie&#xff1a; 存在于客户端的本地文本文件 Session&#xff1a; 存在于服务器的文本文件&#…

今天我在朋友圈看到的新京报公众号一段文章&#xff1a;十三届全国人大&#xff08;过几天就任期结束&#xff09;在第五次会议&#xff08;2022年3月5日&#xff09;对证监会提了一条第6178号建议《关于严厉打击风水盲测股市动向的建议》。今天&#xff0c;证监会进行了收称答…

业务代码编写过程中如何「优雅的」配置隔离

思考 不同的处理方式 1.常规的处理方式&#xff0c;通过某种规则判断区分代码环境 // 获取环境标识 const env getCurrentEnv();if (env dev) {// do something } else if (env test) {// do something } else if (env prod) {// do something } 分析&#xff1a; 1.此种…

Linux 操作系统——查看/修改系统时区、时间、本地时间修改为UTC

文章目录1.背景描述2.知识储备3.解决步骤1. 查看当前时区2.修改设置Linux服务器时区3.复制相应的时区文件&#xff0c;替换系统时区文件&#xff1b;或者创建链接文件4. 查看和修改Linux的时间5. 硬件时间和系统时间的 相互同步1.背景描述 最近一个项目日期采用java8的LocalDa…

你在公司混的差,可能和组织架构有关!

原创&#xff1a;小姐姐味道&#xff08;微信公众号ID&#xff1a;xjjdog&#xff09;&#xff0c;欢迎分享&#xff0c;非公众号转载保留此声明。如果你接触过公司的面试工作&#xff0c;一定见过很多来自大公司的渣渣。这些人的薪资和职位&#xff0c;比你高出很多&#xff0…

Delphi RSA加解密(二)

dll开发环境: Delphi XE 10.1 Berlin exe开发环境: Delphi 6 前提文章: Delphi RSA加解密(一) 目录 1. 概述 2. 准备工作 2.1 下载DEMO程序 2.2 字符编码说明 3. Cryption.dll封装 3.1 接口概况 3.2 uPub.pas单元代码 3.3 uInterface.pas单元代码 3.4 特别注意 4. 主程序…

如何选择合适的数字隔离器

随着数字隔离器在工业和汽车应用中的日益普及&#xff0c;从众多可用选项中选择最适合您系统的器件可能会让人不知所措。除了这一挑战之外&#xff0c;大多数数字隔离器在设计时都考虑了特定的系统要求和应用&#xff0c;让您需要对无穷无尽的规格和功能进行分类&#xff0c;以…

C++ sting类(一)各类操作

1、 C语言中的字符串C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合程序设计的思想&#xff0c;而且底层空间需要用户自己管…

NEXUS 6P刷机安装Edxposed

刷机 abd等工具下载&#xff1a; https://developer.android.com/studio/releases/platform-tools?hlzh-cn 下载后配置环境变量 镜像下载&#xff1a; https://developers.google.com/android/images?hlzh-cn#angler Magisk下载 GitHub - topjohnwu/Magisk: The Magic M…

基于BP神经网络的衣服识别,BP神经网络详细原理,BP神经网络图像识别神经网络案例之19

目标 背影 BP神经网络的原理 BP神经网络的定义 BP神经网络的基本结构 BP神经网络的神经元 BP神经网络的激活函数&#xff0c; BP神经网络的传递函数 数据 神经网络参数 基于BP神经网络 性别识别的MATLAB代码 效果图 结果分析 展望 背影 人靠衣服马靠鞍&#xff0c;通过穿衣可…

Matlab字符串相关操作-拼接、格式化

常见的有三种方法&#xff1a;向量拼接、strcat函数和sprintf函数1、向量拼接在matlab中字符串本质上也是一个向量&#xff0c;可以通过矩阵运算来实现字符串的拼接&#xff0c;这里随便输入两个字符串a1和b1&#xff0c;用矩阵形式进行拼接&#xff1a;a1 I love;b1 Matlab…