C语言程序设计教程(第三版)(微课版)课件 第6章 函数_第1页
C语言程序设计教程(第三版)(微课版)课件 第6章 函数_第2页
C语言程序设计教程(第三版)(微课版)课件 第6章 函数_第3页
C语言程序设计教程(第三版)(微课版)课件 第6章 函数_第4页
C语言程序设计教程(第三版)(微课版)课件 第6章 函数_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

程序设计基础(C)主讲:王娟勤西北农林科技大学信息工程学院模块化程序设计的思想6.1函数的定义和调用6.2函数参数及其数据传递方式6.3第6章函数通过函数返回值传递数据6.4变量的作用域和生存周期6.5函数的嵌套调用和递归调用6.6思考如何实现以下问题?=概述#include"stdio.h"intmain(){inti,m,n,x=1,y=1,z=1;intq;scanf("%d,%d",&m,&n);for(i=1;i<=n;i++)x=x*i;for(i=1;i<=m;i++)y=y*i;for(i=1;i<=n-m;i++)z=z*i;q=x/(y*z);printf("%d\n",q);return0;}=例如:用函数实现

#include"stdio.h"intjch(intn){inti,s=1;for(i=1;i<=n;i++)s=s*i;return(s);}intmain(){inti,m,n,x,y,z;intq;scanf("%d,%d",&m,&n);x=jch(n);y=jch(m);z=jch(n-m);q=x/(y*z);printf("%d\n",q);return0;}=C是模块化程序设计语言C程序结构C是函数式语言必须有且只能有一个名为main的主函数C程序的执行总是从main函数开始,在main中结束函数不能嵌套定义,可以嵌套调用6.1模块化程序设计的思想函数就是用来完成一定功能的一段程序。

把程序需要实现的一些功能分别编写成若干个函数,然后把它们有机地组合成一个完整的程序。

在设计较大的程序时,一般将其分为若干个程序模块,每个模块用来实现一定的功能。在C语言中,模块的功能是由函数来完成的。BAA2A1B2B1A12A11A22A21B12B11B22B21自顶向下、逐步求精的

模块化程序设计方法模块化程序设计基本思想:将一个大的程序按功能分割成一些小模块特点:各模块相对独立、功能单一、结构清晰、接口简单控制了程序设计的复杂性提高软件的可靠性缩短开发周期避免程序开发的重复劳动易于维护和功能扩充开发方法:自上向下,逐步分解,分而治之6.1模块化程序设计的思想函数分类从用户角度标准函数(库函数):由系统提供用户自定义函数从函数形式无参函数有参函数使用库函数应注意:1、函数功能2、函数参数的数目和顺序,及各参数意义和类型3、函数返回值意义和类型4、需要使用的包含文件1.函数定义的一般格式合法标识符函数返回值类型缺省int型无返回值void函数体函数类型函数名(形参类型说明表){

说明部分 语句部分}例有参函数

intmax(intx,inty){intz;z=x>y?x:y;return(z);}例有参函数

intmax(intx,y){intz;z=x>y?x:y;return(z);}例空函数

dummy(){}函数体为空例无参函数

printstar(){printf("**********\n");}或

printstar(void){printf("**********\n");}定义函数:1判断一个数是否素数;2求两点间距离6.2.函数的定义和调用2.

函数的返回值返回语句形式:return(表达式);

return表达式;功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函数说明:函数中可有多个return语句若无return语句,遇}时,自动返回调用函数若函数类型与return语句中表达式值的类型不一致,以前者为准,自动转换------函数调用转换void型函数例无返回值函数

voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}>6.2.函数的定义和调用例函数返回值类型转换intmain(){intmax(float,float);floata,b;intc;scanf("%f,%f",&a,&b);c=max(a,b);printf("Maxis%d\n",c);return0;}intmax(floatx,floaty){floatz;z=x>y?x:y;

return(z);}6.2.函数的定义和调用3.

