深入理解并打败C语言难关之一————指针(5)(最终篇)

前言:

  仔细一想,小编已经把指针的大部分内容都说了一遍了,小编目前有点灵感枯竭了,今天决定就结束指针这一大山,可能很多小编并没有提到过,如果有些没说的小编会在后续博客进行补充道,不多废话了,下面让我们开启今天的指针之旅吧!


目录:

1.函数指针数组

1.1.函数指针数组是什么

1.2.函数指针数组的应用

2.sizeof操作符和strlen函数的辨析

2.1.sizeof操作符

2.2.strlen函数

2.3.二者的比较

3.本节代码展示


正文:

1.函数指针数组

1.1.函数指针数组是什么

  前面我们已经学习了函数指针,数组指针,指针数组等内容 ,看到这读者朋友已经很疑惑了,居然还有函数指针数组这个东西,同样的,我们类比一下,存放着整型的是整型数组,存放指针的是指针数组,以此类推,存放着函数指针的数组,自然就是函数指针数组了,所以,这个很长的玩意就是一个数组,不过存放的内容是函数指针罢了,我们需要学会其的创建方式,我们先把代码放到下面供读者阅读:

int (*p1[3])   ();

  首先,p1会先和[]进行结合,表示这个是一个数组,它的类型就是int (*) ()函数指针类型,所以它存放的类型是函数指针,其实这个稍微有点小绕,所以小编决定同样也用图文的方式来给读者朋友们进行更好的解释:

  为了让各位区分一些指针的名称,小编下面整理了前几篇博客写过的一些指针或者数组来让大家区分:

1.指针数组:

int *p1[3];  //中括号里面的个数看题目,这里为了好看统一用3

2.数组指针(和1进行区分):


int (*p2)[3];

3.函数指针:

int (*p3)( )

4.函数指针数组:

int (*p4[])()  //这个对比下来应该是最复杂的了纯纯

  以上便是小编所说过的一些名称,这些要记住,其中前三个都分别放在了小编写过的(3)和(4)里面,感兴趣的读者朋友可以去看看(下面放上了想关链接):深入理解并打败C语言难关之一————指针(3)-CSDN博客 深入理解并打败C语言难关之一————指针(4)-CSDN博客

  既然我们已经讲完了函数指针数组如何进行创建,那么我们下面就要进行应用了,对于其的应用我们用简易计算机为例子,下面让我们进入下一环节,应用! 

1.2.函数指针数组的应用  

  我相信各位学过了前面的知识,已经会使用了函数和一些重要的语句,那么我们可以通过用这些知识来制作一个简易的计算机(仅仅针对整型),下面我们先来一个不用函数指针数组的简易计算机:

  计算机小编相信读者朋友们都用过,里面的功能有很多,下面我们就以正常算法的加减乘除为例子来进行代码的写,首先我们要先有着菜单页,这个可以模仿小编之前写过的扫雷游戏的菜单页,下面直接代码展示:

void menu()
{
	printf("***********简易计算机************\n");
	printf("*****1.加法***********2.减法*****\n");
	printf("*****3.除法***********4.乘法*****\n");
	printf("*****0.退出**********************\n");
	printf("**********************************\n");
	printf("*********************************\n");
}

  做完菜单后,之后我们就要进入选择环节了,这部分内容其实和扫雷很像,但为了考虑部分读者朋友没有看过那篇文章,小编再来说一下,首先我们可以选用do while语句来一直循环,因为这个语句总会先循环一次在判定条件,之后我们再用switch语句来判定想选哪个选项,之后我们在每次的条件下开始输入我们想要的数,然后进行函数的传参,下面是代码展示:

int main()
{
	menu();             //对于菜单函数的引用
	int i = 0;             //这一个是负责选哪一个运算方式的
	int a = 0;               //这一个和下面那个都是要进行运算的数
	int b = 0;
	do                    //进入do while 循环(先循环一次然后看循环条件)
	{
		printf("请选择你想要的算法:");                //这个是让你选算法的
		scanf("%d", &i);                      //这个是要输入的字符
		switch (i)                    //这一些跟菜单上数字对应的方式一一对应
		{
		case 0 :                      
			printf("好的下次光临\n");
			break;
		case 1 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int c = Add(a, b);
			printf("%d\n", c);
			break;
		case 2 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int d = div(a, b);
			printf("%d\n", d);
			break;
		case 3 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int f = mul(a, b);
			printf("%d\n", f);
			break;
		case 4 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int h = mul(a, b);
			printf("%d\n", h);
			break;
		default :
			printf("您选错了请重新选择:");
			break;
		}
	} while (i);
	return 0;
}

  然后我们就要撰写函数部分了,这部分的内容其实很简单,就是对照着自己想要的算法传参就好了,下面直接展现代码:

int Add(int x, int y)
{
	return x + y;
}
int sub(int x, int y)
{
	return x - y;
}
int div(int x, int y)
{
	return x / y;
}
int mul(int x, int y)
{
	return x * y;
}

   之后我们就写完了这个代码,其实乍一看,这么写是很正常的,但是如果仔细一看,发现其实这个代码是很复杂的,首先它的代码量是很复杂的,这个是可以很快看出来的,并且这个代码感觉有的部分显得很赘余,就比如每次输两个数,光这个操作就已经浪费了很多行了,所以我们可以试想一下,可不可以通过一个总函数,这个函数就已经负责了两个数的输入已经算法的选择,每次我们直接通过调用这个函数就好了,所以我们通过调用函数指针的方式就可以做到对这个代码的优化,下面是这个代码的第一次优化:

void oay(int(*p)(int x, int y))        //这里是通过在函数里面调用函数来实现
{        //此时上面这个函数里面放置着被调用的算法,可以看作函数指针的一个应用
	int a = 0;
	int b = 0;
	printf("请选择您想要运算的两个数:");
	scanf("%d %d",&a ,&b );
	int len = (*p)(a, b);
	printf("%d\n", len);
}

  此时已经让这个代码做到第一次优化了,此时这个优化做到了对于每次选择一个算法都要写一遍scanf的不足,这里其实后者函数是由名字的,这个可以叫做回调函数!不过,此时这个算法其实还有可以提升的空间的,就比如,我们可以利用我们刚学的函数指针数组的内容,咱们把每个算法函数的指针放到函数指针数组里面吗,然后通过输入算法来调用数组中的元素从而调用想要的算法,此时我们仅仅需要用到if语句判断我们所选择的算法是否是我们数组内部就好,废话不多说,下面是代码展示:

int main()
{
	menu();
	int i = 0;
	int a = 0;
	int b = 0;
	int(*p[5]) (a,b) = {0,add,sub,div,mul};      //md函数指针数组的名字别写错了
	do
	{
		printf("请选择您想要的算法:");
		scanf("%d", &i);
		if (i <= 4 && i >= 1)
		{
			printf("请输入您想要的数字:");
			scanf("%d %d", &a, &b);
			int len = (*p[i])(a, b);         //这相对于函数指针数组的数进行引用了,
			printf("%d\n", len);
		}
		else if (i == 0)
		{
			printf("期待您的下次游玩");
			break;
		}
		else
		{
			printf("您输错了请重新输入:");
		}
	} while (i);
}

  这个就是这个代码最主要的优化,可能很多人看了都会是下面这个表情:

   所以算法是有千万种的,一个题目往往可以有很多的算法,各位读者朋友们一定要学会举一反三,这对于后面编程的学习有很大的帮助,另外其实最后一个代码还是有个好名字的,它叫做转移表!下面不多废话,进入本节的一个小重点,sizeof操作符与strlen函数的辨析!

 

2.sizeof操作符和strlen函数的辨析

2.1.sizeof操作符

  这个操作符小编在前面说过,这个是计算数组长度的运算符,不过sizeof和数组(这里用arr)有个特殊的关系,小编在之前的文章说过,sizeof(arr)运算的是数组整个的长度,这个特例大家一定要记住,以后在小编在出辨析题的时候可能会有坑哦~

2.2strlen函数

  这个函数小编在之前也说过,这个函数的作用是计算字符串中\0之前的字符个数的,这里应该暂时没有特殊情况,下面我们进入sizeof操作符和strlen的比较环节,对了,这里放一张strlen库函数的相关图让读者阅读:

2.3.二者的比较

  其实二者本质就有很大的区别,前者是一个操作符,后者是一个库函数,需要包含在头文件<string.h>;前者是计算操作符所占内存的大小,单位是字节,后者是计算字符串中字符的个数;前者并不关注存的数据,给它数据它就闷头计算,后者如果一直找不到\0,如果找不到的话会一直找,可能出现越界现象!所以说二者是有着明显的区别的,读者朋友们一定要好好的区分!下面就放上面计算机的代码:

 

3.本节代码展示:

1.优化前的简易计算机代码:

void menu()
{
	printf("******************************\n");
	printf("***********简易计算器*********\n");
	printf("*******1.加法*****************\n");
	printf("*******2.减法*****************\n");
	printf("*******3.除法*****************\n");
	printf("*******4.乘法*****************\n");
	printf("*******0.退出*****************\n");
}
int Add(int x, int y)
{
	return x + y;
}
int sub(int x, int y)
{
	return x - y;
}
int div(int x, int y)
{
	return x / y;
}
int mul(int x, int y)
{
	return x * y;
}
int main()
{
	menu();             
	int i = 0;             
	int a = 0;               
	int b = 0;
	do                   
	{
		printf("请选择你想要的算法:");               
		scanf("%d", &i);                      
		switch (i)                  
		{
		case 0 :                      
			printf("好的下次光临\n");
			break;
		case 1 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int c = Add(a, b);
			printf("%d\n", c);
			break;
		case 2 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int d = div(a, b);
			printf("%d\n", d);
			break;
		case 3 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int f = mul(a, b);
			printf("%d\n", f);
			break;
		case 4 :
			printf("请选择您要的操作数:");
			scanf("%d %d", &a, &b);
			int h = mul(a, b);
			printf("%d\n", h);
			break;
		default :
			printf("您选错了请重新选择:");
			break;
		}
	} while (i);
	return 0;
}

2.第一次优化后的代码(回调函数)

void menu()
{
	printf("******************************\n");
	printf("***********简易计算器*********\n");
	printf("*******1.加法*****************\n");
	printf("*******2.减法*****************\n");
	printf("*******3.除法*****************\n");
	printf("*******4.乘法*****************\n");
	printf("*******0.退出*****************\n");
}
int Add(int x, int y)
{
	return x + y;
}
int sub(int x, int y)
{
	return x - y;
}
int div(int x, int y)
{
	return x / y;
}
int mul(int x, int y)
{
	return x * y;
}
void oay(int(*p)(int x, int y))        
{
	int a = 0;
	int b = 0;
	printf("请选择您想要运算的两个数:");
	scanf("%d %d",&a ,&b );
	int len = (*p)(a, b);
	printf("%d\n", len);
}
int main()
{
	menu();
	int i = 0;
	do
	{
		printf("请选择您想要的算法:");
		scanf("%d", &i);
		switch (i)
		{
		case 1:
			oay(Add);       
			break;
		case 2:
			oay(sub);     
			break;
		case 3:
			oay(div);
			break;
		case 4:
			oay(mul);
			break;
		case 0:
			printf("期待您的下次使用");
			break;
		default:
			printf("您填错数了,请重新填写");
			break;
		}
	} while (i);
	return 0;
}

3.转移表:

void menu()
{
	printf("******************************\n");
	printf("***********简易计算器*********\n");
	printf("*******1.加法*****************\n");
	printf("*******2.减法*****************\n");
	printf("*******3.除法*****************\n");
	printf("*******4.乘法*****************\n");
	printf("*******0.退出*****************\n");
}
int Add(int x, int y)
{
	return x + y;
}
int sub(int x, int y)
{
	return x - y;
}
int div(int x, int y)
{
	return x / y;
}
int mul(int x, int y)
{
	return x * y;
}
int main()
{
	menu();
	int i = 0;
	int a = 0;
	int b = 0;
	int(*p[5]) (a,b) = {0,add,sub,div,mul};     
	do
	{
		printf("请选择您想要的算法:");
		scanf("%d", &i);
		if (i <= 4 && i >= 1)
		{
			printf("请输入您想要的数字:");
			scanf("%d %d", &a, &b);
			int len = (*p[i])(a, b);        7
			printf("%d\n", len);
		}
		else if (i == 0)
		{
			printf("期待您的下次游玩");
			break;
		}
		else
		{
			printf("您输错了请重新输入:");
		}
	} while (i);
}

总结:

  今天小编也是写完了指针这部分的内容,也是终于结束了这部分的书写,说实在越到后期我感觉我掌握的知识越不牢固,就比如上面的函数指针数组,我其实已经忘记这个怎么定义了,这个也是边看以前写的代码边写博客才回忆到的,这里就展现了温故而知新的重要性,所以读者朋友们平时一定要多回顾自己以前学的内容,无论是编程还是别的,不然很容易遗忘的,这里小编就不多废话了,预告一下,下一篇小编就要写小编在学习C语言的时候恩师讲过的一些笔试题,我忘记了不少,所以决定写博客回顾一下,如果文章有错误,请在评论区指出,小编一定会汲取错误,那么,我们下一篇见喽!(ps:下一篇可能晚点发布)

 

 

 

   

  

  • 28
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值