C程序设计实验报告
实验项目:
###6.4.2、模块化程序设计
- 利用复化梯形公式计算定积分
- 计算Ackerman函数
###6.4.3 函数的递归调用
- 编程计算x的y次幂的递归函数getpower(int x,int y),并在主程序中实现输入输出
- 编写计算学生年龄的递归函数
- 编写递归函数实现Ackman函数
##姓名:罗龙妹 实验地点: 514实验室 实验时间:2019年5月16日
##一、实验目的与要求
###6.4.2、模块化程序设计
####6.4.2.2 利用复化梯形公式计算定积分
- 掌握C语言中定义函数的方法
- 掌握通过“值传递”调用函数的方法
####6.4.2.3 计算Ackerman函数
- 掌握递归函数的设计方法
- 进一步练习阅读检查与的调试修改C程序的方法
###6.4.3 函数的递归调用
####6.4.3.1 编程计算x的y次幂的递归函数getpower(int x,int y),并在主程序中实现输入输出
- 写出解决该问题的递归算法:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518091420521-392191465.png)
- 在递归函数中,使用数字1作为回归条件
- 在递归函数中,使用if-else语句根据条件的真假来决定是递推还是回归
####6.4.3.2 编写计算学生年龄的递归函数
- 写出解决该问题的递归算法:
递归公式如下,根据公式容易写出递归程序。
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518091807009-1625751680.png)
- 在递归函数中,使用数字1作为回归条件
- 在递归函数中,使用if-else语句根据条件的真假来决定是递推还是回归
####6.4.3.3 编写递归函数实现Ackman函数
- 根据递归公式编写递归函数
- 在递归函数中,使用if-else语句根据条件的真假来决定是递推还是回归
##二、实验内容
###6.4.2:模块化程序设计
####实验练习2:利用复化梯形公式计算定积分
- 问题的简单描述:
(1)编写一个函数sab(a,b,n),其功能为利用复化梯形公式计算定积分
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518092243053-1490352187.png)
其中n为对区间[a,b]的等分数。要求改函数在一个独立的文件中。
(2)编制一个主函数以及计算被积函数值的函数f(x),在主函数中调用(1)中的函数sab(a,b,n)计算并输出下列积分值
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518092609012-2057392390.png)
要求主函数与函数f(x)在同一文件中。
(3)编制另一个主函数以及计算被积函数值的函数f(x),在主函数中调用(1)中的函数sab(a,b,n)计算并输出下列积分值
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518092809688-1542214895.png)
同样要求主函数与函数f(x)在同一文件中。
(4)要求画出模板sab()的流程图。
方法说明:
设定积分为
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518092933551-893938124.png)
则复化梯形求积公式为
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518093003518-420510.png)
其中
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518093027538-1605707702.png)
- 程序流程图:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518125355325-358457372.png)
- 实验代码1:
```
/*sab.h*/
#include
double f(double x);
double sab(double a,double b,int n)
{
double h,result,x1,x2,x3=0,t,k;
h=(b-a)/n;/*求h的值*/
x1=f(a);/*求f(a)的值*/
x2=f(b); /*求f(b)的值*/
for(k=1;k<=n-1;k++)/*for循环的循环体*/
{
t=a+k*h;
x3=x3+f(t);
}
result=h*(x1+x2)/2+h*x3;
return result;
}
```
- 实验代码2:
```
#include
#include
#include"sab.h"
double f(double x)
{
double result;
result=x*x*exp(x);/*f(x)=x*x*exp(x)的程序段*/
return result;
}
main()
{
double a,b,result;
int n;
printf("please input double a,b and integer n:");/*提示输入a,b,n*/
scanf("%lf,%lf,%d",&a,&b,&n);/*输入a,b,n*/
result=sab(a,b,n);/*调用sab(a,b,n)求积分*/
printf("sab(%lf,%lf,%d)=%f",a,b,n,result);/*输出结果*/
return 0;
}
```
- 实验代码3:
```
#include
#include"sab.h"
double f(double x)
{
double result;
result=1/(25+x*x);/*f(x)=1/(25+x*x);f(x)=1/(25+x*x)的程序段*/
return result;
}
main()
{
double a,b,result;
int n;
printf("please input double a,b and integer n:");/*提示输入a,b,n*/
scanf("%lf,%lf,%d",&a,&b,&n);/*输入a,b,n*/
result=sab(a,b,n);/*调用sab(a,b,n)求积分*/
printf("sab(%lf,%lf,%d)=%f",a,b,n,result);/*输出结果*/
return 0;
}
```
- 问题分析:(重点分析在实验过程中出现的问题,及解决方法。)
这个程序需要建立三个独立文件,首先要建好sab.h头文件,然后在另外两个文件中要记得加上这个sab.h头文件,不然程序是运行不出来的,将sab.h头文件单独拉出来是为了让代码看起来不会那么繁杂,要在不同文件中引用的话也不用再打一遍代码,只要加上一个头文件即可,然后按照流程图一步一步地走即可运行成功。
- 程序运行如下:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518093834012-1507528397.png)
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518093852987-1932957060.png)
####实验练习3:计算Ackerman函数
- 问题的简单描述:
具体要求如下:
(1)根据方法说明,编制计算Ackerman函数的递归函数ack(n,x,y)。
(2)编制一个主函数,由键盘输入n,x,y,调用(1)中的函数ack(n,x,y),计算Ackerman函数
(3)在主函数中,输入之前要有提示,并检查输入数据的合理性。若输入的数据不合理,则输出出错信息。输出要有文字说明。
(4)输入(n,x,y)=(2,3,1)运行该程序。然后自定义几组数据在运行该程序。
方法说明:
Ackerman函数的定义如下:
n,x,y为非负整数,且
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518095241914-1074538567.png)
- 程序流程图:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518132650749-1483009722.png)
- 实验代码:
```
#include
int Ack(int n,int x,int y)
{
int a;
if (n==0)/*判断回归条件1的if语句头部*/
a=x+1;
else if (n==1&&y==0)/*判断回归条件2的if语句头部*/
a=x;
else if (n==2&&y==0)/*判断回归条件3的if语句头部*/
a=0;
else if (n==3&&y==0)/*判断回归条件4的if语句头部*/
a=1;
else if (n>=4&&y==0)/*判断回归条件4的if语句头部*/
a=2;
else if (n!=0&&y!=0)/*进一步递推的语句*/
a=Ack(n-1,Ack(n,x,y-1),x);
return a;
}
main()
{
int n,x,y,result;
printf("please input n,x,y:");/*提示输入n,x,y*/
scanf("%d,%d,%d",&n,&x,&y);/*输入n,x,y*/
if(n<0||x<0||y<0)
printf("error!");/*如果输入不合法,输出错误提示信息并重新输入*/
else
{
result=Ack(n,x,y);/*用输入的两个数据,调用递归函数*/
printf("Ack(%d,%d,%d)=%d\n",n,x,y,result);
}
}
```
- 问题分析:
这个程序是对递归函数的调用,用if嵌套语句来判断5个回归条件,要特别注意n,x,y这三个变量的要求是非负整数,所以在输入之前要有提示并检查输入数据的合理性。
- 程序运行如下:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518095604065-870023883.png)
###6.4.3:函数的递归调用
####实验练习1:编程计算x的y次幂的递归函数getpower(int x,int y),并在主程序中实现输入输出
- 问题的简单描述:编写程序,分别从键盘输入数据x和y,计算x和y次幂并输出。
- 程序流程图:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518133635245-1521780510.png)
- 实验代码:
```
#include
long getpower(int x,int y)
{
if(y==1)/*判断回归条件的if语句头部*/
return x;
else
return x*getpower(x,y-1);/*进一步递推的语句*/
}
main()
{
int num,power;
long answer;
if (num%2==0||num%2==1)
{
printf("输入一个数:");/*提示输入一个数*/
scanf("%d",&num);/*输入一个整数*/
}
else printf("输入出错!");
if (power%2==0||power%2==1)
{
printf("输入幂次方:");/*提示输入幂次方*/
scanf("%d",&power);/*输入一个整数*/
}
else printf("输入出错!");
answer=getpower(num,power);/*用输入的两个数据,调用递归函数*/
printf("结果是:%ld\n",answer);
}
```
3问题分析:(重点分析在实验过程中出现的问题,及解决方法。)
这个程序是一个涉及递归算法的数学模型,用if-else语句根据条件的真假来决定是递归还是回归。在主函数中,变量answer可能要存放较大的数,所以将它的类型定义为long型;在求幂的递归函数getpower()可能要存放较大的数,所以也定义为long型;在输出结果的printf()函数中,由于要输入长整型数据,所以其输出格式要为“%ld”。在输入x和y变量的时候要判断输入的数是否为整数,在这个提示上我研究了很久,结果还是研究不怎么 清楚,不知道判断是否为整数的条件语句到底该怎么写。
- 程序运行如下:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518101506726-262053380.png)
####实验练习2:编写计算学生年龄的的递归函数
- 问题的简单描述:用递归方法计算学生的年龄。已知第一位学生的年龄最小为10岁,其余学生一个比一个大2岁,求第5位学生的年龄。
- 程序流程图:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518134520557-424714084.png)
- 实验代码:
```
#include
int age(int n)
{
int c;
if(n==1)/*判断回归条件if语句头部*/
c=10;
else
return age(n-1)+2;/*进一步递推的语句*/
return c;
}
main()
{
int result,n=5;
result=age(n);
printf("age(%d)=%d",n,result);
}
```
- 问题分析:
这个程序根据递归问题描述写出递归问题描述很容易写出递归公式,进而写出递归程序。
- 程序运行结果如下:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518101847090-1065321154.png)
####实验练习3:编写递归函数实现Ackman函数
- 问题的简单描述:定义递归函数实现下列Ackman函数:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518101957523-1405229198.png)
其中m、n为正整数。设计创新求Acm(2,1),Acm(3,2)。
- 程序流程图:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518135501780-239776663.png)
- 实验代码:
```
#include
Acm(int m,int n)
{
if(m==0)
return n+1;
else if(n==0)
return Acm(m-1,1);
else
return Acm(m-1,Acm(m,n-1));
return 0;
}
main()
{
int x,y;
x=Acm(2,1);
y=Acm(3,2);
printf("Acm(2,1)=%d\n",x);
printf("Acm(3,2)=%d\n",y);
return 0;
}
```
- 问题分析:(重点分析在实验过程中出现的问题,及解决方法。)
这个程序也是一个递归函数的调用问题,也要使用if-else语句根据条件的真假来决定是递推还是回归。
- 程序运行结果如下:
![](https://img2018.cnblogs.com/blog/1617039/201905/1617039-20190518102158769-1879218415.png)
##三、实验小结(在本次实验中收获与不足)
这节实验课还是函数和宏定义的实验,在这次实验中大部分的都是关于递归函数的调用问题,要注意什么时候是递推,什么时候是回归,要对递归函数概念有一定的理解,但对于一些算法我还是不太清楚,课后还需花些时间去弄明白。然后就是流程图问题,流程图真的很重要,所以拿到一个题目我们要尝试着自己画出它的流程图,然后看看根据自己画的流程图看看能不能运行出这个程序,不能的话要不断地进行修改,直到程序运行成功。