函数的调用调用形式函数名(实参表);说明:实参与形参个数相等,类型一致,按顺序一一对应6.2.函数的定义和调用调用方式函数语句:例printstar();函数表达式:例m=max(a,b)*2;函数参数:例printf(“%d”,max(a,b));m=max(a,max(b,c));6.2.函数的定义和调用例6-1:定义函数求

,在主函数中输入x及n,调用定义好的函数,输出计算结果。#include<stdio.h>intmypow(intpx,intpn) /*定义mypow函数,函数功能为计算乘方*/{inti;intresult=1;for(i=1;i<=pn;i++)result*=px;returnresult;}intmain(){intx,n;inty;printf("Enterxandn:\n");scanf("%d%d",&x,&n);

y=mypow(x,n); //在主函数中调用mypow,实际参数为x和nprintf("x^n=%d",y);return0;}6.2.函数的定义和调用说明对被调用函数要求:必须是已存在的函数库函数:#include<*.h>用户自定义函数:函数说明函数说明一般形式:函数类型函数名(形参类型[形参名],…..);作用:告诉编译系统函数类型、参数个数及类型,以便检验函数定义与函数说明不同函数说明位置:程序的数据说明部分(函数内或外)下列情况下,可不作函数说明被调用函数定义出现在主调函数之前6.2.函数的定义和调用例函数说明举例floatadd(floatx,floaty){floatz;z=x+y;return(z);}intmain(){floata,b,c;scanf("%f,%f",&a,&b);c=add(a,b);printf("sumis%f",c);return0;}被调函数出现在主调函数之前,不必函数说明intmain(){floatadd(float,float);/*functiondeclaration*/floata,b,c;scanf("%f,%f",&a,&b);c=add(a,b);printf("sumis%f",c);return0;}floatadd(floatx,floaty){floatz;z=x+y;return(z);}6.2.函数的定义和调用形参与实参形式参数:定义函数时函数名后面括号中的变量名实际参数:调用函数时函数名后面括号中的表达式例比较两个数并输出大者intmain(){inta,b,c;

intmax(intx,inty);scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis%d",c);return0;}intmax(intx,inty){intz;z=x>y?x:y;return(z);}形参实参6.3函数参数及其数据传递方式6.3函数参数及其数据传递方式说明:实参必须有确定的值形参必须指定类型形参与实参类型一致,个数相同若形参与实参类型不一致,自动按形参类型转换———函数调用转换形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放形参与实参形式参数:定义函数时函数名后面括号中的变量名实际参数:调用函数时函数名后面括号中的表达式6.3函数参数及其数据传递方式参数传递方式

1.变量的传递变量值的传递方式方式:函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值特点:形参与实参占用不同的内存单元单向传递形参实参变量变量数组元素表达式6.3函数参数及其数据传递方式例交换两个数voidswap(inta,intb);#include<stdio.h>intmain(){inta=10,b=20;printf(“a=%d,\tb=%d\n",a,b);printf("swapped:\n");

