实验报告(函数与宏定义)
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。
四、实验小结
通过本次实验,加强了对有关函数与宏定义方面知识的掌握,但仍需要多加练习。对于递归的运用,还不是很熟练。
五、近期个人学习总结
经过这一段时间的学习,相比之前还是有了一定的进步。自己的动手能力和逻辑思维有了一定的提高,其次,对于一些感到困惑的问题,现在也能慢慢一步步的解决。