C语言程序设计教程(第三版)李凤霞 第八章课后习题答案

习题八
一、单项选择题
1、C语言程序由函数组成。它的( )。
A)主函数必须在其它函数之前,函数内可以嵌套定义函数
B)主函数可以在其它函数之后,函数内不可以嵌套定义函数
C)主函数必须在其它函数之前,函数内不可以嵌套定义函数
D)主函数必须在其它函数之后,函数内可以嵌套定义函数
2、一个C语言程序的基本组成单位是( )。
A)主程序 B)子程序 C)函数 D)过程
3、以下说法中正确的是( )。
A)C语言程序总是从第一个定义的函数开始执行
B)在C语言程序中,要调用的函数必须在main()函数中定义
C)C语言程序总是从main()函数开始执行
D)C语言程序中的main()函数必须放在程序的开始部分
4、已知函数abc的定义为:
void abc()
{… …}
则函数定义中void的含义是( )。
A)执行abc后,函数没有返回值 B)执行函数abc后,函数不再返回
C)执行函数abc后,可以返回任意类型 D)以上三个答案全是错误的
5、在以下对C语言的描述中,正确的是( )。
A)在C语言中调用函数时,只能将实参数的值传递给形参,形参的值不能传递给实参
B)C语言函数既可以嵌套定义又可以递归调用
C)函数必须由返回值,否则不能使用函数
D)C语言程序中有定义关系的所有函数都必须放在同一源文件中
6、以下叙述中错误的是( )。
A)在C语言中,函数中的自动变量可以赋初值,每调用一次赋一次初值
B)在C语言中,在定义函数时,实参和对应的形参在类型上只需赋值兼容
C)在C语言中,外部变量的隐含类别是自动存储类别
D)在C语言中,函数形参的存储类型是自动(auto)类型的变量
7、说明语句“static int i=10;”中“i=10”的含义是( )。
A)只说明了一个静态变量 B)与“auto i=10;”在功能上等价
C)将变量i初始化为10 D)将变量i赋值为10
8、C语言中的函数( )。
A)可以嵌套定义 B)不可以嵌套调用
C)可以嵌套调用,但不能递归调用 D**)嵌套调用和递归调用均可**
9、C语言中函数返回值的类型是由( )决定的。
A)return语句中的表达式类型 B)调用该函数的主调函数类型
C)调用函数时临时 D)定义函数时所指定的函数类型
10、C语言规定,调用一个函数时,实参变量和形参变量之间的数据传递方式是( )。
A)地址传递 B)值传递
C)由实参传给形参,并由形参传回给实参 D)由用户指定传递方式
11、下列的结论中只有( )是正确的。
A)所有的递归程序均可以采用非递归算法实现
B)只有部分递归程序可以用非递归算法实现
C)所有的递归程序均不可以采用非递归算法实现
D)以上三种三种说法都不对
12、在以下结论中,只有一个是错误的,它是( )。
A)C语言允许函数的递归调用
B)C语言中的continue语句,可以通过改变程序的结果而省略
C)有些递归程序是不能用非递归算法实现的
D)C语言中不允许在函数中再定义函数
13、在下列结论中,只有一个是正确的,它是( )。
A)递归函数中的形式参数是自动变量
B)递归函数中的形式参数是外部变量
C)递归函数中的形式参数是静态变量
D)递归函数中的形式参数可以根据需要自己定义存储类别
14、下列结论中只有一个是正确的,它是( )。
A)在递归函数中使用自动变量要十分小心,因为在递归过程中,不同层次的同名变量在赋值的时候一定会产生相互影响
B)在递归函数中使用自动变量要十分小心,因为在递归过程中,不同层次的同名变量在赋值的时候可能会产生相互影响
C)在递归函数中使用自动变量要十分小心,因为在递归过程中,不同层次的同名变量在赋值的时候肯定不会产生相互影响
D)在C语言中无法得出上述三个结论之一
15、在C语言的函数定义过程中,如果函数funA调用了函数funB,函数funB又调用了函数funA,则( )。
A)称为函数的直接递归 B)称为函数的间接递归
C)称为函数的递归定义 D)C语言中不允许这样的递归形式