swap(a,b);printf(“a=%d,\tb=%d\n",a,b);return0;}voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}参数传递方式

1.变量的传递变量值的传递方式变量地址的传递方式方式:函数调用时,为形参分配单元,并将实参变量的地址复制到形参中;实参和形参指向同一存储空间。特点:形参与实参指向相同的内存单元双向传递形参实参指针变量地址指针6.3函数参数及其数据传递方式voidswap(int*x,int*y){intp;p=*x;*x=*y;*y=p;}intmain(){inta=10,b=20;printf(“a=%d,\tb=%d\n",a,b);printf("swapped:\n");swap(&a,&b);printf("\n%d,%d\n",a,b);return0;}运行结果:20,10例交换两个数交换指针形参指向的值运行结果:10,20voidswap(int*x,int*y){int*p;p=x;x=y;y=p;}intmain(){inta=10,b=20;printf(“a=%d,\tb=%d\n",a,b);printf("swapped:\n");swap(&a,&b);printf("\n%d,%d\n",a,b);return0;}交换指针形参的值例交换两个数参数传递方式

1.变量的传递

2.一维数组的传递数组名作函数参数地址传递形参数组大小(多维数组第一维)可不指定形参实参数组(编译时会编译成指针)指针数组名指针6.3函数参数及其数据传递方式例求学生的平均成绩#include<stdio.h>

floataverage(intstu[10],intn);intmain(){intscore[10],i;floatav;printf("Input10scores:\n");for(i=0;i<10;i++)scanf("%d",&score[i]);av=average(score,10);printf("Averageis:%.2f",av);return0;}floataverage(int

stu[10],intn){inti;floatav,total=0;for(i=0;i<n;i++)total+=stu[i];av=total/n;returnav;}实参用数组名形参用数组定义,

intstu[]..2109score562312….….88stu6.3函数参数及其数据传递方式例求学生的平均成绩#include<stdio.h>

floataverage(intstu[10],intn);intmain(){intscore[10],*p,i;floatav;

p=score;printf("Input10scores:\n");for(i=0;i<10;i++)scanf("%d",&score[i]);av=average(p,10);printf("Averageis:%.2f",av);return0;}floataverage(int

stu[10],intn){inti;floatav,total=0;for(i=0;i<n;i++)total+=stu[i];av=total/n;returnav;}实参用指针形参用数组定义,

intstu[]..2109score562312….….88stu6.3函数参数及其数据传递方式例求学生的平均成绩#include<stdio.h>

floataverage(int*stu,intn);intmain(){intscore[10],i;floatav;printf("Input10scores:\n");for(i=0;i<10;i++)scanf("%d",&score[i]);av=average(score,10);printf("Averageis:%.2f",av);return0;}floataverage(int*stu,intn){inti;floatav,total=0;for(i=0;i<n;i++)total+=stu[i];av=total/n;returnav;}实参用数组名形参用指针..2109score562312….….88stu6.3函数参数及其数据传递方式例求学生的平均成绩#include<stdio.h>

floataverage(int*stu,intn);intmain(){intscore[10],*p,i;floatav;

p=score;printf("Input10scores:\n");for(i=0;i<10;i++)scanf("%d",&score[i]);av=average(p,10);printf("Averageis:%.2f",av);return0;}floataverage(int*stu,intn){inti;floatav,total=0;for(i=0;i<n;i++,stu++)total+=*stu;av=total/n;returnav;}实参用指针形参用指针..2109score562312….….88stu6.3函数参数及其数据传递方式例数组排序----简单选择排序voidsort(intarray[],intn){inti,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; if(k!=i) {t=array[i]; array[i]=array[k]; array[k]=t; }}}intmain(){inta[10],i;for(i=0;i<10;i++) scanf("%d",&a[i]);

sort(a,10);for(i=0;i<10;i++)printf("%d",a[i]);printf("\n");return0;}0123456789a4968573299927137688arraykjjjkjkjjjjj949i=06.3函数参数及其数据传递方式下面程序的功能是将形参x的值转换为6进制数,所得的6进制数放在一个一维数组中返回,6进制数的最低位放在下标为0的元素中,请完善程序。fun(intx,intb[]){intk=0,r;do{r=x%(1);b[k++]=r;x/=(2);}while(x);}练习:参数传递方式

1.变量的传递

2.一维数组的传递

3.二维数组的传递形参实参数组行指针数组名行指针

调用函数如果要将二维数组整体传递给被调用函数,可以用数组名或指向该数组的行指针作为实参,而被调用函数则用数组或指向二维数组的行指针作为形参。6.3函数参数及其数据传递方式#include<stdio.h>#defineM4#defineN5

