大家好,很高兴又和大家见面啦!经过前面的学习,博主不清楚大家对前面内容的掌握情况如何,那么今天我们将会开始通过做题来检测并加深大家对前面内容的理解与应用。
习题演练——函数篇
1.接收一个无符号整型值,按顺序打印它的每一位:
(1)代码编写
这一题我们在函数递归时有讲解过,今天我们尝试着通过函数迭代的方式来解答这一题:
#define _CRT_SECURE_NO_WARNINGS 1//防止VS对使用scanf函数时报出警告
#include <stdio.h>//使用scanf函数需要调用头文件
#include <math.h>//使用pow函数需要调用头文件//按顺序打印无符号整型值的每一位数
//知识点一:进行函数定义与声明(声明要在主函数前)
void print(int x)//知识点二:自定义函数的组成(返回类型、函数名、函数参数、函数体)
//void——无返回类型;print——函数名;x——函数形参;
{
int m = 0, n = 10, i = 0;//函数体——函数的实现;
//知识点三——函数的迭代——在函数体中使用循环
for (i = 3; i >= 0; i--)//通过for循环进行函数迭代;
{
//知识点四——函数的嵌套调用
m = pow(n, i);//进行嵌套调用数学函数pow求10的i次方;
printf("%d ", x / m);//进行嵌套调用输出函数printf打印x/10的i次方的整数部分;
x %= m;//将x/10的i次方的余数部分赋值给x;
}
}
int main()
{
unsigned int a = 0;
scanf("%d", &a);
//知识点五——函数的实参
//知识点六——函数的传值调用
print(a);//a——函数实参,进行传值调用;
return 0;
}
这里的编写思路我就不再重复了,下面我们还是输入1234来测试编写是否正确:
(2)涉及知识点
我们从这次编写中可以看到,这里涉及了函数的6个知识点:
- 函数的组成;
- 函数的参数;
- 函数的传值调用;
- 函数的嵌套调用;
- 函数的定义与声明;
- 函数的迭代;
不知道这些知识点,朋友们你们对它们的掌握情况如何呢?我们接着看下一题:
2.编写函数,不允许创建临时变量,求字符串长度:
看到这个题目,我们能马上想到计算字符串长度的函数strlen,这个题目的要求是让我们自己编写一个strlen,那我们应该如何编写呢?下面我们来分析一下题目:
【分析】
strlen函数的工作流程就是计算字符的个数,直到遇到字符串停止标志“\0”才停止计算。通过strlen函数的工作流程,我们可以确定我们编写的函数,至少需要有两个功能——1.计算字符的个数,2.遇到\0时停止。如何去实现呢?下我们来思考几个问题:
(1)用什么来接收字符串?
这里我们可以通过输入函数scanf来接收字符串;
(2)接收的字符串存放在哪里呢?
提到字符串,我们首先要想到的是数组,我们可以通过定义一个字符数组来存储scanf函数接收的字符串;
(3)函数的参数分别是什么?
既然我们通过数组来接收存储的字符串,那我们进行传参的实参肯定也是数组,所以函数的形参可以定义数组来接收,在数组的内容里我们知道了数组名代表的是首元素的地址,所以函数的形参可以采用指针来接收;
(4)函数如何实现?
我们定义的函数需要完成两个功能:
- 计算字符的个数
- 遇到\0时停止
根据这两个功能我们可以通过循环语句来实现,判断条件则是arr[i]!=\0
,也就是我们从数组中将元素一个一个提取出来与\0比较,不等于\0就将数量加1,直到等于\0才跳出循环;
【代码编写】
(1)函数迭代
在分析完题目,下面我们开始进行代码编写:
int my_strlen(char x[])
//int——函数返回类型;
//my_strlen——函数名;
//x[]——函数形参;
{//函数体——函数的实现
int i = 0, j = 0;//i——元素下标,j——字符个数
//函数的迭代
for ( i = 0; x[i] != '\0'; i++)
//x接收的是首元素的地址,我们通过元素下标来访问数组的各个元素
//每次访问元素时都与\0进行比较,不相等则进入循环;
{
//进入循环后开始记录进入次数,进入循环的次数=字符的个数
j++;
}
//当遇到\0时跳出循环,此时将j的值返回给函数
return j;
}
int main()
{
char a[20];
//函数的传址调用
scanf("%s", a);//a为函数实参
//函数的链接访问
printf("len=%d", my_strlen(a));
return 0;
}
这里我们通过函数迭代的方式实现了求字符串长度代码的编写,但是通过迭代的方式我们创建了临时变量,不符合题目要求,接下来我们尝试用函数递归来编写代码;
(2)函数递归
int my_strlen(char* x)
//int——函数返回类型;
//my_strlen——函数名;
//x——函数形参;
{//函数体——函数的实现
//*x——将地址中的元素提取出来与\0进行比较
if (*x != '\0')
{
//函数递归
return my_strlen(x + 1) + 1;
}
else
return 0;
}
int main()
{
char a[20];
//函数的传址调用
scanf("%s", a);//a为函数实参
//函数的链接访问
//函数的传址调用
printf("len=%d", my_strlen(a));
return 0;
}
现在就按照题意把计算字符长度的函数编写完了,下面我们来看一下这一题分别涉及了哪些函数的知识点;
(3)涉及知识点
这道题涉及到了以下知识点:
- 函数的组成;
- 函数的参数;
- 函数的传址调用;
- 函数的链式访问;
- 函数的定义与声明;
- 函数的递归与迭代;
- 数组作为函数的参数
不知道各位朋友对函数的这些知识点掌握的怎么样了,接下来我们继续看下一题;
3.求第n个斐波那契数。(不考虑溢出):
做这道题我们首先要了解一下什么是斐波那契数:
(1)什么是斐波那契数?
斐波那契数指的是:1,1,2,3,5,8,13,21,34,55,89……这样一个数列,这个数列从第3项开始,每一项都等于前两项之和。
(2)解题分析
功能一——第三项起,每一项都等于前两项之和
这题的要求是需要我们写一个函数能够使它从第3项开始进行前两项相加,我们可以尝试编写一个两数相加以及相互赋值的代码:
int a = 1, b = 1, c = 0;
c = a + b;
a = b;
b = c;
这个代码的逻辑如下:
根据这个逻辑,我们能很好的实现第三项起,每一项都等于前两项之和;
功能二——求第n项
既然我们要实现求第n项,那就有两个选择——函数递归与函数迭代。要使用递归和迭代,我们就需要先搞清楚它的限制条件,显而易见,这个限制条件与我们需要求解的n相关,我们可以通过输入n来完成对递归或者迭代的限制:
int main()
{
int a = 1, b = 1, c = 0, n = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
if (i <= 2)
{
c = 1;
}
else
{
c = a + b;
a = b;
b = c;
}
printf("第%d项的斐波那契数=%d\n", i, c);
}
printf("第%d项的斐波那契数=%d\n", n, c);
return 0;
}
在主函数中通过这样编写就能求出第n项的斐波那契数了,求解结果如下:
下面理清了编写思路,我们就开始分别用递归与迭代的方式来编写函数吧;
(3)函数的实现
我们先通过迭代的方式来完成函数:
int Fib(int n)
{
int a = 1, b = 1, c = 0;
//函数迭代
for (int i = 1; i <= n; i++)
{
if (i <= 2)
{
c = 1;
}
else
{
c = a + b;
a = b;
b = c;
}
}
return c;
}
int main()
{
int m = 0, n = 0;
scanf("%d", &n);
//传值调用
m = Fib(n);
printf("第%d项的斐波那契数=%d\n", n, m);
return 0;
}
这样我们就通过函数迭代的方式实现了第n项的斐波那契数列求解,下面我们再试一下用函数递归来编写:
int Fib(int n)
{
if (n <= 2)
{
//第1项与第2项都为1
return 1;
}
else
{
//第n项为前两项之和
return Fib(n - 1) + Fib(n - 2);
//n-1为n的前一项,n-2为n-1的前一项;}
}
int main()
{
int m = 0, n = 0;
scanf("%d", &n);
//传值调用
m = Fib(n);
printf("第%d项的斐波那契数=%d\n", n, m);
return 0;
}
这样我们也通过函数递归的方式完成了斐波那契数的第n项求解,这一题整体做下来其实并不复杂,我们只需要把思路理清,然后就能将编写出来,下面我们来总结一下这一题涉及到的知识点;
(4)涉及知识点
- 函数的组成;
- 函数的参数;
- 函数的传址调用;
- 函数的定义与声明;
- 函数的递归与迭代;
结语
到这里咱们本章的内容就全部结束了,在今天的习题中涉及的知识点都是咱们必须要掌握的知识点,希望这些内容能够帮助大家更好的理解函数的这些相关知识并能够将其融会贯通。接下来随着学习的深入,我会继续给大家分享我在学习过程中的感受。如果各位喜欢博主的内容,还请给博主的文章点个赞支持一下,有需要的朋友也可以收藏起来反复观看哦!感谢各位的翻阅,咱们下一篇见。