二、填空题
1、下面的函数sum (int n)完成计算1~n的累加和。

sum (int n)
    {  if (n<0)
          retuen -1;
       if (n==1);     /* return (1) */
       else;     /* return ( n+sum(n-1) )  */
    }

2、下面的函数是一个求阶乘的递归调用函数。

facto (int n)
    {   if ( n == 1 );          /* return (1) */
        else return ();        /* return(n*facto(n-1)) */
    }

三、编程题
1、编写一个判断一个整数是否是素数的函数,使用该函数编写验证1000以内的哥德巴赫猜想是成立。(每个不小于6的偶数都是两个素数之和)

#include <stdio.h>
 main( )
 {  int i, j;
    for ( i=6; i<=1000; i+=2 )
       for ( j=3; j<=i/2; j+=2 )
	   if ( flag(j) && flag(i-j) )  {
		 printf("%d=%d+%d\n", i, j, i-j);
		 break;
	   }
 }
 flag (n)           /* 函数flag的功能是判断整数n是否为素数 */
   int n;
 {  int i;
    if ( n%2 == 0) return(0);
    for ( i=3; i<n/2; i++ )
       if ( n%i==0 )
            return(0);
    return(1);
 }

2、编写一个程序,调用函数已知一个圆筒的半径、外径和高,计算该圆筒的体积。

#include <stdio.h>
 double v ( double r, double h )
 {    return (3.1415926*r*r*h);
 }
 main( )
 {  double r1, r2, h, v();    /* r1:外圆半径  r2:内圆半径  h:圆筒的高 */
    printf ("Enter r1 r2 h:");
    scanf ("%lf%lf%lf", &r1, &r2, &h);
    printf ("v=%lf\n", v(r1,h)-v(r2,h) );
 }

3、编写一个求水仙花数的函数,求100到999之间的全部水仙花数。所谓水仙花数是指一个三位数,其各位数字立方的和等于该数。例如:153就是一个水仙花数:
153 = 111 + 555 + 333

main( )
 {   int i=0,j,k,a,b,c,s;
     for (a=1; a<=9; a++)
       for (b=0; b<=9; b++)
	 for (c=0; c<=9; c++)
	    { j=100*a+10*b+c;
	      if ( ex(j) )
		 printf ("%d=%d*%d*%d+%d*%d*%d+%d*%d*%d\n", j,a,a,a,b,b,b,c,c,c);
	    }
 }
 int ex (int m)
 {    int sum=0, z, k;
      z=m;
      while (z>0)   {
	 k= z%10;
	 sum += k*k*k;
	 z /= 10;
      }
      return ( m==sum );
 }

4、请编写一个函数,输出整数m的全部素数因子。例如:m=120时,因子为:
       2,2,2,3,5
参考答案:

main ( )
   {  int m;
      printf ("\nEnter m=");
      scanf ("%d", &m);
      primedec (m);
   }
   primedec(m)
     int m;
   {  int k=2;
      while (k<=m)
         if (m%k == 0 )
          {  printf ("%d, " , k);
             m = m/k;
          }
         else  k++;
   }

5、已知某数列前两项为2和3,其后继项根据当前的前两项的乘积按下列规则生成:① 若乘积为一位数,则该乘积就是数列的后继项;② 若乘积为二位数,则乘积的十位和个位数字依次作为数列的后继项。当N=10,求出该数列的前十项为:
2 3 6 1 8 8 6 4 2 4。
参考程序:

#include "stdio.h"
 #define MAXNUM 100
 void sum (n, pa)
   int n, pa[];
 {  int count, temp;
    pa[0] = 2;
    pa[1] = 3;
    count=2;
    while ( count < n )
    {  temp = pa[count-1] * pa[count-2];
       if ( temp<10 )
	   pa[count++] = temp;
       else
       {  pa[count++] = temp/10;
	  if ( count<n )
	      pa[count++] = temp%10;
       }
    }
 }
 main( )
 {  int n, i, num[MAXNUM];
    do
    {   printf ("Input N=? (2<N<=%d):", MAXNUM);
	scanf("%d", &n);
    } while ( n<=2 || n>MAXNUM );
    printf ("\nsum(%d)=", n);
    sum(n, num);
    for ( i=0 ; i<n; i++ )
	printf ("%4d", num[i]);
    printf ("\n");
 }

