指针传2(续集)

news2025/1/11 10:07:12

近期的天气是真的冷啊,老铁们一定要照顾好自己呀,注意防寒保暖,没有你们我怎么活啊!

上次的指针2的末尾,给大家分享了两个有趣的代码,今天就先来讲一讲那两个代码:

两个有趣的代码:

1  ( *  (   void  (*)    (  )   )   ) ( ); 
相同颜色的就是对应的一对括号,我们从里面看着出来,void  (*)  (  )这是一种指针类型吧,然后就是(   void  (*)    (  )   )   表示将0地址强制转换为函数指针类型,像我们之前写的(int)3.14这中就是强制类型转换,之后还剩下(*)(),这个不就是函数的调用吗?所以这是一次函数调用,将整数值0强制类型转换成一个函数地址,这个函数没有参数,返回类型为void;
去调用0地址处的函数.
void (*signal (int , void(*)(int) ) ) (int );
我们还是从里面分析着出来,首先看 signal (int , void(*)(int),这不就是一个函数吗?里面有两个参数,第一个是int类型,第二个是函数指针类型,该指针指向的函数参数是int,返回类型是void,signal函数的返回类型是这种类型的void(*)(int)函数指针,该指针指向的函数参数是int,返回类型是void,这是函数的声明!

函数指针数组:

函数指针数组是一个数组,其元素都是指向函数的指针。它的定义形式如下:

返回类型 (*指针数组名称[元素个数])(参数1类型, 参数2类型, ...);


其中,返回类型是函数的返回类型,指针数组名称是一个合法的标识符,元素个数是指针数组中元素的个数。参数类型是函数的参数类型。

例如,定义一个包含3个元素的函数指针数组,每个元素都指向返回类型为int,参数类型为int的函数,可以如下定义:
int (* PArray[3] )  (int);

PArray先和 [] 结合,说明 PArray是数组,数组的内容是 int (*)(int) 类型的函数指针。

这样,PArray就是一个包含3个元素的函数指针数组,每个元素都是指向返回类型为int,参数类型为int的函数的指针。

函数指针数组的使用:
我们编写计算器的实现:
先看看第一种方法:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

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 mune(void)
{
	printf("************************\n");
	printf("*****1,加法运算 ********\n");
	printf("*****2,减法运算 ********\n");
	printf("*****3,乘法运算 ********\n");
	printf("*****4,除法运算 ********\n");
	printf("*****0,退出计算 ********\n");
	printf("************************\n");

}
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;

	do
	{
		mune();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
		    ret = Add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
		    ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf("退出计算器\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
	
	return 0;
}

这种方法相信大家都会的吧,就是我们前面知识的应用,就不和大家细说了。上面我们看见重复的代码太多了,而且我们以后想实现其他的运算就会变得很麻烦。


上述的方法,我们可不可以把它们进行封装到另一个函数里面呢,通过函数指针找到相应的函数:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int input = 0;
int x = 0;
int y = 0;
int ret = 0;

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 mune(void)
{
	printf("************************\n");
	printf("*****1,加法运算 ********\n");
	printf("*****2,减法运算 ********\n");
	printf("*****3,乘法运算 ********\n");
	printf("*****4,除法运算 ********\n");
	printf("*****0,退出计算 ********\n");
	printf("************************\n");

}

void calc( int(*pf)(int, int))//函数指针
{
	printf("请输入两个操作数:\n");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}
int main()
{
	do
	{
		mune();
		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("退出计算器\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
	
	return 0;
}

我们来看看运行效果:


我们可不可以把这些函数放在一个数组里面呢,因为这些函数都是这一大类的吧,弄一个函数指针数组,然后根据输入去调用相应的函数:

int (*parr[5]) (int, int) = { NULL,Add,Sub,Mul,Div };

前面加上一个空指针,这样我们在输入数字的时候就可以找到相应的函数(数组的下标是从0开始的)!

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;

	do
	{
		mune();
		printf("请选择:\n");
		scanf("%d", &input);
		int (*parr[5]) (int, int) = { NULL,Add,Sub,Mul,Div };
		//这里的函数指针数组我们称为转移表
		
		
			if (input == 0)
			{
				printf("退出计算器\n");
				
			}
			else if(input>=1 && input<=4)
			{
			    printf("请输入两个操作数:\n");
			    scanf("%d %d", &x, &y);
		        ret = parr[input](x, y);
			    printf("%d\n", ret);
			    
			}
			else
			{
				printf("输入错误,请重新输入!\n");
			
			}
		
	} while (input);

	return 0;
}

这样我们是不是就大大减少了我们的代码量了,而且如果想加上其他的方法,加在数组里面就可以了,但这只是其中一部分代码哈,前面的方法我没有写上。

好了,今天就到这里了,明天见哦,不要太想我哟!😊😊😊


 

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

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

相关文章

Pandas 将DataFrame中单元格内的列表拆分成单独的行

使用 explode 函数 import pandas as pddata {month: [1, 2],week: [[i for i in range(2)], [i for i in range(3)]]} df pd.DataFrame(data) print(df)df df.explode(week) print(df)

Spring3新特性:graalvm打包Springboot+Mybatis

Spring3新特性 graalvm打包SpringbootMybatis 项目源代码 https://github.com/cmdch2017/SpringNative_Graalvm_Mybatis 如何安装与运行 安装graalvm与配置环境 首先安装步骤参考这篇博客 https://blog.csdn.net/weixin_38943666/article/details/129505945 其次如何处理…

【Python大数据笔记_day10_Hive调优及Hadoop进阶】

hive调优 hive官方配置url: Configuration Properties - Apache Hive - Apache Software Foundation hive命令和参数配置 hive参数配置的意义: 开发Hive应用/调优时&#xff0c;不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率&#xff0c;或帮助定位问…

图像生成colab集合

不过colab会做检测&#xff0c;一般文生图算法是基本很难跑起来的。 https://github.com/camenduruhttps://github.com/camenduru这哥们有很多colab。 1.stable-diffusion-webui https://colab.research.google.com/drive/1Iy-xW9t1-OQWhb0hNxueGij8phCyluOh#scrollTow3KNZ-…

变长子网划分问题的二叉树解法

计网的变长子网划分、计组的变长操作码划分、数据结构的哈夫曼编码&#xff0c;都是前缀编码的本质&#xff08;变长操作码的二叉树解法我还在琢磨中&#xff09; 【二叉树解法】每条从叶结点到根节点的路径上有且只有一个被分配的结点&#xff1a; 【例】现将一个IP网络划分成…

redis运维(十)列表

一 列表 强调&#xff1a; 知道原生redis具备的能力,以便后续API调用 ① 基础概念 备注&#xff1a; 单个list最多2^32-1个元素 列表操作常用命令,涉及&#xff1a;CURD ② lpush 左插入 说明&#xff1a; 如果key不存在就会初始化,否则就是插入元素备注&#xff1a; l…

C++ string类(一)

1.C语言中的字符串 C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符 OOP(Object Oriented Programming)的思想&#xff0c;而且…

Java后端工程师有福啦,CSDN里找到宝藏

目录 一、说明 二、操作步骤 一、说明 CDSN也有系统的java学习资料&#xff0c;有事无事翻翻挺好。 二、操作步骤 1、在CSDN首页顶端左边&#xff0c;点【学习】 2、在【学习】的页面&#xff0c;往下滑&#xff0c;找到【职业路线】 3、java后端工程师【入门版】【进阶版】…

WhatsApp账号被封?看看是不是你的原因!

WhatsApp经常封号是一个难题&#xff0c;这一篇将为你详细介绍WhatsApp封号原因&#xff0c;以及如何防封。 封号原因 首先我们分情况来判定封号原因&#xff0c;WhatsApp封号一般有以下几种情况&#xff1a; 1、一注册就封 许多小伙伴账号刚注册什么都没动&#xff0c;就遭…

Pr怎么消除人声?三个方法解决!

在一些情况下&#xff0c;消除人声可以保护个人隐私。例如&#xff0c;在公共场所录制视频或音频时&#xff0c;如果不需要记录人声&#xff0c;可以通过技术手段消除人声&#xff0c;以保护个人隐私和信息安全。下面就向大家介绍三种方法详细的操作步骤。 方法一&#xff1a;使…

会说话,情商高:职场人士必看的情商口才提升攻略

在职场上&#xff0c;口才和情商是非常重要的软实力。能言善辩&#xff0c;与人交流得心应手&#xff0c;往往可以帮助我们更好地完成工作任务&#xff0c;并获得更多的机会和提升。那么&#xff0c;如何才能培养出好的口才和高情商呢?本文将从以下几个方面给大家提供一些建议…

Python递归函数的定义和几个小例子

大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 递归函数 &#xff08;1&#xff09;什么是递归函数&#xff1f; 我们都知道&#xff0c;一个函数可以调用其他函数。如果这个函数在内部调用它自己&#xff0c;那么这个…

Unity - Cinemachine

动态获取Cinemachine的内部组件 vCam.GetCinemachineComponent<T>() 动态修改Cinemachine的Transposer属性 var vCamComp transfrom.GetComponent<CinemachineVirtualCamera>(); var transposerComp vCamComp.GetCinemachineComponent<CinemachineTransposer&…

使用drawio的图层构建更强大的图表

drawio中使用图层 drawio是一款强大的图表绘制软件&#xff0c;支持在线云端版本以及windows, macOS, linux安装版。 如果想在线直接使用&#xff0c;则直接输入网址draw.io或者使用drawon(桌案), drawon.cnhttps://www.drawon.cn?useSourcecsdn内部完整的集成了drawio的所有功…

遇见未来的你——过程中真是苦了你妈妈

目录 一、背景介绍二、思路&方案三、过程1.你给你妈妈增加的体重负担2.你给你妈妈增加的起夜负担3.凌晨6点你非常活跃吓坏爹妈4.凌晨3点你又调皮的让我和妈妈用仪器与你互动5.经历&#xff0c;都在积攒未来相遇的泪湿眼眶 四、总结 一、背景介绍 十年前&#xff0c;你米爷…

CI/CD 持续集成与持续交付(1)

git Git git使用 [rootserver1 ~]# yum install -y git [rootserver1 ~]# mkdir demo [rootserver1 ~]# cd demo/初始化版本库 [rootserver1 demo]# git init查看状态 [rootserver1 demo]# git status [rootserver1 demo]# git status -s #简化输出[rootserver1 demo]# echo…

JS进阶——构造函数数据常用函数

1、深入对象 1.1 创建对象三种方式 1.1.1 利用对象字面量创建对象 1.1.2 利用new Object创建对象 1.1.3 利用构造函数创建对象 1.2 构造函数 构造函数&#xff1a;是一种特殊的函数&#xff0c;主要用来初始化对象 使用场景&#xff1a;常规的{...}语法允许创建一个对象。…

spring-boot-maven-plugin插件 —— 默认打包配置

创建 Spring Boot 应用&#xff0c;默认会添加 Maven 插件&#xff1a;spring-boot-maven-plugin。如果项目结构比较简单&#xff0c;可以不用额外配置&#xff0c;使用默认的编译打包就可以。 执行 maven 打包命令时会自动触发 spring-boot-maven-plugin 插件的 repackage 目…

面向面试学习,全网最齐全的软件测试面试题(含答案)

做测试的&#xff0c;我整理的真的很用心了&#xff0c;能找的新鲜面经都找了。 一面 1. 自我介绍 2. 面向对象的三种特性 集成用到了哪些特性 多态的具体使用场景 设计模式中的多态体现&#xff08;手撕&#xff09; 封装&#xff1a;将属性私有化&#xff1b;封装的意义&a…

Vue路由 replace属性 控制浏览记录不能前进或后退

默认是push模式 表示页面一直增加&#xff0c;用户可以操作返回上一个页面 replace 模式 <router-link replace :to"{path:/user,query:{ id:123,age:666 }} ">跳转用户</router-link><!--replace true表示浏览器不能后退浏览记录-->