intmain()/*主函数main()*/{intscr[M][N],(*ph)[N]=scr,max_value(intarray[M][N]);inti,j,smax;srand((unsigned)time(NULL));//产生时间序列的随机数种子

printf("二维数组初始值:\n");for(i=0;i<M;i++){for(j=0;j<N;j++) {ph[i][j]=rand()*100/32767;//生成0~100之间的随机整数

printf("%4d",ph[i][j]);}printf("\n");}smax=max_value(ph);//实参为行指针phprintf("\n二维数组中的最大值:%d\n",smax);return0;}【例】编制程序求二维数组中的最大元素。也可用smax=max_value(scr)/*子函数max_value()*/intmax_value(intarray[M][N])//形参为二维数组array{inti,j,max;max=array[0][0];for(i=0;i<M;i++)for(j=0;j<N;j++)if(max<array[i][j])max=array[i][j];return(max);//返回值为二维数组各元素的最大值}

本例max_value()用二维数组array作形参,在参数传递时,该数组被自动转换成行指针并复制实参指针ph中的地址值,从而指向main()函数中的数组scr。所以,main()中的scr[i][j]与max_value()中的array[i][j]表示的是同一存储空间。max_value(intarray[4][5])或max_value(intarray[M][N])max_value(intarray[][5])或max_value(intarray[][N])max_value(int(*array)[5])或max_value(int(*array)[N])参数传递方式

1.变量的传递

2.一维数组的传递

3.二维数组的传递

4.字符数组的传递6.3函数参数及其数据传递方式例用函数调用实现字符串复制(1)用字符数组作参数(2)用字符指针变量作参数aIamateaceh\0r.fromabyuarasutndetoboet.\0Iaaeceh\0r.t.\0mtavoidcopy_string(charfrom[],charto[]){inti=0;while(from[i]!='\0'){to[i]=from[i]; i++;}to[i]='\0';}intmain(){chara[]="Iamateacher.";charb[]="Youareastudent.";printf("string_a=%s\nstring_b=%s\n",a,b);

copy_string(a,b);printf("\nstring_a=%s\nstring_b=%s\n",a,b);return0;}voidcopy_string(char*from,char*to){for(;*from!='\0';from++,to++)*to=*from;*to='\0';}intmain(){chara[]="Iamateacher.";charb[]="Youareastudent.";printf("string_a=%s\nstring_b=%s\n",a,b);

copy_string(a,b);printf("\nstring_a=%s\nstring_b=%s\n",a,b);return0;}练习:1.编写函数,统计字符串中数字字符的个数,在主函数中调用该函数。2.从键盘输入一个八进制数组字符串,编写程序,将输入的数据转换为十进制后输出。参数传递方式

1.变量的传递

2.一维数组的传递

3.二维数组的传递

4.字符数组的传递5.函数的传递6.3函数参数及其数据传递方式用函数指针变量作函数参数例用函数指针变量作参数,求最大值、最小值和两数之和intmain(){inta,b,max(int,int),min(int,int),add(int,int);voidprocess(int,int,int(*fun)());scanf("%d,%d",&a,&b);process(a,b,max);process(a,b,min);process(a,b,add);return0;}voidprocess(intx,inty,int(*fun)()){intresult;result=(*fun)(x,y);printf("%d\n",result);}max(intx,inty){printf(“max=”);return(x>y?x:y);}min(intx,inty){printf(“min=”);return(x<y?x:y);}add(intx,inty){printf(“sum=”);return(x+y);}6.3函数参数及其数据传递方式参数传递方式

1.变量的传递

2.一维数组的传递

3.二维数组的传递

4.字符数组的传递5.函数的传递6.main函数带参数6.3函数参数及其数据传递方式命令行:在操作系统状态下,为执行某个程序而键入的一行字符命令行一般形式:命令名

参数1参数2………参数nmain(intargc,char*argv[]){………}命令行参数传递带参数的main函数形式:C:\TC>copy[.exe]

source.c

temp.c有3个字符串参数的命令行命令行中参数个数元素指向命令行参数中各字符串首地址形参名任意命令行实参main(形参)系统自动调用main函数时传递第一个参数:main所在的可执行文件名6.命令行参数6.3函数参数及其数据传递方式例输出命令行参数/*test.c*/#include<stdio.h>intmain(intargc,char*argv[]){while(argc>1){++argv;printf("%s\n",*argv);--argc;}return0;}#include<stdio.h>intmain(intargc,char*argv[]){while(argc-->0)printf("%s\n",*argv++);return0;}1.编译、链接test.c,生成可执行文件test.exe2.在DOS状态下运行(test.exe所在路径下)例如:C:\TC>test

hello

world!运行结果:helloworld!运行结果:testhelloworld!argv[0]argv[1]argv[2]char*argv[]worldtesthelloargvargc=3#include<stdio.h>#include<stdlib.h>intmain(intargc,char*argv[]){inti,sum=0;for(i=0;i<argc;i++){sum=sum+atoi(argv[i]);}printf("sum=%d\n",sum);return0;}带参数的main函数命令行中参数个数元素指向命令行参数中各字符串首地址6.3函数参数及其数据传递方式6.4通过函数返回值传递数据用返回值方式向调用函数只能返回一个数据。根据返回数据的类型,返回值传递的数据可分为传值和传地址两类。如果函数返回值是某个内存对象的地址,该函数称为返回指针的函数。返回指针的函数定义格式如下:

类型说明符*函数名(形参表){

函数体;}例:编写函数pmax求两个整数的最大数。#include<stdio.h>int*pmax(int*,int*);//函数声明intmain(){inta,b;int*p;scanf("%d%d",&a,&b);p=pmax(&a,&b);//函数调用printf("maxvalueis:%d",*p);return0;}

int*pmax(int*pa,int*pb){if(*pa>=*pb)returnpa;returnpb;}练习:1.写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果,两个整数由键盘输入。2.写一函数,将两个字符串连接,在主程序中调用测试所编写的函数。3.输入3个学生5门课的成绩,分别用函数求:①每个学生平均分;②每门课的平均分;③找出最高分所对应的学生和课程。内存…….main(){inta;a=10;printf("%d",a);}编译或函数调用时为其分配内存单元10程序中使用变量名对内存操作变量是对程序中数据的存储空间的抽象20002001200220036.5变量的作用域和生存周期变量的属性数据类型:变量所持有的数据的性质(操作属性)存储类型:数据在内存中存储的方式(静态存储、动态存储)变量的存储类型auto-----自动型register-----寄存器型static------静态型extern-----外部型变量是对程序中数据的存储空间的抽象变量定义格式:[存储类型]数据类型变量表;如:intsum;

auto

inta,b,c;

registerinti;

static

floatx,y;6.5变量的作用域和生存周期1.变量的作用域局部变量全局变量6.5变量的作用域和生存周期局部变量与全局变量局部变量---内部变量定义:在函数内定义,只在本函数内有效说明:main中定义的变量只在main中有效不同函数中同名变量,占不同内存单元形参属于局部变量可在复合语句中定义有效的变量局部变量可用存储类型:autoregisterstatic(默认为auto)floatf1(inta){intb,c;…….}charf2(intx,inty){inti,j;……}intmain(){intm,n;…….}a,b,c有效x,y,i,j有效m,n有效例不同函数中同名变量intmain(){inta,b;a=3;b=4;printf("main:a=%d,b=%d\n",a,b);sub();printf("main:a=%d,b=%d\n",a,b);return0;}sub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}例复合语句中变量#include<stdio.h>intmain(){floata,b;scanf("%f,%f",&a,&b);if(a>b){floatt;t=a;a=b;b=t;}printf("%5.2f,%5.2f\n",a,b);return0;}例不同函数中同名变量intmain(){inta,b;a=3;b=4;printf("main:a=%d,b=%d\n",a,b);sub();printf("main:a=%d,b=%d\n",a,b);return0;}sub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=4变量定义可以出现在函数内,亦可出现在函数外或者是函数的参数中。按照变量定义语句出现的位置,可以分为:全局变量---外部变量定义:在函数外定义,可为本文件所有函数共用有效范围:从定义变量的位置开始到本源文件结束全局变量可以通过说明改变其作用域:

