《C程序设计》课程学习(9)——第八章 函数(另一个版本)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_34573534/article/details/102730720

例:编程求3至100之间满足下列条件的各组素数:每组有3个素数,第2个比第1个大2,第3个比第2个大4。

§8.1 概述

分类:

例:

#include<math.h>
main( )
{ int  x;
  float  y;
  scanf("%d",&x);
  y=sin(x);
  printf("%f ",y);
}
  int max( int  x, int  y) 
  {    int z;
       z=x>y ? x : y ;
           return(z);  
    }
      main( )
    { int  a,b,c;
      scanf("%d%d",&a,&b);
      c=max(a,b);
      printf("max=%d\n",c);
      }

§8.2  函数的定义

三、空函数

§8.3 函数的调用

三、函数参数和函数的值

例4:

int  sa(int  x,int  y)             
{ if(x>y)     return(1.6);
   if(x==y)   return(0.7);
   return(-1.9);
}

main( )
{int  a,b;
  scanf("%d%d",&a,&b);
  printf("%d\n",sa(a,b));
  printf("%d\n",sa(6,2*a));
}

说明:

1.实参 → 形参单向值传递。  

2.形参为变量时,实参可以是表达式。  

3.实参与形参类型一致或赋值兼容。  

4.函数的返回值通过 return 语句获得,return 语句可以有0~n个。  

5.函数类型决定返回值的类型。

四、对被调用函数的声明

例5

main( )
{int  a,b;
  void  swap(int  x,int  y);
  scanf("%d%d",&a,&b);
  swap(a,b);
  printf("a=%d,b=%d\n",a,b);
}

void  swap(int  x,int  y)             
{int  z; 
  z=x; x=y; y=z;
  printf("x=%d,y=%d\n",x,y);
}

可以省略对被调函数声明的几种情形:

1. 被调函数的定义出现在主调函数之前。

2. 在所有函数定义之前,在函数的外部已做了函数声明(例如下图代码)。

3. 被调用函数类型为整型。(不提倡)

例1: 编写求阶乘的函数。

float jiec(int  n)
{ float   y=1;
   int   i;
   for (i=1;i<=n;i++)
     y=y*i;
   return (y);
  }
main( )
{ int  i;  float  s;
   s=0;
   for(i=1;i<=10;i++)       s=s+jiec(i);
   printf("%e\n",s);
}

例2:  编写判断一个整数是否素数的函数。

求一组数中素数之和?

main( )
{int  a[100],n,i,num=0;
  scanf("%d",&n);
  for(i=0;i<n;i++)
       {scanf("%d",&a[i]);
         if (prime(a[i])==1)
                num++;
       }
  printf("num:%d\n",num);
}

编写函数时考虑:

1. 是否有返回值。→ 函数值类型  

2. 函数名不可与关键字或主调函数中其它量重名。  

3. 形参:需要从主调函数接收几个数据、类型。  

4. 若有返回值需有 return 语句。

例3: 编写函数,判定某数字是否在某正整数中,若在,打印 TRUE,否则打印 FALSE 。

 main( )
  { int m,n;
     int among(int  m, int  n );
    scanf("%d %d",&m,&n);
    if ( among(m,n) ) 
        printf("TRUE\n");
    else  printf("FALSE\n");
    }
int among(int  m, int  n)
  { int  k, z=0;
    do
     {k=m%10;
      if (n==k) {z=1;   break;  }
      m=m/10;
      }while(m!=0);
    return  z ;
    }

例4: 统计400~499这些数中4这个数字出现的次数,判一个数有几位4数字用函数实现。

num(int x)
{ int y,k=0;
  while  (x!=0) 
  {y=x%10;
   if(y==4) k++;
   x=x/10;
   }
  return(k);
 }
main( )
{int i,k=0;
 for(i=400;i<=499;i++)
   k=k+num(i);
 printf ("number=%d\n",k);
  }

例5: 找出1000之内的所有“完数”,判一个数是否为完数用函数实现 。

wan(int x)
{ int i,k=0;
   for  (i=1;i<=x/2;i++)
       if (x%i==0)  k=k+i;
   if  (k==x)   return (1);
   else   return (0);
}
main( )
{ int i;
   for(i=1;i<1000;i++)
      if(wan(i)) printf ("%5d",i);
    printf ("\n");  }

§8.5 函数的嵌套调用

不能嵌套定义函数,可以嵌套调用函数 。

例6: 写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果 。

int  gcd(int a,int b)
{int  r,t;
  if  (a<b)
   { t=a; a=b;  b=t; }
      r=a%b;
  while  (r!=0)
    { a=b;b=r; r=a%b;}
  return (b);
  }
int   lcm(int a,int b)
{  int  r;
    r=gcd(a,b);
    return(a*b/r);
  }
main( )
{  int x,y;
    scanf ("%d%d",&x,&y);
    printf ("%d\n",gcd(x,y));
    printf ("%d\n",lcm(x,y));
  }

§8.6 函数的递归调用

    在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。 

    递归问题的特点 :

1. 把一个问题转化为一个新问题,新问题与原问题解法相同,只是所处理的对象有所不同,它们是有规律的递增或递减。

