函数与宏定义实验

C程序设计实验报告

实验项目:
姓名:谢梅芳
实验地点:1教524
实验时间:2021.5.27
一、实验目的与要求

⑴熟练地掌握函数的定义方法和调用规则。
⑵掌握再C语言程序种主调函数和被条用函数之间进行数据传递的规则。
⑶了解函数的返回值及其类型,并正确使用它。
⑷了解局部变量和全局变量的作用域及它们与存储分类的关系,理解变量的存在性和可见性的概念。
⑸练习递归函数的使用。

二、实验内容
1、实验练习:6.3.2习2
1.1问题的简单描述:
⑴编制一个函数sab(a,b,n),.其功能为利用复化梯形公式开算定积分:
其中,n为对区间[a,b]的等分数。要求该函数在一个独立的文件中。
(2)编制一个主函数及计算被积函数值的函数f(x),在主函数中调用(1)中的函数sab(a,b,n)计算并输出下列积分值:
取n=10。要求主函数与函数f(x)在同一文件中。
(3)编制另一个主函数及计算被积函数值的函数f(x),在主函数中调用(1)中的函数sab(a,b,n)计算并输出下列积分值:
取n=8。要求主函数与函数f(x)在同一文件中。
(4)要求画出模块sab(a,b,n)的流程图。设定积分为:
则复化梯形求积公式为:
其中,h=(b-a)/n,x=a+kh。
1.2实验代码:需要使用MARKDOWN插入代码。

头文件
#include <stdio.h>
double f(double x);
double sab(double a,double b,int n)
{
	double h,result,x1,x2,x3=0,t;
	int k;
	h=(b-a)/n;
	x1=f(a);
	x2=f(b);
	for(k=1;k<=n-1;k++)
	{
	t=a+k*h;
	x3=x3+f(t);	
	}
	result=h*(x1+x2)/2+h*x3;
	return result;
}
主函数1
#include <stdio.h>
#include <math.h>
#include "sab.h" 
double f(double x)
{
	double result;
	result=x*x*exp(x);
	return result;	
	}
void main()
{
	double a,b,result;
	int n;
	printf("请输入a,b,n的值:\n");
	scanf("%lf %lf %d",&a,&b,&n);
	result=sab(a,b,n);
	printf("sab(%lf,%lf,%d)=%lf",a,b,n,result);
	return 0;
	}	
主函数2
#include <stdio.h>
#include "sab.h" 
double f(double x)
{
	double result;
	result=1/(25+x*x);
	return result;	
	}
void main()
{
	double a,b,result;
	int n;
	printf("请输入a,b,n的值:\n");
	scanf("%lf %lf %d",&a,&b,&n);
	result=sab(a,b,n);
	printf("sab(%lf,%lf,%d)=%lf",a,b,n,result);
	return 0;
	}	

实验结果:


1.3问题分析:(重点分析在实验过程中出现的问题,及解决方法。)

⑴不明白如何将三个代码联系起来从而编译运行;最后发现只要将三个文件放在一个文件夹就可,之前因头文件的命名出错导致编译不出;
⑵自定义函数用了外部函数,单独写出来从而与主函数联系;
⑶主函数与外部函数之间用了递归函数的调用。

2、实验练习:6.3.2习3
2.1问题的简单描述:
(1)根据方法说明,编制计算Ackerman函数的递归函数Ack(n,x,y)。
(2)编写一个主函数,由键盘输入n、x、y,调用(1)中的函数Ack(n, x, y),计算Ackerman函数。
(3)在主函数中,输人之前要有提示,并检查输人数据的合理性,若输人的数据不合理,则输出出错信息。输出要有文字说明。
(4)输入(n, x, y)= (2,3,1)并运行该程序。然后自定义几组数据,再运行该程序。
2.2实验代码:

#include <stdio.h>
int Ack(int n,int x,int y)
{
	int a;
	if(n==0)
	a=x+1;
	else if(n==1&&y==0)
	a=x;
	else if(n==2&&y==0)
	a=0;
	else if(n==3&&y==0)
	a=1;
	else if(n==4&&y==0)
	a=2;
	else
	a=Ack(n-1,Ack(n,x,y-1),x);
	return a;
 } 
