一、实验目的
1.掌握函数定义与调用的方法。
2.掌握实参和形参的对应关系以及函数调用时的数据传递方式。
3.了解函数的嵌套调用和递归调用。
4.掌握局部变量、全局变量、自动变量和静态局部变量的使用方法。
二、实验学时
三、实验内容
1.运行下面的程序,分析结果
(1) #include<stdio.h>
int main(){
long fac(int);
for(int i=1;i<10;i++)
printf(“%d!=%ld\n”,i,fac(i));
}
long fac(int x){
static long p=1;
return p=p*x;
}
分析:局部静态变量离开函数,值仍保留
(2) #include<stdio.h>
int main(){
long fac(int);
for(int i=1;i<10;i++)
printf(“%d!=%ld\n”,i,fac(i));
}
long fac(int x) {
long p=1;//或 auto long p=1;
return p=p*x;
}
分析:局部自动变量离开函数,值会消失
(3) #include<stdio.h>
long p=1;
int main(){
long fac(int);
for(int i=1;i<10;i++)
printf(“%d!=%ld\n”,i,fac(i));
}
long fac(int x) {
return p=p*x;
}
分析:全局变量离开函数,函数值不会消失
2.编写函数 int fac(int x)计算 x!的值。在主函数中输入 n 和 m 的值,通过调用函
数 fac 计算Cmn 的值(要求分别用递归和非递归的方法编写函数 fac)。
非递归法:
#include<stdio.h>
int fac(int x)
{
int i;
long result=1;
for(i=2;i<=x;i++)
result*=i;
return result;
}
int main(){
double p;
int m,n;
do{
scanf("%d %d",&n,&m);
}while(n<m||m<0||n<0);
p=(double)fac(n)/(fac(m)*fac(n-m));printf("p=%.0f\n",p);
}
递归法:
#include<stdio.h>
int fac(int x);
int main() {
double p;
int m,n;
scanf("%d %d",&n,&m);
p=(double)fac(n)/(fac(m)*fac(n-m));
printf("p=%.0f\n",p);}
int fac(int x){
if(x<0)
return -1;
else if(x==0||x==1)
return 1;
else
return(x*fac(x-1));
}
运行结果
3.编写一个递归函数计算两个正整数的最大公约数。在主函数中输入两个正整数
m 和 n 的值,计算两个数的最大公约数和最小公倍数并输出。
(算法参考教材 P186 P7.7)
#include<stdio.h>
int gcd(int a,int b){
int i;
for(i=a;i>=1;i--)
if(a%i==0&&b%i==0)
break;
return i;
}
int lcm(int a,int b)
{
return a*b/gcd(a,b);
}
int main() {
int m,n;
scanf("%d %d",&m,&n);
printf("最大公约数%d,最小公倍数%d\n",gcd(m,n),lcm(m,n));
return 1;
}
4.编写一个判别素数(质数)的函数 int isPrime(int x)。在 main 函数中,输入一
个正整数 n,输出 1~n 之间的所有素数以及素数的个数
(算法参考教材 P187 P7.13)
#include<stdio.h>
int isPrime(int x)
{
int i;
if(x==1)
return 0;
for(i=2;i<x;i++)
if(x%i==0)
return 0;
return 1;
}
int main() {
int n,i,sum=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
if(isPrime(i)){
printf("%d ",i);
sum++;}
}
printf("素数的个数:%d\n",sum);
return 1;
}
5.在 main 函数中,输入一个正整数 n。对于 2~n 之间的每一个数,如果是合数,
则输出每个合数的所有质因子(利用上一题的 isPrime 函数)
如:n=12
输出: 4=2×2
6=2×3
8=2×2×2
9=3×3
10=2×5
12=2×2×3
#include<stdio.h>
int isPrime(int n)
{
int i;
if(n==1)
return 0;
for(i=2;i*i<=n;i++)
if(n%i==0)
return 0;
return 1;
}
void OutputPrimeFactor(int n)
{
int i;
printf("%d=",n);
for(i=2;n>1;i++)
{
while(n%i==0)
{
printf("%d",i);
n=n/i;
if(n>1)
printf("×");
}
}
printf("\n");
}
int main()
{
int i,n;
scanf("%d",&n);
for(i=2;i<=n;i++)
{
if(isPrime(i)==0)
OutputPrimeFactor(i);
}
return 0;
}
6、5 个水手在岛上发现了一堆椰子,先有第一个水手把椰子分成等量的 5 堆,还
剩了 1 个给了猴子,自己藏起一堆。然后第 2 个水手把剩下的 4 堆混合后重新分
为等量的 5 堆,还剩了 1 个给了猴子,自己藏起一堆。以后第三、四个水手依次
按此方法处理。最后,第 5 个水手把剩下的椰子分成等量的 5 堆后,同样剩下 1
个给了猴子。请用迭代法编程计算并输出原来这堆椰子至少有多少个?
#include<stdio.h>
int candivide(int x){
int i;
for(i=1;i<=5;i++){
if((x-1)%5!=0)
return 0;
x=(x-1)/5*4;
}
return 1;
}
int main() {
int i;
for(i=1;;i++){
if(candivide(i)){
printf("%d",i);
break;
}
}
}
7、在上题中,如果第 5 水手分得 255 个椰子,用递归的方法计算原来这堆椰子
的个数。
#include<stdio.h>
int beforeDivide(int n)
{
if(n==5)
return 255*5+1;
else
return beforeDivide(n+1)/4*5+1;
}
int main()
{
printf("%d\n",beforeDivide(1));
}
8.有 m 个 A 和 n 个 B,用递归方法计算有多少种排列。
提示:假设用 P(m,n)表示 m 个 A 和 n 个 B 的排列数。假设第一个是 A,
则剩下 m-1 个 A 和 n 个 B,剩下的字母排列数是 p(m-1,n)。如果第 1 个是 B,
则剩下 m 个 A 和 n-1 个 B,剩下的排列数是 p(m,n-1)。所以有:
p(0,n) = 1
p(m,0)=1
p(m, n) = p(m-1,n) + (m, n-1)
#include<stdio.h>
int f(int x,int y)
{
if(!x||!y)
return 1;
return f(x-1,y)+f(x,y-1);
}
int main(){
while(1)
{
int n,m;
scanf("%d%d",&n,&m);
printf("%d\n",f(n,m));
break;
}
return 0;
}
四、实验小结
在实验报告中记录各题实验代码及运行结果,针对实验中遇到的问题及其解
决方法、或尚未解决的问题、实验收获等,仔细撰写实验报告。