extern数据类型变量表;intp=1,q=5;floatf1(inta){intb,c;…….}intf3(){…..}charc1,c2;charf2(intx,inty){inti,j;……}intmain(){intm,n;…….}c1,c2的作用范围p,q的作用范围intp=1,q=5;floatf1(inta){intb,c;…….}intf3(){…..}charc1,c2;charf2(intx,inty){inti,j;……}intmain(){intm,n;…….}c1,c2的作用范围p,q的作用范围externcharc1,c2;externcharc1,c2;c1,c2的作用范围扩展后c1,c2的作用范围扩展后例用extern扩展外部变量作用域运行结果:1:x=0y=02:x=135y=2463:x=135y=246intmain(){voidgx(),gy();

externintx,y;printf(“1:x=%d\ty=%d\n”,x,y);y=246;gx();gy();return0;}voidgx(){externintx,y;x=135;printf(“2:x=%d\ty=%d\n”,x,y);}intx,y;voidgy(){printf(“3:x=%d\ty=%d\n”,x,y);}例:编写一函数,求出10个学生成绩的最高分、最低分和平均成绩(使用全局变量的方法)。#include<stdio.h>floatmax=0,min=0;//定义全局变量max和minfloatgetAve(floatarr[],intn)//定义getAve函数{ inti; floatsum=0;

