第
This presentation is the property of its rightful owner.
Sponsored Links
1 / 75

程序结构概念 : 1 )较大的程序应分为 若干个程序模块 ; 2 )每个模块实现单一的特定功能; 3 )由主函数开始执行,主函数调用子函数; 4 )子函数之间可以互相调用。 PowerPoint PPT Presentation


  • 84 Views
  • Uploaded on
  • Presentation posted in: General

第 8 章 函数. 8.1 概述. 程序结构概念 : 1 )较大的程序应分为 若干个程序模块 ; 2 )每个模块实现单一的特定功能; 3 )由主函数开始执行,主函数调用子函数; 4 )子函数之间可以互相调用。. 说明 :. 1. 一个源文件可由一个或多个函数组成; 2. 一个 源文件 是一个 编译单位 ; 3. 一个 C 程序 由一个或多个 源文件 组成。 4. 从 main() 开始,调用其它函数后, 回到 main() 结束 ; 5. 不能嵌套定义,但可互相调用 。 6. 分类 :

Download Presentation

程序结构概念 : 1 )较大的程序应分为 若干个程序模块 ; 2 )每个模块实现单一的特定功能; 3 )由主函数开始执行,主函数调用子函数; 4 )子函数之间可以互相调用。

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


1 2 3 4

第8章 函数

8.1 概述

程序结构概念 :

1)较大的程序应分为若干个程序模块 ;

2)每个模块实现单一的特定功能;

3)由主函数开始执行,主函数调用子函数;

4)子函数之间可以互相调用。


1 2 3 4

说明 :

1. 一个源文件可由一个或多个函数组成;

2. 一个源文件是一个编译单位;

3. 一个C 程序由一个或多个源文件组成。

4. 从 main() 开始,调用其它函数后,

回到 main() 结束 ;

5. 不能嵌套定义,但可互相调用 。

6. 分类 :

1) 标准函数 和 用户自定义函数 ;

2) 无参函数 和 有参函数 。


1 2 3 4

8.2 函数定义

1. 无参函数的定义

形式:类型标识符 函数名( )

{说明部分

语句 }

例如:

main( )

{ int a=5,b=9 ;

printf(" %d\n " , a*b*b );

}

说明:若不带回函数值,类型标识符也可以不写,无参函数一般用于完成指定的一组操作。


1 2 3 4

2.有参函数的定义

形式:类型标识符 函数名(形式参数表列)

形式参数说明

{说明部分

语句}

如:int max( x, y )

int x , y;

{ int z ;

z=x>y ? x : y ;

return ( z ) ;

}

空函数定义形式:

类形标识符 函数名( )

{ }

作用:备以后扩充。


1 2 3 4

8.3 函数参数和函数的值

8.3.1 形式参数和实际参数

形式参数 :

定义函数时,括号中说明的变量名 ;

实际参数 :

调用函数时,括号中给定的表达式 。


1 2 3 4

main( )

main( )

