实验报告(函数与宏定义)

C语言程序设计

实验项目:函数与宏定义

姓名:贺煜林 实验地点:一教524 实验时间:5月18日

一、实验目的与要求

1、掌握函数的调用方法和定义规则
2、掌握在C语言程序中主调函数与被调函数之间数据传递的规则
3、了解函数的返回值与类型,并将其正确使用
4、了解局部变量与全局变量的作用域与它们与储存分类的关系,理解变量的存在性和可见性的概念
5、熟悉练习递归函数的使用
6、理解宏的概念,掌握定义无参宏和有参宏的方法
7、理解文件的概念,并掌握其用法
8、理解内部函数和外部函数,掌握外部函数的编译方法和连接方法

二、实验内容

实验6-3-1-3

1、问题描述
编写程序,从键盘输入两个整数,调用gcd()函数求它们的最大公约数,并输出结果。
2、实验代码

#include<stdio.h>
int gcd(int a,int b) 
{
	int temp;
	int remainder;
	if(a<b)
	{
		temp=a;
	    a=b;
	    b=temp;
	}
	while(b!=0)
	{
		remainder=a%b;
		a=b;
		b=remainder;
	}
	return a;
}
void main()
{
	int x,y;
	int fac;
	printf("请输入两个整数:\n");
	scanf("%d,%d",&x,&y);
	fac=gcd(x,y);
	printf("The great common divisor is%d",fac);
}

3、问题分析
求最大公约数需要用到辗转相除法,其次求最大公约数函数的类型是整形,有返回值,不能写成调用语句,而应把函数调用当作表达式,把它放在表达式能出现的地方。

实验6-3-2-1

1、问题描述
若正整数 A 的所有因子( 包括 1 但不包括自身,下同)之和为 B ,而 B 的因子之和为 A,则称 A 和 B 为一对亲密数。例如,6的因子之和为1+2+3=6,因此6与6为一对亲密数。(即6自身构成一对亲密数);又如,220的因子之和为1+2+4+5+10+11+22+44+55+110=284,而284的因子之和为1+2+4+71+142=220,因此,220和284为一对亲密数。
求出500以内的所有亲密数对。
2、实验代码

#include <stdio.h>
int facsum(int m)
{
	int sum=1,f=2;
	while(f<=m/2)
	{
		if(m%f==0)
		sum=sum+f;
		f++;
	}
	return sum;
}
void main()
{
	int m=3,n,k;
	while(m<=500)
	{
		n=facsum(m);
		k=facsum(n);
		if(m==k&&m<=n)
		printf("%d,%d\n",m,n);
		m++;
	}
}

3、问题分析
需要明白亲密数对的含义,另外,在主函数中,for循环是从m=3开始调用facsum(m),在计算m是否有亲密数对。

实验6-3-2-3

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)并运行该程序。然后自定义几组数据,再运行该程序。
方法说明:
Ack函数的定义如下,n、x y为非负整数,且:

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 if(n!=0&&y!=0)
	a=Ack(n-1,Ack(n,x,y-1),x);
	return a;
}
void main()
{
	int n,x,y,result;
	printf("请输入n,x,y:\n");
	lp2: 
	scanf("%d,%d,%d",&n,&x,&y);
	if(n<0||x<0||y<0)
	{ 
	printf("输入数据错误,请重新输入\n");
	} 
	else result=Ack(n,x,y);
	printf("Ack(%d,%d,%d)=%d\n",n,x,y,result);
}

3、问题分析
在根据递归公式编写递归程序是,注意回归条件的数量

实验6-3-2-1

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。
同样要求主函数与函数/(x)在同一文件中。
(4)要求画出模块sab(a,b,n)的流程图。
设定积分为:
则复化梯形求积公式为: .
其中,h=(b-a)/n, Xk =a+kh。
2、实验代码

/*sy6_8.h*/
#include<stdio.h>
double f(double x);
double sab(double a,double b,int n)
{
	int k;
	double h,result,x1,x2,x3=0,t;
	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;
}
/*sy6_8_1.c*/
#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);
}
/*sy6_8_2.c*/
#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);
}

3、问题分析
sab()模块在一个独立的文件中,需放在一个新建立的sab.h头文件中。sab()模块中还须调用主程序文件中的f()函数,在sab.h 头文件中还须对f()函数进行声明。

三、什么是辗转相除法

辗转相除法又称欧几里得算法,是指用于计算两个非负整数a,b的最大公约数。应用领域有数学和计算机两个方面。计算公式gcd(a,b) = gcd(b,a mod b)。
欧几里得算法是用来求两个正整数最大公约数的算法。古希腊数学家欧几里得在其著作《The Elements》中最早描述了这种算法,所以被命名为欧几里得算法。
扩展欧几里得算法可用于RSA加密等领域。
假如需要求 1997 和 615 两个正整数的最大公约数,用欧几里得算法,是这样进行的:
1997 / 615 = 3 (余 152)
615 / 152 = 4(余7)
152 / 7 = 21(余5)
7 / 5 = 1 (余2)
5 / 2 = 2 (余1)
2 / 1 = 2 (余0)
至此,最大公约数为1
以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数,所以就得出了 1997 和 615 的最大公约数 1。

四、实验小结

通过本次实验,加强了对有关函数与宏定义方面知识的掌握,但仍需要多加练习。对于递归的运用,还不是很熟练。

五、近期个人学习总结

经过这一段时间的学习,相比之前还是有了一定的进步。自己的动手能力和逻辑思维有了一定的提高,其次,对于一些感到困惑的问题,现在也能慢慢一步步的解决。

posted @ 2021-06-05 22:41  HEYULIN  阅读(131)  评论(1编辑  收藏  举报