程序2

/*P244_5.c*/
#define N 20
main()
{int i,n,a[N];
 shul(a,N);
 for(i=0;i<N;i++)
 printf("%3d",a[i]);
 printf("\n");
 }
shul(int x[],int k)
{int i=0,m,n;
 x[0]=2;x[1]=3;
 for(i=2;i<k;i++)
  {m=x[i-1]*x[i-2];
   if(m>=10){x[i++]=m/10;x[i]=m%10;}
   else x[i]=m;
   }
}

6、求组合数。编程计算:
参考答案:

double facton(int n)
{double s=1;
for(;n>0;n--)
   s=s*n;
 return s;
 }
main()
{int m,n;
 double c;
 scanf("%d %d",&m,&n);
 c=facton(m)/facton(n)/facton(m-n);
 printf("c(%d,%d)=%lf\n",m,n,c);
 } 

7、已知 ackermann 函数,对于 m>=0 和 n>=0 有如下定义:
ack(0,n)=n+1
ack(m,0)=ack(m-1,1)
ack(m,n)=ack(m-1,ack(m,n-1))
请编程输入m和n,求出ack(m,n)之值。
参考程序:

#include <stdio.h>
 ackerman ( int m, int n )
 {  if ( m==0 ) return (n+1);
    if ( n==0 ) return ( ackerman ( m-1, 1) );
    else        return ( ackerman ( m-1, ackerman(m, n-1) ) );
 
 }
 main( )
 {  int m, n;
    printf ("Enter ackerman m n:");
    scanf ("%d%d", &m, &n);
    printf ("ackerman(%d,%d)=%d\n", m,n,ackerman(m,n) );
 }

8、用递归的方法打印杨辉三角形。
                 1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
…… …… …… …… …… …… ……
参考答案:
杨辉三角形中的数,正是(x+y)的N次方幂展开式中各项的系数。本题作为程序设计中具有代表性的题目,求解的方法很多(可以使用一维数组,也可以使用二维数组),这里仅给出一种使用递归求解的方法。
从杨辉三角形的特点出发,可以总结出:
① 第N行有N+1个值(设起始行为第0行);
② 对于第N行的第J个值: (N>=2)
  当J=1或J=N+1时: 其值为1
     当J!=1且J!=N+1时: 其值为第N-1行的第J-1个值与第N-1行第J个值之和
将这些特点提炼成数学公式可表示为:
c(x,y) = 1 x=1 或 x=N+1
c(x,y) = c(x-1,y-1) + c(x-1,y) 其它
下面程序就是根据以上递归的数学表达式编制的。

#include <stdio.h>
main( )
{  int i,j,n=13;
   printf("N=");
   while ( n>12 )
      scanf("%d", &n);                        /* 最大输入值不能大于12 */
   for ( i=0; i<=n; i++ )                             /* 控制输出N行 */
   {  for ( j=0; j<12-i; j++ )
          printf("   ");                  /* 控制输出第i行前面的空格 */
      for ( j=1; j<i+2; j++ )
          printf("%6d", c(i,j));              /* 输出第i行的第j个值 */
      printf("\n");
   }
}
int c(x,y)                          /* 求杨辉三角形中第x行第y列的值 */
   int x, y;
{  int z;
   if ( (y==1) || (y==x+1) )
       return(1);                /* 若为x行的第1或第x+1列,则输出1 */
   else                 /* 否则;其值为前一行中第y-1列与第y列值之和 */
       z = c(x-1,y-1) + c(x-1,y); 
   return(z);
}

9、编写一递归程序实现任意正整数向八进制数的转换。
参考程序1:

  #include <stdio.h>
   main ( )
   {  int m;
      printf ("\nEnter m=");
      scanf ("%d", &m);
      printhex (m);
   }
   printhex ( int m )
   {  if ( m>=8 )
	  printhex (m/8);
      printf ("%d", m%8);
   }