{ int a,b,c;

{ int a,b,c;

scanf ("%d,%d",&a,&b);

scanf ("%d,%d",&a,&b);

c=max( a ,b );

函数调用

c=max( a ,b );

printf ("max is %d\n",c);

printf ("max is %d\n",c);

}

int

max( x, y )

max( x, y )

形参说明

int x,y;

int x,y;

{int z;

{ int z;

z=x>y?x:y;

z=x>y?x:y;

return (z);

return (z);

}


1 2 3 4

说明:

1. 定义函数时,形参不占内存单元 ;

调用函数时,形参才分配内存单元 ;

调用结束后,形参所占内存单元被释放。

2. 实参可以是常量、变量或表达式,但必须有确切的值。

3. 定义函数,必须指明形参类型。

4. 实参与形参类型一致。

5. 实参变量对形参变量的数据传递是“值传递 ”,即单向传递。

6. 可在“形参表列”中说明形参类型。

int max( int x , int y )

{ 函数体 }


1 2 3 4

8.3.2 函数的返回值

说明 :

1. 通过 return 语句获得返回值 ;

2. 定义函数时指定函数返回值的类型;不加类型说明

的,按整型处理。

3. 函数值的类型和 return 语句中表达式的值不一

致时,以函数类型为准。

4. 被调用函数中没有 return 语句时,带回一个不

确定的值。

5. 为了明确表示“不带回值”,可以用“ void ” 定

义 “ 无类型 ”。


1 2 3 4

看下面例子:

main()

{float a,b;

int c;

scanf(“%f,%f”,&a,&b);

c=max(a,b);

printf(“Max is %d\n”,c);

}

max(float x,float y)

{float z;

z=x>y?x:y;

return (z)}

运行结果:

1.5,2.5

Max is 2


1 2 3 4

8. 4 函数的调用

8.4.1 函数调用的一般形式

函数名(实参表列)

说明 :

1.无参函数,括号不能省 ;

2.实参表列中,各实参与形参在 个数、顺序、 类型上一一对应,参数间用逗号分隔。

注意:计算实参时的次序不同。为了提高程序的通用性,一般都写清楚。


1 2 3 4

int f(int a,int b)

{ int c;

if (a>b) c=1;

else if (a= =b) c=0;

else c=-1;

return (c);

}

函数调用发生

函数调用结束

i

5

j

9

i

5

j

9

a,b所占的存储单元被释放

b

9

a

5

main( )

{int i,j,p;

scanf("%d%d",&i,&j);

p=f(i,j);

printf ("%d",p);

}


1 2 3 4

8.4.2 函数调用的方式

调用函数的方式有三种:

函数语句、函数表达式、函数参数。

如:printf("******");

m=max(a,b)*20;

printf("%d",max(a,b));


1 2 3 4

8.4.3 对被调用函数的声明和函数原型

1.被调函数必须存在;

2.用#include命令包含有关库函数;

3.被调用函数一般应在主调函数前定义,这样在主调函数中可以不对调用函数类型进行声明。否则在主调函数中必须对调用函数类型进行声明(整型除外);

4.如果在文件开头,已声明了被调函数类型,则主调函数中不必再作类型声明。


1 2 3 4

被调用函数声明

例 1:

函数声明的作用是把函数名及函数类型、形参个数及类型通知编译系统,以便在调用该函数时系统按此进行对照检查。

main( )

{float add( );

float a,b,c;

.....

}

float add(x,y)

float x,y;

{…}

float add(float,float);

float add(float x,float y );

函数定义

函数定义是指对函数功能的确立,包括指定函数名、函数值类型、形参个数及类型、函数体等。它是一个完整、独立的程序单位。


1 2 3 4

例 2:

float add(x,y)

float x,y;

{ float z;

z=x+y;

return(z);

}

main( )

{ float a,b,c;

scanf("%f,%f",&a,&b);

c=add(a,b);

printf("%f\n",c);

}

在主调函数前定义


1 2 3 4

char let( );

float f( );

int max( );

例 3:

已在文件

开头声明

main( )

{......}

char let(c1,c2)

char c1,c2;

{......}

float f(x,y)

float x,y;

{......}

int max(j,k)

float j,k;

{......}

定义 let 函数

定义f函数

定义max函数


1 2 3 4

main( )

{ float a;

int y();

scanf ("%f",&a);

printf ("%d", y(a));

}

1 x>0

y=

0 x=0

-1 x<0

程序举例:

float x;

例1:求下列函数的值

scanf("%f",&x);

y(x)

y(a)

int y(float x)

{ int z;

if (x>0) z=1;

else if (x<0) z=-1;

else z=0;

return(z);

}

a

5

x

5

x


1 2 3 4

例 2.求5!、16!和27!

float jiec(n)

int n;

{ float y=1;

int i;

for (i=1;i<=n;i++)

y=y*i;

return (y);

}

main( )

{ float a,b,c;

a=jiec(5);

b=jiec(16);

c=jiec(27);

printf ("%f,%f,%f\n",a,b,c);

}


1 2 3 4

例 3.编写函数,判定某数字是否在某正整数中,若在,打印 TRUE,否则打印 FALSE,输出结果在主函数中完成。

main( )

{int m,n; /*判断数字n是否在数m中/

int among(int m,int n);

scanf("%d %d",&m,&n);

if(among(m,n)) printf("TRUE");

else printf("FALSE");

}


1 2 3 4

int among(m,n)

int m,n;

{ int k,z=0;

do

{k=m%10;

if (n==k) {z=1; break;}

m=m/10;

}while(m!=0);

return(z);

}


1 2 3 4

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

num(x)

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);

}


1 2 3 4

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

wan(x)

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");

}


1 2 3 4

例 6.求图形的面积 。

#include "math.h"

float area1(a,b,c)

float a,b,c;

{ float s,p;

p=(a+b+c)/2;

s=sqrt(p*(p-a)*(p-b)*(p-c));

return(s);

}

float area2(d)

float d;

{ float s;

s=3.14159*(d/2)*(d/2)/2;

return(s);

}


1 2 3 4

main( )

{ float a,b,c,s;

scanf ("%f%f%f",&a,&b,&c);

s=area1(a,b,c)+area2(a)+area2(b)+area2(c);

printf ("%f\n",s);

}


1 2 3 4

8.5 函数的嵌套调用

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

main 函数

{

调用 a 函数

}

a 函数

{

调用 b 函数

return();

}

b 函数

{

return();

}


1 2 3 4

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

int lcm(a,b)

int a,b;

{ int r;

r=gcd(a,b);

return(a*b/r);

}

int gcd(a,b)

int a,b;

{int r;

do

{r=a%b;

a=b;

b=r;}

while (r!=0);

return (a);

}

main( )

{ int x,y;

scanf ("%d%d",&x,&y);

printf ("%d\n",gcd(x,y));

printf ("%d\n",lcm(x,y));

}


1 2 3 4

8.6 函数的递归调用

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

递归问题的特点 :

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

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


1 2 3 4

例 1. 用递归法求 n!

1 (n=1或n=0)

n!=

n*(n-1)! (n>1)

main( )

{ int n;

float fac( ); float y;

scanf ("%d",&n);

if (n<0)

printf ("n<0,data error\n");

else

{ y=fac(n);

printf ("%d!=%15.0f",n,y);

}

}

n!=n*(n-1)!

(n-1)!=(n-1)*(n-2)!

...

2!=2*1!

1!=1


1 2 3 4

float fac(n)

int n;

{ float f;

if (n==1||n==0) f=1;

else f=fac(n-1)*n;

return(f);

}

以n=4为例,执行过程如下:

fac(n)

{ ...

f=fac(1)*2;

return (f);

}

fac(n)

{ ...

f=1;

return (f);

}

fac(n)

{ ...

f=fac(2)*3;

return (f);

}

main( )

{ ...

y=fac(4);

...

}

fac(n)

{ ...

f=fac(3)*4;

return(f);

}

2

1

24

6


1 2 3 4

1 (n=0)

xn = x (n=1)

x*xn-1 (n>1)

例 3.求xn (n>0)

float f(int x,int n)

{ float z;

if(n==0) z=1;

else if (n==1) z=x;

else z=x*f(x,n-1);

return z;

}

main( )

{ int x,n;

float f( );

scanf ("%d%d",&x,&n);

printf ("%d %d %f\n",x,n,f(x,n));

}


1 2 3 4

f(5,4)

float f(x,n)

int x,n;

{ float z;

if (n==0) z=1;

else if (n==1) z=x;

else z=x*f(x,n-1);

return z;

}

float f(x,n)

int x,n;

{ float z;

if (n==0) z=1;

else if (n==1) z=x;

else z=x*f(x,n-1);

return z;

}

5,3

5,1

float f(x,n)

int x,n;

{ float z;

if (n==0) z=1;

else if (n==1) z=x;

else z=x*f(x,n-1);

return z;

}

float f(x,n)

int x,n;

{ float z;

if (n==0) z=1;

else if (n==1) z=x;

else z=x*f(x,n-1);

return z;

}

z=5;

5,2


1 2 3 4

例 4.用递归方法求N阶勒让德多项式的值,递归公式

为 :

1 (n=0)

pn(x)= x (n=1)

(( 2n-1) · x · p n-1(x)-(n-1) · p n-2(x)) /n (n>1)


1 2 3 4

main( )

{ float pn(float,int), x,lyd;

int n;

scanf ("%d %f",&n,&x);

lyd=pn(x,n);

printf ("pn=%f\n",lyd);

}

float pn(x,n)

float x; int n;

{ float temp;

if (n==0) temp=1;

else if (n==1) temp=x;

else temp=((2*n-1)*x*pn(x,n-1)-(n-1)*pn(x,n-2))/n;

return (temp);

}


1 2 3 4

8.7 数组作为函数参数

1、 数组元素作函数实参

对应的形参为简单变量。

int sushu(x)

int x;

{int i,k=1;

if(x==1) k=0

for(i=2;i<=x/2;i++)

if(x%i==0) k=0;

return(k);

}

例 1:求正整数数组 a[10]中的素数.

main( )

{ int a[10],i;

for(i=0;i<10;i++)

scanf("%d",&a[i]);

for(i=0;i<10;i++)

if(sushu(a[i])) printf("%5d",a[i]);

}


1 2 3 4

例2:求正整数数组a[4][4]中的素数.

main( )

{ int a[4][4],i,j;

for(i=0;i<4;i++)

for(j=0;j<4;j++)

{scanf("%d",&a[i][j]);

if(sushu(a[i][j]))

printf("%5d",a[i][j]);}

printf("\n");

}

main( )

{ int a[4][4],i,j;

for(i=0;i<4;i++)

for(j=0;j<4;j++)

scanf("%d",&a[i][j]);

for(i=0;i<4;i++)

for(j=0;j<4;j++)

if(sushu(a[i][j]))

printf("%5d",a[i][j]);}

printf("\n");

}

int sushu(x)

int x;

{int i,k=1;

if(x==1) k=0;

for(i=2;i<=x/2;i++)

if(x%i==0) k=0;

return(k);

}


1 2 3 4

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

a[9]

b[0]

b[1]

b[2]

b[3]

b[4]

b[5]

b[6]

b[7]

b[8]

b[9]

2、数组名可作函数实参

对应的形参为数组名

说明 :

1. 数组名作函数参数,应在主调函数和被调函数中分别定义数组 ;

2. 实参数组与形参数组类型应一致 ;

3. 实参数组与形参数组大小可以一致也可以不一致 。形参数组可以不指定大小。

4. 数组名作函数参数时,是 “ 地址传送 ”。

a

b


1 2 3 4

例3: 数组 score 存放 10 个学生成绩,求平均成绩 。

main( )

{ float score[10],aver,a;

float average(float);

int i;

for (i=0;i<10;i++)

{ scanf ("%f",&a);

score[i]=a;}

aver=average(score);

printf (" %5.2f",aver);

}

float average(array)

float array[10];

{ int i;

float aver,sum=0;

for (i=0;i<10;i++)

sum=sum+array[i];

aver=sum/10;

return(aver);

}

score

array


1 2 3 4

例4 :用选择法对数组中10个整数按升序排序 。

12 3 45 -7 6 17 4 9 2 77

-7 2 3 4 6 9 12 17 45 77

main()

{ int a[10],i;

void sort( );

for (i=0;i<10;i++)

scanf ("%d",&a[i]);

sort(a,10);

for (i=0;i<10;i++)

printf ("%5d",a[i]);

printf ("\n");

}

void sort(array,n)

int array[ ],n;

{ int i,j,k,t;

for (i=0;i<n-1;i++)

{ k=i;

for (j=i+1;j<n;j++)

if (array[j]<array[k]) k=j;

t=array[k];

array[k]=array[i];

array[i]=t;

}

}

a

array


1 2 3 4

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

冒泡法的思路是:将相邻两个数比较,将小的调到前头.

3

1

5

3

第二轮:

(j=1)

依此类推经过

j 轮比较

第一轮:

(j=0)

1

3

5

3

1

5

5

1

5

每轮比较n-j-1次

6

6

0

比较9次

比较8次

8

6

0

6

6

0

8

for(j=0;j<n-1;j++)

-2

8

8

for(i=0;i<n-j-1;i++)

0

8

-2

8

if(a[i]>a[i+1])

-2

9

9

{ t=a[i];

a[i]=a[i+1];

a[i+1]=t; }

9

9

4

-2

9

4

9

9

21

21

4

4

21

21


1 2 3 4

5 3 1 8 6 0 9 -2 21 4

-2 0 1 3 4 5 6 8 9 21

main()

{ int array[10],i;

void sort( );

for (i=0;i<10;i++)

scanf ("%d",&array[i]);

sort(array,10);

for (i=0;i<10;i++)

printf ("%5d",array[i]);

printf ("\n");

}

void sort(a,n)

int a [ ],n;

{ int i,j, t;

for (j=0;j<n-1;j++)

for (i=0;i<n-j-1;i++)

if (a[i]>a[i+1])

{ t=a[i];

a[i]=a[i+1];

a[i+1]=t;

}

}

array

a


1 2 3 4

11 13 10 87 43 41 79 77 76 51 53 63 33 36 47

例 6.产生15个[10,90]上的数放入a数组中,找出其中

的素数放入b数组,并求b数组中元素的和 。

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

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

a

b

11

13

43

41

79

53

47

k=0

1

2

3

4

5

6

7


1 2 3 4

方法一:

#include "stdlib.h"

main()

{int a[15],b[15];

int i,m=0;

for(i=0;i<15;i++)

{ a[i]=random(81)+10;

if(sushu(a[i])==1) {b[m]=a[i]; m++;}

}

printf("the array A is:\n");

for(i=0;i<15;i++)

printf("%5d",a[i]); printf("\n");

printf("the array B is:\n");

for(i=0;i<m;i++)

printf("%5d",b[i]); printf("\n");

printf("\nthe sum of array B is:%d\n",sum(b,m));

}


1 2 3 4

sushu(int k)

{int n,x;

x=1;

if(k==1)x=0;

for(n=2;n<k/2;n++)

if(k%n==0) x=0;

return(x);

}

int sum(b,n)

int b[ ],n;

{int i,s=0;

for(i=0;i<n;i++)

s=s+b[i];

return(s);

}


1 2 3 4

方法二:

#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));

}


1 2 3 4

int sushu(a,b)

int a[ ],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(b,n)

int b[ ],n;

{int i,s=0;

for(i=0;i<n;i++)

s=s+b[i];

return(s);

}


1 2 3 4

3、用多维数组作函数参数

1. 用多维数组元素作函数实参,这点与前述相同。

2. 用多维数组名作函数实参和形参,在被调用函数中对形参数组定义时可以指定每一维的大小, 也可以省略第一维的大小说明。

如:int a[3][10];

int a[][10];

二者都合法完全等价。但是不能把第二维以及其它高维的大小说明省略。


1 2 3 4

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

main( )

{ static int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}};

printf ("max=%d\n",max_value(a));

}

max_value(array)

int array[12];

{ int i,max;

max=array[0];

for(i=0;i<12;i++)

if(array[i]>max) max=array[i];

return(max);

}

max_value(array)

int array[ ][4];

{ int i,j,k,max;

max=array[0][0];

for (i=0;i<3;i++)

for (j=0;j<4;j++)

if (array[i][j]>max) max=array[i][j];

return(max);

}


1 2 3 4

例9: 求 3×3 矩阵转置

23 34 7

23

34

7

2

56

17

21

4

36

2 56 17

21 4 36

交换a[i][j]与a[j][i]的值


1 2 3 4

void turn(array)

int array[][3];

{ int i,j,k;

for (i=0;i<3;i++)

for (j=0;j<i;j++)

{ k=array[i][j];

array[i][j]=array[j][i];

array[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");

}

}


1 2 3 4

8.8 局部变量和全局变量

8.8.1 局部变量

只在函数内有效的变量 。

float f1(a)

int a;

{ int b,c;

......

}

a , b, c 有效

main ( )

{ int m,n;

......

}

m ,n 有效

char f2(x,y)

int x,y;

{ int i,j;

......

}

x ,y ,i ,j 有效


1 2 3 4

说明 :

1. 每个函数中定义的变量,只在定义它的函数中有效;

2. 不同函数可以使用相同名字的变量,但意义不同 ;

3. 形式参数是局部变量 ;

4. 可以在复合语句中定义变量,但它们只在本复合语

句中有效 。

main ( )

{ int a,b;

......

{int c;

c=a+b;

......

}

......

}

c 的有效范围

a , b 的有效范围


1 2 3 4

8.8.2 全局变量

1. 外部变量 :在函数之外定义的变量;

2. 外部变量是全局变量 ;

3. 作用范围:

从定义变量的位置开始到本源文件结束

4. 说明:

(1) 作用 :提供一种函数间数据联系与共享的方法;

(2) 尽量不用全局变量 ;

1) 占内存 2) 藕合性强 3)维护性差

(3) 用 extern 实现先引用 ,后定义 。

(4) 外部变量与局部变量同名时,局部变量屏蔽外

部变量 。


1 2 3 4

int p=1,q=5;

float f1(a)

int a;

{ int b,c;

..…

}

char c1,c2;

char f2(x,y)

int x,y;

{ int i,j;

..…

}

main ( )

{ int m,n;

...... }

p,q的作用范围

c1,c2的作用范围


1 2 3 4

例1 :

int max(int x,int y)

{ int z;

z=x>y?x:y;

return(z);

}

main( )

{extern a,b;

printf ("%d\n",max(a,b));

}

int a=13,b=-8;

外部变量说明

外部变量定义


1 2 3 4

例2:

int a=3,b=5; /*a,b为外部变量*/

max(a,b)

int a,b; /*a,b为局部变量*/

{ int c;

c=a>b? a : b;

return(c);

}

main( )

{ int a=8; /*a为局部变量 */

printf ("%d",max(a,b));

}

形参a,b作用范围

局部变量 a作用范围

全局变量 b作用范围


1 2 3 4

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

分析: 1. 平均分由函数值带回

2. 设max,min为全局变量

score 10 max min

main( )

average( )

array n max min


1 2 3 4

float max,min;

float average(array,n)

float array[ ];int n;

{ int i;

float aver,sum=array[0];

max=min=array[0];

for (i=1;i<n;i++)

{ if (array[i]>max) max=array[i];

else if (array[i]<min) min=array[i];

sum=sum+array[i];

}

aver=sum/n;

return(aver);

}


1 2 3 4

main( )

{ float ave,score[10],x;

int i;

for (i=0;i<10;i++)

{ scanf ("%f",&x);score[i]=x; }

ave=average(score,10);

printf ("%6.2f,%6.2f,%6.2f\n",max,min,ave);

}


1 2 3 4

不用全局变量, 利用数组名作参数,从而达到"双向"

传送数值的目的.

void average(array,n,b)

float array[],b[];int n;

{ int i;

float aver;

b[0]=b[1]=b[2]=array[0];

for (i=1;i<n;i++)

{ if (array[i]>b[0]) b[0]=array[i];

else if (array[i]<b[1]) b[1]=array[i];

b[2]=b[2]+array[i];

}

b[2]=b[2]/n;

}


1 2 3 4

main( )

{ float y[3],score[10],x;

int i;

for (i=0;i<10;i++)

{ scanf ("%f",&x);score[i]=x;}

average(score,10,y);

printf ("max=%6.2f,min=%6.2f,ave=%6.2f\n",y[0],y[1],y[2]);

}


1 2 3 4

8.9 变量的存储类别

8.9.1 动态存储方式与静态存储方式

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

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

1) 函数形参变量 ;

2) 局部变量(未加 static 说明的);

3) 函数调用时的现场保护和返回地址等 。