2. 必须有某个终止递归的条件。

例7: 用递归法求n!

float f(int m, int n)
{ float z;
   if(n==0) z=1;
   else  z=m*f(m,n-1);
   return z;
 }
main( )
{  int  m,n;   
   scanf ("%d%d",&m,&n);
   printf ("%d,  %d,  %.0f\n",m,n,f(m,n));   
}

§8.7  数组作为函数参数

1、数组元素作函数实参

例1:读程序,写结果。

思考?

例3: 用冒泡法对数组中5个整数按升序排序。

冒泡法的思路是:将相邻两个数比较。

例3: 用冒泡法对数组中n个整数按升序排序。

main( )
{ int  a[1000],i,n;
  void sort(int  a[ ],int  n);
  scanf("%d",&n); 
  for (i=0;i<n;i++)
       scanf ("%d",&a[i]);
  sort(a,n);
  for (i=0;i<n;i++)
       printf ("%5d",a[i]);
  printf ("\n");
}
void  sort(int a[ ], int n)
 { int   i, j, t;
    for(i=1;i<=n-1;i++)
      for(j=0;j<=n-i-1;j++)
         if (a[j]>a[j+1])   
           { t=a[j];
             a[j]=a[j+1];
             a[j+1]=t;
           }
      }

注意:

数组名作参数的好处:

1、由于只需复制一个地址值,而无须复制全部需要处理的数据,因此节约存储空间并提高效率。

2、由于主调函数和被调函数是在相同的内存区域上对数据进行操作,因此可以实现数据的同步更新。

例4: 有一个3×4的矩阵,求其中的最大元素。

int  arrmax(int   y[ ], int  n)
{ int  i,max;
   max=y[0];
   for(i=1;i<n;i++)
         if(y[i]>max) max=y[i];
   return(max);
}
main( )
{ int  a[3][4]={{1,3,25,17},{22,4,6,18},{15,17,36,12}}; 
   printf ("%d\n",arrmax(a,12));
}

例5: 求3×3矩阵转置

 void  turn(int b[][3])
 { int  i, j, k;
   for (i=0;i<3;i++)
   for (j=0;j<i;j++) 
     { k=b[i][j];
       b[i][j]=b[j][i];
       b[j][i]=k;
      }
}
main()
{ static int a[3][3]={{1,3,5},
              {2,4,6},{15,17,34}};
   int  i, j;
   turn(a);
   for (i=0;i<3;i++)
     { for (j=0;j<3;j++)   
           printf ("%5d",a[i][j]);
         printf ("\n");  
      }
}

例6:写一个函数比较两个字符串s1,s2, 如果s1=s2,则返回0,如果s1>s2, 则返回1,如果s1<s2,则返回-1。

 int  comp(char s1[ ],char s2[ ])
 {int  z,i;
   for(i=0;s1[i]!='\0';i++) 
        if(s1[i]!=s2[i]) break;
   if(s1[i]>s2[i]) z=1; 
   else  if(s1[i]==s2[i]) z=0;
   else  z=-1;  
   return(z);
 }
 main()
 {char c1[40],c2[40];
   int  x;
   gets(c1);
   gets(c2);
   x=comp(c1,c2);
   printf("%d\n",x);
 }

例7: 调用递归函数求整型数组中10个元素之和。

int sum(int a[ ], int n)
{ int s;
   if (n==0)  s=a[0];
   else  s=sum(a,n-1)+a[n];
   return(s);
}
main( )
{ int a[10],i;
   for (i=0;i<10;i++)
     scanf("%d",&a[i]);
   printf("%d\n",sum(a,9));
}

8.8   局部变量和全局变量

一、局部变量

        在函数内定义的变量。    

说明 :  

  • 每个函数中定义的变量,只在定义它的函数中有效;  
  • 不同函数可以使用相同名字的变量,但意义不同;  
  • 形式参数是局部变量 ;  
  • 可以在复合语句中定义变量,但它们只在本复合语句中有效 。

二、全局变量

  • 外部变量:在函数之外定义的变量;  
  • 外部变量是全局变量;  
  • 作用范围:从定义变量的位置开始到本源文件结束。

例:在一维数组中存放10个学生的成绩,写一个函数,求出平均分,最高分和最低分。

分析:

  • 1. 平均分由函数值带回      
  • 2. 设max,min为全局变量

float max,min;
float average(float a[],int n)
{ int i;
  float aver,s=a[0];
  max=min=a[0];
  for (i=1;i<n;i++)
    { if (a[i]>max)   max=a[i];
      else  if (a[i]<min)   min=a[i];
      s=s+a[i];}
  aver=s/n;  return(aver);
}
main( )
{  float ave,score[10];
      int  i;
      for (i=0;i<10;i++)      scanf ("%f",&score[i]);
      ave=average(score,10);
      printf ("%6.2f,%6.2f,%6.2f\n",max,min,ave); }
 void average(float a[ ], int n, float b[ ])
 { int i; 
   b[0]=b[1]=b[2]=a[0];
   for (i=1;i<n;i++)
   { if (a[i]>b[0])  b[0]=a[i];
     else  if (a[i]<b[1])   b[1]=a[i];
      b[2]=b[2]+a[i];}
     b[2]=b[2]/n; }