void main()
{
	int n,x,y,result;
	printf("请输入n,x,y的值:\n");
	scanf("%d %d %d",&n,&x,&y);
	while(n<0||x<0||y<0)
	{
	printf("输入错误,请重新输入:");
	scanf("%d %d %d",&n,&x,&y);
}
        result=Ack(n,x,y);
	printf("Ack(%d,%d,%d)=%ld\n",n,x,y,result);
}

实验结果:

2.3问题分析:(重点分析在实验过程中出现的问题,及解决方法。)

⑴函数定义中用了else if语句将多分支语句实现;
⑵在主函数中用了个while循环从而实现当输入错误时提示重新输入这一内容;
⑶函数定义中用了递归函数来实现效果。

3、实验练习:6.3.3习2
3.1问题的简单描述:
(1)用递归的方法计算学生的年龄。已知第1位同学年龄最小为10岁,其余学生一个比另一个大两岁,求第5位学生的年龄。
3.2实验代码:

#include <stdio.h>
int age(int n)
{
	int c;
	if(n==1)
	c=10;
	else
	{
		c=age(n-1)+2;//用了递归函数
	}
	return c;
 } 
 main()
{
	int n=5,sage;
	sage=age(n);
	printf("第%d位学生的年龄为%d\n",n,sage);
}

实验结果:

3.3问题分析:(重点分析在实验过程中出现的问题,及解决方法。)

⑴用了递归函数从而层层深入至第五个同学,进而将其年龄输出。

4、实验练习:6.3.3习3
4.1问题的简单描述:
⑴定义递归函数:当m=0时,Acm(m,n)=n+1;当n=0时,Acm(m,n)=Acm(m-1,1);当n>0且m>0时,Acm(m,n)=Acm(m-1,Acm(m,n-1);
其中,m、n为正整数。设计程序求Acm (2,1)和Acm (3,2)。
4.2实验代码:

#include <stdio.h>
Acm(int m,int n)
{
	unsigned a;
	if(m==0)
	a=n+1;
	if(n==0)
	a=Acm(m-1,1);
	if(m>0&&n>0)
	a=Acm(m-1,Acm(m,n-1));
	return a;
}
void main()
{
	unsigned int s1,s2;
	s1=Acm(2,1);
	s2=Acm(3,2);
	printf("输出Acm(2,1)值:%d\n",s1);
	printf("输出Acm(3,2)值:%d\n",s2);
}

实验结果:

4.3问题分析:(重点分析在实验过程中出现的问题,及解决方法。)

⑴用了两次自身递归以及与if语句的结合,同时也用了函数的定义及相应的函数调用从而将Acm(2,1)与Acm(3,2)的值输出。
⑵用递归函数的使用有点迷糊。

三、什么是辗转相除法(摘要介绍,并注明出处 10分)
介绍:辗转相除法, 又名欧几里德算法(Euclidean algorithm),是求最大公约数的一种方法。它的具体做法是:用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。另一种求两数的最大公约数的方法是更相减损法。

四、实验小结(在本次实验中收获与不足 20分)

不足:递归函数的设计与调用不知道如何正确书写,并且对递归过程模糊不清;
对文件包含的使用也不太熟悉;
对函数的返回值还不是特别明白。
收获:经过实验以及自己对代码的反复剖析,对递归函数有了一定的了解,同时更深刻的了解的函数的定义与调用及宏定义的使用。
了解了局部变量和全局变量的作用域。

五、近期个人学习小结(学习收获与不足,计划如何复习,希望老师在哪部分加强训练和给与什么方面的帮助 10分)
⑴刚开始接触c语言时,第一感觉好难,都听不懂老师讲的知识,但慢慢地发现c语言挺有趣的,而且自己也会动手写代码了,知识也理解了,可能是因为平时的一些实验使对学的理论知识有了进一步的理解。
⑵但是说实话自己有时候碰上比较难的问题时,比较容易放弃,不愿去思考,尤其对于函数那一部分听的迷迷糊糊,做实验时也是,好多不懂。
⑶接下来要好好把课本上的理论知识过一遍,不明白的地方多花点时间,多做多练多学。

posted @ 2021-06-02 21:14  ❤️三石  阅读(144)  评论(0编辑  收藏  举报