8.9.2 auto 变量 (局部变量的存储方式)

调用时,系统自动给变量分配存储单元,称这类局部变量为自动变量(auto),其特点:

1) 函数调用后,值不予保留,即释放存储空间 。

2) 再次调用时,原值不能引用 。

8.9.3 用static声明局部变量

1) 函数调用后保留原值,即不释放所占存储空间;

2) 再次调用时,原值在本函数内仍可使用 。


1 2 3 4

调用时初值

调用结束时的值

第几次调用

b

c

b

c

a+b+c

0

0

0

1

1

1

4

5

6

1

2

3

3

4

5

7

8

9

例1 :

int f(a)

int a;

{ int b=0;

static int c=3;

b=b+1;c=c+1

return(a+b+c);

}

局部静态变量

main( )

{ int a=2,i;

for (i=0;i<3;i++)

printf("%d",f(a));

}


1 2 3 4

例2:

float fac(int n)

{ static float f=1;

f=f*n;

return(f);

}

1!= 1.0

2!= 2.0

3!= 6.0

4!= 24.0

5!=120.0

main( )

{ int i;

for(i=1;i<=5;i++)

printf("%d!=%5.1f\n", i,fac(i));

}


1 2 3 4

说明 :

1. 局部静态变量在静态存储区内分配存储单元,