/*P245_9*/ 程序2
int a[8],i;
main()
{int n;
 scanf("%d",&n);
 ch10to8(n);
 while(i>=0)
  printf("%d",a[i--]);
  printf("\n");
  }
 ch10to8(int m) /*八进制数的每一位存入数组中*/
 {if(m<8){a[i]=m;return;}
  else
   {a[i++]=m%8;ch10to8(m=m/8);}
  } 
/*p249_9c*/
main()
{int n;
 long n8,t8();
 scanf("%d",&n);
 n8=t8(n);
 printf("n8=%ld\n",n8);
 }
long t8(int k)   /*按十进制形式读出的八进制数*/
{ if(k<8)return k;
 else return(k%8+t8(k/8)*10);
  }
/*用位移算法*/
#include "stdio.h"
void printoct(long n)
{
	long i;
	if(i=n>>3)printoct(i);
	putchar((n&7)+48);
	}
int main()
{
	long i;
	scanf("%ld",&i);
	printoct(i);
}
/* 用一般函数调用实现P245_9 */
main()
{int n;
 long n8,t8();
 scanf("%d",&n);
 n8=t8(n);
 printf("n8=%ld\n",n8);
 }
long t8(int k)
{long n=0;
 int m[8],i=0;
 while(k>0)
  {m[i++]=k%8;k=k/8;}
  i--;
 for(;i>=0;i--)
  n=n*10+m[i];
  return n;
  } 

10、验证卡布列克运算。任意一个四位数,只要它们各个位上的数字是不全相同的,就有这样的规律:
① 将组成这个四位数的四个数字由大到小排列,形成由这四个数字构成的最大的四位数;
② 将组成这个四位数的4个数字由小到大排列,形成由这4个数字构成的最小的四位数(如果四个数字中含有0,则得到的数不足四位);
③ 求两个数的差,得到一个新的四位数。
重复以上过程,最后得到的结果总是6174。
参考答案:
根据原题中描述的算法,可以将整个进行卡布列克运算的过程做成递归,这样原算法描述中的“重复执行卡布列克运算”就可以变成了递归调用。可以很容易写出递归算法如下。
进行“卡布列克运算”
若 结果不是6174
则 递归进行“卡布列克运算”
否则 结束整个程序
程序如下:


```csharp

```csharp

```c
#include <stdio.h>
int  count=0;                                             /* 计数器 */
main( )
{  int n;
   printf("Enter a number:");
   scanf("%d",&n);                                 /* 输入任意正整数 */
   vr6174(n);                                    /* 调用函数进行验证 */
}
vr6174 (num)
  int num;
{ int each[4],max,min;
  if ( num!=6174 && num ) /* 若不等于6174且不等于0则进行卡布列克运算 */
  {   parse_sort(num, each);         /* 将整数分解,数字存入each数组中 */
      max_min(each,&max,&min);          /* 求数字组成的最大值和最小值 */
      num=max-min;                            /* 求最大值和最小值的差 */
      printf("  [%d]: %d-%d=%d\n", ++count, max, min, num);
							 /* 输出该步计算过程 */
      vr6174(num);                /* 递归调用自身继续进行卡布列克运算 */
  }
}


parse_sort(num, each)          /* 函数将整数分解,数字存入each数组中 */
   int num,*each;
{  int i,*j,*k,temp;
   for ( i=0; i<=4; i++ )                         /* 将NUM分解为数字 */
   {  j=each+3-i;
      *j=num%10;
      num/=10;
   }
   for ( i=0; i<3; i++ )                /* 对各个数字从小到大进行排序 */
      for ( j=each,k=each+1; j<each+3-i; j++,k++ )
          if ( *j>*k )
             { temp=*j;  *j=*k;   *k=temp;  }
   return;
}
max_min ( each, max, min )    /* 将分解的数字还原为最大整数和最小整数 */
   int *each, *max, *min;
{  int *i;
   *min = 0;
   for ( i=each; i<each+4; i++ )                  /* 还原为最小的整数 */
      *min = *min * 10 + *i;
   *max = 0;
   for ( i=each+3; i>=each; i-- )                 /* 还原为最大的整数 */
      *max = *max * 10 + *i;
   return;
}
  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是筱倩阿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值