max=min=arr[0]; for(i=0;i<n;i++) { sum+=arr[i]; if(arr[i]>max)max=arr[i];//求最高分

elseif(arr[i]<min)min=arr[i];//求最低分

} returnsum/n;//return语句返回计算到的平均分}6.5变量的作用域和生存周期intmain(){ floatavescore,score[10]; inti; printf("Enterthescores:\n"); for(i=0;i<10;i++)scanf("%f",&score[i]); avescore=getAve(score,10); printf("max=%f,min=%f,ave=%f",max,min,avescore); return0;}6.5变量的作用域和生存周期#include<stdio.h>floatgetAve(floatarr[],intn,float*max,float*min)//定义函数{ inti; floatsum=0;

*max=*min=arr[0]; for(i=0;i<n;i++) { sum+=arr[i]; if(arr[i]>*max)*max=arr[i];//求最高分

elseif(arr[i]<*min)*min=arr[i];//求最低分

} returnsum/n;//return语句返回计算到的平均分}例:编写一函数,求出10个学生成绩的最高分、最低分和平均成绩(不使用全局变量的方法)。6.5变量的作用域和生存周期int

main(){ floatavescore,score[10],maxscore,minscore; inti; printf("Enterthescores:\n"); for(i=0;i<10;i++)scanf("%f",&score[i]); avescore=getAve(score,10,&maxscore,&minscore); printf("max=%f,min=%f,ave=%f",maxscore,minscore,avescore); return0;}6.5变量的作用域和生存周期全局变量---外部变量定义:在函数外定义,可为本文件所有函数共用有效范围:从定义变量的位置开始到本源文件结束全局变量可以通过说明改变其作用域:

extern数据类型变量表;

全局变量可以被不同的文件共享。

file1.c

file2.cinta;

externinta;文件1定义的外部变量。

文件2通过说明使用文件1的外部变量。static如果只希望在本文件中使用,可以加static说明。

此变量为静态全局变量。6.5变量的作用域和生存周期全局变量---外部变量定义:在函数外定义,可为本文件所有函数共用有效范围:从定义变量的位置开始到本源文件结束

定义

说明次数:只能1次可说明多次位置:所有函数之外函数内或函数外分配内存:分配内存,可初始化不分配内存,不可初始化全局变量可以通过说明改变其作用域:

extern数据类型变量表;外部变量定义与外部变量说明不同

全局变量可以被不同的文件共享。6.5变量的作用域和生存周期全局变量---外部变量定义:在函数外定义,可为本文件所有函数共用有效范围:从定义变量的位置开始到本源文件结束>全局变量可以通过说明改变其作用域:

extern数据类型变量表;外部变量定义与外部变量说明不同若外部变量与局部变量同名,则外部变量被屏蔽

全局变量可以被不同的文件共享。6.5变量的作用域和生存周期inta=3,b=5;max(inta,intb){intc;c=a>b?a:b;return(c);}intmain(){inta=8;printf("max=%d",max(a,b));return0;}例外部变量与局部变量运行结果:max=86.5变量的作用域和生存周期全局变量---外部变量定义:在函数外定义,可为本文件所有函数共用有效范围:从定义变量的位置开始到本源文件结束