程序整个运行期间不释放 ;

2. 局部静态变量编译时赋初值一次,以后每次调用不再重新赋初值,而是保留上次函数调用结束时的值 ;

3. 局部静态变量定义时不赋初值,编译时自动赋初值 0;

4. 定义全局变量和局部静态变量时,才能对数组初始化 ;

5. 不能被其它函数引用 。


1 2 3 4

运算器

存数

取数

内 存

8.9.4 register 变量

一般情况下,变量的值是放在内存中的,若要用到该变量的值时,由控制器发出指令将内存中的值送到运算器中进行运算(如下示意图)。

如果有些变量使用比较频繁,为了提高执行效率,C语言允许将局部变量的值放在CPU中的寄存器中,需要时直接从寄存器中取数运算,不必再到内存中存取。这种变量叫做“寄存器变量”,用关键字register作声明。看下例(P175例8.19):


1 2 3 4

int fac(int n)

{register int i,f=1; /*定义寄存器变量*/

for (i=1;i<=n;i++)

f=f*i;

return (f);

}

main()

{int i;

for (i=1;i<=5;i++)

printf(“%d!=%d\n”,i,fac(i));

}


1 2 3 4

8.9.5 用extern声明外部变量

外部变量(即全局变量),是在函数的外部定义的,其作用域从变量定义处开始,到本程序文件的末尾。

