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