应尽量少使用全局变量,因为:全局变量在程序全部执行过程中占用存储单元降低了函数的通用性、可靠性,可移植性降低程序清晰性,容易出错全局变量可以通过说明改变其作用域:

extern数据类型变量表;外部变量定义与外部变量说明不同若外部变量与局部变量同名,则外部变量被屏蔽

全局变量可以被不同的文件共享。全局变量可用存储类型:static、extern6.5变量的作用域和生存周期2.变量的生存期

变量生存期是由变量的存储类型决定的。C语言提供了变量的四种存储类型,分别用关键字表示如下:

autoregisterstaticextern

从变量存在的时间角度来看,将变量分为两类:静态存储变量和动态存储变量。6.5变量的作用域和生存周期动态变量与静态变量存储方式静态存储:程序运行期间分配固定存储空间动态存储:程序运行期间根据需要动态分配存储空间内存映像生存期静态变量:从程序开始执行到程序结束动态变量:从包含该变量定义的函数开始执行至函数执行结束6.5变量的作用域和生存周期自动变量(auto)“自动”体现在进入语句块时自动申请内存,退出时自动释放内存标准定义格式

[auto]

类型名变量名;动态局部变量缺省的存储类型不初始化时,值是随机不确定的动态变量6.5变量的作用域和生存周期例auto变量的作用域intmain(){intx=1;voidprt(void);

{

intx=3;prt();printf(“2ndx=%d\n”,x);}printf(“1stx=%d\n”,x);return0;}voidprt(void){intx=5;printf(“3thx=%d\n”,x);}运行结果:3thx=52ndx=31stx=1x=1作用域x=1作用域x=3作用域x=5作用域6.5变量的作用域和生存周期寄存器变量(register)CPU的寄存器很有限、但速度极快。对使用频率比较高的变量可以声明为register,以提高程序执行的效率。register类型名变量名;registerinti;

现代编译器有能力自动把普通变量优化为寄存器变量,并且可以忽略用户的指定,所以一般无需特别声明变量为register

。动态变量6.5变量的作用域和生存周期静态变量(static)一般的内部变量在函数退出后失效,再次进入函数,重新分配变量存储空间。静态变量在变量类型前面用static修饰staticinti;变量的值可以保存到下次进入函数。6.5变量的作用域和生存周期intmain(){voidincrement(void);increment();increment();increment();return0;}voidincrement(void){intx=0;x++;printf(“%d\n”,x);}例局部静态变量值具有可继承性运行结果:111intmain(){voidincrement(void);increment();increment();increment();return0;}voidincrement(void){staticintx=0;x++;printf(“%d\n”,x);}运行结果:1236.5变量的作用域和生存周期例文件file1.cinta;intmain(){…….…….f2;…….f1;…….}f1(){autointb;………f2;……..}f2(){staticintc;………}C作用域b作用域a作用域mainf2f1mainf1f2maina生存期:b生存期:c生存期:⑴从作用域角度分,有局部变量和全局变量,采用的存储类别如下:①局部变量

自动变量、静态局部变量、寄存器变量、形参。②全局变量

静态外部变量、外部变量存储类别小结⑵从变量存在的时间(生存期)来区分,有动态存储和静态存储两种类型。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元。

动态存储:自动变量、寄存器变量、形式参数静态存储:静态局部变量、静态外部变量、外部变量(3)从变量值存放的位置来区分,可分为:内存中静态存储区:静态局部变量、静态外部变量、外部变量内存中动态存储区:自动变量和形式参数CPU中的寄存器:寄存器变量存储类别小结(4)static对局部变量和全局变量的作用不同。对局部变量来说,它使变量由动态存储方式改变为静态存储方式。而对全局变量来说,它使变量局部化,但仍为静态存储方式。从作用域角度看,凡有static声明的,其作用域都是局限的,或者是局限于本函数内,或者局限于本文件内。静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存储区动态区存储区寄存器局部变量外部变量作用域定义变量的函数或复合语句内本文件其它文件局部变量默认为auto型register型变量个数受限,且不能为long,double,float型局部static变量具有全局寿命和局部可见性局部static变量具有可继承性extern不是变量定义,可扩展外部变量作用域register局部staticauto外部static外部存储类别存储类别小结6.6函数的嵌套调用和递归调用函数的嵌套调用:在被调函数中又调用其他函数。6.6函数的嵌套调用和递归调用