1. 在一个文件内声明外部变量:在函数外部定义变量。

2. 在多个文件的程序中声明外部变量, 需要用extern 作说明 。看下例:

file2.c

extern int a;

power(n)

int n;

{ int i,y=1;

for(i=1;i<=n;i++)

y=y*a;

return(y);}

file1.c

int a;

main( )

{ int m,k;

k=power(m);

printf("%d",k);

}


1 2 3 4

8.9.6 用static声明外部变量

1) 在函数外部用static定义

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

这样引用是错误的

file2.c

extern int a;

power(n)

int n;

{ int i,y=1;

for(i=1;i<=n;i++)

y=y*a;

return(y);}

file1.c

static int a;

main( )

{ .....

k=power(m);

....}

这种加上static声明、只能用于本文件的外部变量(全局变量)称为静态外部变量。


1 2 3 4

8.9.8 存储类别小结

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

存储类别:

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

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

寄存器变量 (离开参数,值就消失)

(形参可以定义为自动变量或寄存器变量)

全局变量 静态外部变量(只限本文件引用)

外部变量(即非静态外部变量,允许其它文件引用)


1 2 3 4

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

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

自动变量 (本函数内有效)

动态存储寄存器变量(本函数内有效)

形式参数

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

静态存储静态外部变量(本文件内有效)

外部变量(其它文件可引用)

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


1 2 3 4

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

静态局部变量

内存中静态存储区 静态外部变量(函数外部静态变量)

外部变量(可为其它文件引用)

内存中动态存储区 : 自动变量和形式参数

CPU中的寄存器 : 寄存器变量


1 2 3 4

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

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

2)静态外部变量和外部变量的作用域和存在性也一

致, 离开函数后,变量值仍存在,可被引用 。

3)静态局部变量的作用域和存在性不一致,离开函

数后,变量值存在,但不能被引用 。

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

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

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

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


1 2 3 4

8.10 内部函数和外部函数

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

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

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

2、 外部函数 :

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


1 2 3 4

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

1、用Turbo C集成环境建立项目文件

2、用#include 命令


  • Login