main( )
 { float  x[3], score[10];   int  i;
   for (i=0;i<10;i++)      scanf ("%f",&score[i]);
   average(score,10,x);
   printf ("max=%6.2f,min=%6.2f,ave=%6.2f\n",x[0],x[1],x[2]);
 }

§8.9  变量的存储类别

  变量的存储类别

  静态存储变量:程序运行期间分配固定的存储空间,存放全局变量或静态局部变量。

  动态存储变量:根据需要动态分配存储空间,存放:

  •    函数形参变量 ;
  •    局部变量(未加 static 说明的);
  •    函数调用时的现场保护和返回地址等 。

局部变量的存储方式

 局部动态变量:(  [ auto  ]   )

  •    函数调用后,值不予保留,即释放存储空间 。
  •    再次调用时,原值不能引用 。

 局部静态变量:    (  static   )

  •    函数调用后保留原值,即不释放所占存储空间;
  •    再次调用时,原值在本函数内仍可使用 。

小结:

1.  按作用域分为局部变量和全局变量

        局部变量:动态局部变量(离开函数,值就消失。)

                            静态局部变量(离开函数,值仍保留。)  

       全局变量值始终保留。

2.  按存在时间分为动态存储和静态存储两种类型

动态存储:调用函数时临时分配单元 。

静态存储:程序整个运行期间都存在 ;                    

动态存储:    自动变量(本函数内有效)

                        形式参数(本函数内有效)         

静态存储:    全局变量

                        静态局部变量(本函数内有效)

3.  按变量存放位置分为

     内存中静态存储区:  全局变量

                                           静态局部变量

     内存中动态存储区:  自动变量

                                           形式参数

4.  关于作用域和生存期的概念

1) 自动变量和形式参数的作用域和存在性一致,离开函数后,值不存在,不能被引用 。  

2) 全局变量的作用域和存在性也一致,离开函数后,变量值仍存在,可被引用 。  

3) 静态局部变量的作用域和存在性不一致,离开函数后,变量值存在,但不能被引用 。

全局变量的存储方式

  静态存储

       外部变量

        1)  在函数外部定义。

        2)  允许其他文件中的函数引用,  需要用 extern 作说明。

     静态外部变量

     1)  在函数外部用static定义

     2)  只能被本文件中的函数引用

存储类别小结

1.  按作用域分为局部变量和全局变量

2.    按存在时间分为动态存储和静态存储两种类型

静态存储是程序整个运行期间都存在 ;

动态存储则是在调用函数时临时分配单元 。

3.   按变量存放位置分为 :

4 .   关于作用域和生存期的概念

  1) 自动变量和寄存器变量的作用域和存在性一致,离开函数后,值不存在,不能被引用 。

  2) 静态外部变量和外部变量的作用域和存在性也一致 , 离开函数后,变量值仍存在,可被引用 。

  3) 静态局部变量的作用域和存在性不一致 ,  离开函数后,变量值存在,但不能被引用 。

5.   static对局部变量和全局变量的作用不同

  1) 对局部变量 :使动态存储方式改变为静态存储 ;

  2) 对全局变量 :使变量局部化,但仍为静态存储 ;

  3)凡有 static 说明的,其作用域都是局限的。

§8.10  内部函数和外部函数

根据函数能否被其它源文件调用,将函数分为内部函数和外部函数。

1   内部函数 :如果一个函数只能被本文件其它函数所调用,它称为内部函数。

     static 类型标识符  函数名(形参表)

2   外部函数

     [ extern ] 类型标识符  函数名(形参表)

例23 有一个字符串,内有若干个字符,今输入一个字符,程序将字符串中该字符删去。用外部函数实现。

§8.11 如何运行一个多文件的程序

用Turbo C集成环境

用#include命令

例4: 产生15个[10,90]上的数放入a数组中,找出其中的素数放入b数组,并求b数组中元素的和。

要求: 1. 求素数用函数sushu( )完成

          2. 求素数的和用函数sum( )完成

#include <time.h> 
#include <stdlib.h>
main( )
{ int a[15],b[15],i,m;
   randomize( );
   for(i=0;i<15;i++)
      a[i]=random(81)+10;
   m=sushu(a,b);
   for(i=0;i<m;i++)
       printf("%4d",b[i]);
   printf("\n");
   printf("sum=%d\n", sum(b,m));
}
int sushu(int a[ ],int b[ ])
{     int i,j,k=0;
      for(i=0;i<15;i++)
       {for(j=2;j<=a[i]-1;j++)
          if(a[i]%j==0)  break;
         if(j>a[i]-1) 
           {b[k]=a[i];k++;}
        }
    return(k);
}
int sum(int b[ ], int n)
{  int  i, s=0; 
    for(i=0;i<n;i++)  s=s+b[i];
    return(s);
   }

猜你喜欢

转载自blog.csdn.net/qq_34573534/article/details/102730720
今日推荐