#include<stdio.h>intsof(int);//声明函数sofintfactor(int);//声明函数factorintmain(){intn;intsum;printf("inputn:\n");scanf("%d",&n);sum=sof(n);//在主函数中调用函数sofprintf("theresultis:%d\n",sum);return0;}6.6函数的嵌套调用和递归调用intsof(intm){inti;ints=0;for(i=1;i<=m;i++)s=s+factor(i);//调用factor函数,求阶乘

returns;}intfactor(intm){intfa=1;inti;for(i=1;i<=m;i++)fa=fa*i;returnfa;}6.6函数的嵌套调用和递归调用函数的递归调用:函数直接或间接的调用自身叫函数的递归调用f()调f调f2调f1f1()f2()说明每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出intf(intx){inty,z;……

z=f(y);…….return(2*z);}intf1(intx){inty,z;……

z=f2(y);…….return(2*z);}intf2(intt){inta,c;……

c=f1(a);…….return(3+c);}例求n的阶乘

#include<stdio.h>intfactor(intn){if(n==0||n==1)return(1);elsereturn(n*factor(n-1));}intmain(){intx,factor();scanf("%d",&x);printf("%d!=%ld\n",x,factor(x));return0;}

回推过程递推过程factor(4)=4*factor(3)=24factor(2)=2*factor(1)=2factor(3)=3*factor(2)=6

factor(5)=5*factor(4)factor(4)=4*factor(3)factor(1)=1factor(2)=2*factor(1)factor(3)=3*factor(2)factor(5)=5*factor(4)=120n=5时n!递归算法执行过程intfactor(intn){if(n==0||n==1)return(1);elsereturn(n*factor(n-1));}【例】利用递归实现将一个数据各位上的数字逆序输出,如将12345逆序输出54321。#include<stdio.h>voidreverse(intn){if(n>0){printf("%d",n%10);reverse(n/10);}}intmain(){intx;scanf("%d",&x);reverse(x);return0;}构成递归的条件(1)具备递归结束条件及结束时的值(递归出口);(2)能用递归形式表示,并且递归向终止条件发展(递归体);

递归算法通常通常把一个大的复杂问题层层转化为一个或多个与原问题相似的规模较小的问题来求解。递归策略只需少量的代码就可以描述出解题过程所需要的多次重复计算,大大减少了算法的代码量。原问题小问题1小问题2小问题k…一般来说,能够用递归解决的问题应该满足以下3个条件:需要解决的问题可以转化为一个或多个子问题来求解,而这些子问题的求解方法与原问题完全相同,只是在数量规模上不同。递归调用的次数必须是有限的。必须有结束递归的条件来终止递归。6.6函数的嵌套调用和递归调用快速排序

从待排序列中任取一个元素(例如取第一个)作为中心,所有比它小的元素一律前放,所有比它大的元素一律后放,形成左右两个子表;然后再对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个。此时便为有序序列了。优点:因为每趟可以确定不止一个元素的位置,而且呈指数增加,所以特别快!前提:顺序存储结构

基本思想:lowhigh设arr[s]=52为枢轴

将arr[high]和枢轴的关键字进行比较,从high开始找出第一个小于枢轴的关键字,进行交换

将arr[low]和枢轴的关键字进行比较,从low开始找出第一个大于枢轴的关键字,进行交换high23low80high14low52例如pivot=52lowhighhighhighlow1.这种不断划分子表的过程,计算机如何自动实现?编程时:①每一趟的子表的形成是采用从两头向中间交替式逼近法;②由于每趟中对各子表的操作都相似,主程序可采用递归算法。while(low<high){

//从表的两端交替地向中间扫描

while(low<high&&

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论