函数与宏定义实验报告
第六章实验报告
姓名:樊铮雄 实验地点:一教522 实验时间:5月27日
一、实验目的与要求
1.掌握函数的定义方法和调用规则。
2.掌握C语言程序中主调函数和被调函数之间进行数据传递的规则。
3.了解函数的返回值及其类型,并正确使用。
4.了解局部变量和全局变量的作用域及存储分类关系理解变量存在性和可见性的概念。
5.练习递归函数的使用。
6.理解宏的概念,掌握定义无参宏和带参宏的方法。
7.理解文件的概念并掌握其用法。
8.理解内部函数和外部函数,掌握外部函数的编译和连接方法。
二、实验内容
1、实验6.3.1(3)
问题描述:求两个整数的最大公约数.
实验代码:
#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);
}
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);
}
问题分析:用辗转相除法求两个数的最大公约数,还要判断a和b的大小关系将a,b位置交换;
不能完全照搬实验指导书,书上是remainder=a%b;a=b;应该还要加上b=remainder;
2、实验6.3.1(4)
问题描述:输入整数n,输出高度为n的等边三角形.
实验代码:
#include <stdio.h>
void trangle(int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n-i;j++)
printf(" ");
for(j=0;j<=2*i;j++)
printf("*");
putchar('\n');
}
}
main()
{
int n;
printf("请输入一个整数 ");
scanf("%d",&n);
printf("\n");
trangle(n);
}
问题分析:根据图形所示观察出每一行号前的空格数都比上一行少一个,
每一行号前的个数都比上一行多两个.
3、实验6.3.2(2)
问题描述:
(1)编写一个函数sab(a,b,n)其功能为利用复化梯形公式计算定积分,其中n为对区间[a,b]的等分数,要求该函数在一独立的文件中.
(2)编织一个主函数及计算被积函数值的函数f(x),在主函数中调用1)中函数sab.h计算并输出下列积分值.
(3)编制另一个主函数及计算被积函数值的函数f(x),在主函数中利用sab计算并输出下列积分值.
(4)要求画出模块sab(a,b,n)的流程图.
实验代码:
sab.h:
#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.cpp"
double f(double x)
{
double result;
result=x*x*exp(x);
return result;
}
main()
{
double a,b,result;
int n;
printf("请输入a,b,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.cpp"
double f(double x)
{
double result;
result=1/(25+x*x);
return result;
}
int main(void)
{
double a,b,result;
int n;
printf("Please input double a,b and integer n:");
scanf("%lf,%lf,%d",&a,&b,&n);
result=sab(a,b,n);
printf("sab(%lf,%lf,%d)=%lf",a,b,n,result);
}
问题分析:
(1)需要设计一个为sab.h的文件,命名最好简单简洁,因为后面需要引用这个文件.
(2)double应该用%lf输出.
(3)<>表示被包含文件在标准目录(include)中,包含文件名可以是.c源文件或.h头文件.
(4)""表示被包含文件在指定目录中,若文件只有文件名不带路径,则在当前目录中,若找不到,再到标准目录中寻找.
4、实验6.3.2(3)
问题描述:编制计算Ackerman函数的递归函数Ack(n,x,y).
实验代码:
#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;
}
main()
{
int n,x,y,result;
printf("请输入 n,x,y:");
scanf("%d,%d,%d",&n,&x,&y);
if(n<0)
printf("输入错误");
result=Ack(n,x,y);
printf("Ack(%d,%d,%d)=%d\n",n,x,y,result);
}
问题分析:需要用到递归函数的计算方法在判断递归条件时用好if,else分支结构.
三、辗转相除法:
欧几里得算法是用来求两个正整数最大公约数的算法。古希腊数学家欧几里得在其著作《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。(该段文字源于百度搜素)
四、实验小结:
发现自己离不开书上流程图了,但是书上的流程图有时候会有点错误,需要在自己脑里构思算法,摆脱对书本的依赖.
近期个人学习小结:
不能够完全独立的完成代码的编写,需要书本及网上资源的辅助.
多看书,基础知识都在书本上.多练习打代码,用实践将知识转化为能力.