欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    c语言 课件第5章.ppt

    • 资源ID:5341650       资源大小:1.89MB        全文页数:80页
    • 资源格式: PPT        下载积分:10金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要10金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    c语言 课件第5章.ppt

    1,第5章 函数,C 语言程序设计,2023/6/27,2023/6/27,2,第5章 函数与预处理命令,5.1 概述5.2 函数的定义与调用5.3 数组作函数参数5.4 函数的嵌套调用和递归调用5.5 局部变量和全局变量及其作用域5.6 变量的存储类别及变量的生存期5.7 函数的存储分类,2023/6/27,3,5.1 概述,程序结构清晰,可读性好。减少重复编码的工作量。可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。,使用函数的好处,2023/6/27,4,【例5.1】求一个整数的立方。,int cube(int x)/*函数定义*/return(x*x*x);main()int f,a;printf(nEnter an integer number:);scanf(%d,程序运行情况如下:Enter an integer number:22*2*2=8,函数调用,程序的执行总是从main函数开始,2023/6/27,5,一个C源程序可以由一个或多个源程序文件组成。C编译系统在对C源程序进行编译时是以文件为单位进行的。一个C源程序文件可以由一个或多个函数组成。所有函数都是独立的。主函数可以调用其它函数,其它函数可以相互调用。在一个C程序中,有且仅有一个主函数main。C程序的执行总是从main函数开始,调用其它函数后最终回到main函数,在main函数中结束整个程序的运行。,说明,2023/6/27,6,函数的种类,从函数定义形式分:有参函数:在主调(用)函数和被调(用)函数之间通过参数进行数据传递,如:int cube(int x)无参函数:如:getchar()在调用无参函数时,主调函数不需要将数据传递给无参函数。,从使用的角度看:标准函数(库函数)库函数是由系统提供的。如:getchar()、sin(x)等。在程序中可以直接调用它们。附录A列出了C的部分库函数。用户自定义函数。如:例7.1中的cube函数。,2023/6/27,7,【例5.2】无参函数的定义与调用。,void welcome()printf(*n);printf(Welcome to China n);printf(*n);main()welcome();,程序的输出结果如下:*Welcome to China*,2023/6/27,8,5.2.1 函数的定义,函数定义的一般形式,函数类型 函数名(类型名 形式参数1,)说明语句 执行语句,例如:求两个数的最大值。int max(int x,int y)int z;z=x y?x:y;return(z);,类型省略时默认为int类型,2023/6/27,9,int max(x,y)int x,y;int z;z=x y?x:y;return(z);,int max(x,y)int x,y;或int max(int x,y),或int max(x,y)int x,y,z;z=x y?x:y;return(z);,花括号中也可以为空,这种函数叫空函数。不能在函数体内定义其他函数,即函数不能嵌套定义。,形参也可以这样定义,2023/6/27,10,函数名(实参表列),在C语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数调用。例如:welcome();if(iabs(a)max)max=iabs(a);m=max(c,max(a,b);,5.2.2 函数的调用,函数调用的一般形式:,2023/6/27,11,int sum100()int i,t=0;for(i=1;i=100;i+)t+=i;return(t);main()int s;s=sum100();printf(%dn,s);,程序输出结果:5050,int sum(int x)int i,t=0;for(i=1;i=x;i+)t+=i;return(t);main()int s;s=sum(100);printf(%dn,s);,【例5.3】求1100的累加和。,思考:两个程序有何不同,程序输出结果:5050,?,2023/6/27,12,void swap(int x,int y)int z;z=x;x=y;y=z;printf(nx=%d,y=%d,x,y);main()int a=10,b=20;swap(a,b);printf(na=%d,b=%dn,a,b);,5.2.3 函数参数与函数的返回值,1函数的形式参数与实际参数,程序输出结果:x=20,y=10a=10,b=20,形式参数(形参),实际参数(实参),【例5.4】编一程序,将主函数中的两个变量的值传递给swap函数中的两个形参,交换两个形参的值。,单向值传递,2023/6/27,13,有关形参和实参的说明:,当函数被调用时才给形参分配内存单元。调用结束,所占内存被释放。实参可以是常量、变量或表达式,但要求它们有确定的值。实参与形参类型要一致,字符型与整型可以兼容。实参与形参的个数必须相等。在函数调用时,实参的值赋给与之相对应的形参。“单向值传递”。,注意:在TC中,实参的求值顺序是从右到左。,2023/6/27,14,【例5.5】函数调用中实参的求值顺序。,void fun(int a,int b)printf(a=%d,b=%dn,a,b);main()int m=5;fun(3+m,m+);,程序输出结果:a=9,b=5,2023/6/27,15,2.函数的类型与函数的返回值,说明:函数的类型决定了函数返回值的类型。若省略函数的类型,系统默认其为int型。无返回值的函数应将其类型定义为void(空)类型。,函数的类型,【例5.6】输出两个数中的大数。,max(int x,int y)int z;z=xy?x:y;return(z);/*返回z的值*/main()int a,b,c;scanf(%d,%d,2023/6/27,16,函数的返回值是通过return语句带回到主调函数的,功能:终止函数的运行,返回主调函数,若有返回值,将返回值带回主调函数。,说明:若函数没有返回值,return语句可以省略。return语句中的表达式类型一般应和函数的类型一致,如果不一致,系统自动将表达式类型转换为函数类型。,函数的返回值,return 语句格式:,return(表达式);或 return 表达式;或 return;,2023/6/27,17,【例5.8】计算并输出圆的面积。,s(int r)return 3.14*r*r;main()int r,area;scanf(%d,自动转换为int型,思考:若要得到单精度实型的圆面积,程序应如何修改,程序运行情况如下:212,?,2023/6/27,18,5.2.4 对被调函数的声明和函数原型,变量要先定义后使用,函数也如此。即被调函数的定义要出现在主调函数的定义之前。如swap函数:允许整型函数(且参数也是整型)的定义出现在主调函数之后。如max函数:如果非整型函数在主调函数之后定义,则应在主调函数中或主调函数之前对被调函数进行声明。,void swap(int x,int y)main()swap(a,b);,main()c=max(a,b);max(int x,int y),2023/6/27,19,对被调函数进行声明的一般形式,函数类型 函数名(参数类型1 参数名1,);或 函数类型 函数名(参数类型1,参数类型2,);,思考:以下哪种情况需要在主调函数中对被调函数声明被调函数定义在前,主调函数定义在后。主调函数定义在前,被调函数定义在后,且被调函数的类型不是整型的。被调函数定义在后,但被调函数的类型是整型。,第二种形式省略了参数名,此种形式也称为函数的原型。,?,2023/6/27,20,main()void calc(float x,float y,char opr);float a,b;char opr;printf(nInput expression:);scanf(%f%c%f,对被调函数的声明,【例5.9】计算并输出两个数的和、差、积、商。,2023/6/27,21,图 5.2 验证哥德巴赫猜想,【例5.10】哥德巴赫猜想之一是任何一个大于5的偶数都可以表示为两个素数之和。验证这一论断。,2023/6/27,22,#include math.hint prime(int n);main()int a,b,c,n;scanf(%d,/*穷举法判断素数*/int prime(int n)int i;for(i=2;i=sqrt(n);i+)if(n%i=0)return 0;return 1;,可以在main函数的前面对prime函数进行声明。实际上,该声明可以省略,为什么?,程序如下:,2023/6/27,23,5.3 数组作函数参数,5.3.1 一维数组元素作函数参数,main()int a5,i,m;for(i=0;i5;i+)scanf(%d,【例5.11】求5个数中的最小值。,int min(int x,int y)return(xy?x:y);,用打擂台方法求最小值。m相当于擂主,2023/6/27,24,5.3.2 一维数组名作函数参数,数组名表示数组在内存中的起始地址。例如:数组a在内存中从2000地址开始存放,则a的值为2000。2000是地址值,是指针类型的数据(第8中将介绍指针类型),不能把它看成是整型或其他类型数据。实参是数组名,形参也应定义为数组形式,形参数组的长度可以省略,但 不能省,否则就不是数组形式了。【例5.12】用冒泡法将10个整数排序。,2023/6/27,25,void sort(int b,int n);void printarr(int b);main()int a10=11,22,63,97,58,80,45,32,73,36;printf(Before sort:n);printarr(a);sort(a,10);printf(After sort:n);printarr(a);,void printarr(int b10)int i;for(i=0;i10;i+)printf(%5d,bi);printf(n);,void sort(int b,int n)int i,j,t;for(i=1;ibj+1)t=bj;bj=bj+1;bj+1=t;,2023/6/27,26,图5.3 调用sort函数,2000,b,形参 b 实际是一个可以存放地址的变量,a:2000,实参赋给形参,2023/6/27,27,#include stdio.hmain()void scat(char str1,char str2);char s150,s250;int i,k;printf(Input s1:);gets(s1);printf(Input s2:);gets(s2);scat(s1,s2);printf(Output s1:%sn,s1);printf(Output s2:%sn,s2);,void scat(char str1,char str2)int i=0,k=0;while(str1i!=0)i+;while(str2k!=0)str1i=str2k;i+;k+;str1i=0;,scat函数还可简化为:void scat(char str1,char str2)int i=0,k=0;while(str1i)i+;while(str1i+=str2k+);,【例5.13】编程序,实现字符串连接。,2023/6/27,28,以二维数组为例。二维数组名作实参时,对应的形参也应该定义为一个二维数组形式。对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。【例5.14】编程序,将矩阵转置。设转置前为a矩阵,转置后为b矩阵,如下所示:,思路:将a00b00,a01 b10,a02b20,a10b01,aijbji,。,5.3.3 多维数组作函数参数,2023/6/27,29,void turn();main()int a34=1,2,3,4,5,6,7,8,9,10,11,12;int i,j,b43;turn(a,b);printf(array b:n);for(i=0;i4;i+)for(j=0;j3;j+)printf(%5d,bij);printf(n);,/*矩阵转置函数*/void turn(int arra 4,int arrb 3)int r,c;for(r=0;r3;r+)for(c=0;c4;c+)arrbcr=arrarc;,2023/6/27,30,5.4 函数的嵌套调用和递归调用,main函数 调用函数 A;,函数 A 调用函数 B;,函数 B,5.4.1 函数的嵌套调用,2023/6/27,31,【例5.15】函数的嵌套调用,main()int n=3;printf(%dn,sub1(n);,sub1(int n)int i,a=0;for(i=n;i0;i-)a+=sub2(i);return a;,sub2(int n)return n+1;,程序输出结果:9,2023/6/27,32,5.4.2 函数的递归调用,1递归的基本概念,递归调用:一个函数直接或间接地调用了它本身,就称为函数的递归调用。递归函数:在函数体内调用该函数本身。,int sub(int x)int y,z;if()z=sub(y);else return;,例如:,直接调用sub函数本身,2023/6/27,33,2递归函数的执行过程,【例5.16】编一递归函数求n!。,思路:以求4的阶乘为例:4!=4*3!,3!=3*2!,2!=2*1!,1!=1,0!=1。递归结束条件:当n=1或n=0时,n!=1。递归公式:,2023/6/27,34,程序如下:,float fact(int n)float f=0;if(n0)printf(n0,error!);else if(n=0|n=1)f=1;else f=fact(n-1)*n;return(f);,main()int n;float y;printf(nInput n:);scanf(%d,运行情况如下:Input a integer number:44!=24,2023/6/27,35,递归调用过程,2023/6/27,36,3编制递归函数的方法,数值型问题递归函数的编程方法对于数值型问题,首先要找出解题的数学公式,这个公式必须是递归定义的,且所处理的对象要有规律地递增或递减,然后确定递归结束条件。【例5.17】编一递归函数求xn。思路:首先把xn转化成递归定义的公式,再找出递归结束条件:当n=0时,xn=1。,2023/6/27,37,程序如下:,long xn(int x,int n)long f=0;if(n0)printf(n0,data error!n);else if(n=0)f=1;else f=x*xn(x,n-1);return(f);main()int n,x;long y;scanf(%d,%d,程序运行情况如下:2,101024,2023/6/27,38,非数值型问题递归函数的编程方法,有些问题不能直接用数学公式求解。非数值型问题比数值型问题更难找出递归的算法。它不能用一个递归公式表示。解决这类问题首先要把问题将大化小,将繁化简。将一个复杂的问题化解成若干个相对简单的小问题,而某个小问题的解法与原问题解法相同,并且越来越简单直至有确定的解。,【例5.18】编制一递归函数,将一个十进制正整数(如:15613)转换成八进制数形式输出。,2023/6/27,39,思路:十进制整数转换成八进制整数的方法是除8逆向取余。如图5.5所示。,非数值型问题递归函数的编程方法(续),2023/6/27,40,该题实际上是要把一个十进制数除以8得到的余数逆向输出。就是先得到的余数后输出,最后得到的余数最先输出。我们先由大化小:求八进制数变成求一系列余数的问题。求第一个余数是将15613除以8取余,因为先得到的余数后输出,所以把这个余数存在一个变量m中,接下去求下一个余数。和求第一个余数的方法相同,只是被除数变成了15613除以8的整数商1951。因此,这是一个递归调用的问题。定义变量m存放余数,x存放被除数。递归算法描述如下:,非数值型问题递归函数的编程方法(续),2023/6/27,41,先求出余数m:m=x%8;求x除以8取余后的整数商:x=x/8;如果x不等于0,递归调用该函数,否则执行。输出余数m。返回调用点。,非数值型问题递归函数的编程方法(续),2023/6/27,42,程序如下:,#include stdio.hvoid dtoo(int x)int m;m=x%8;x=x/8;if(x!=0)dtoo(x);printf(%d,m);main()int n;scanf(%d,程序运行情况如下:1561315613=(36375)8,2023/6/27,43,5.5 局部变量和全局变量及其作用域,5.5.1 变量的作用域,5.5.2 局部变量及其作用域,变量的作用域:变量在程序中可以被使用的范围。根据变量的作用域可以将变量分为局部变量和全局变量。,局部变量(内部变量):在函数内或复合语句内定义的变量以及形参。作用域:函数内或复合语句内。,【例5.19】分析下面程序的运行结果及变量的作用域。,问题:一个变量在程序的哪个函数中都能使用吗?,2023/6/27,44,void sub(int a,int b)int c;a=a+b;b=b+a;c=b-a;printf(sub:ta=%d b=%d c=%dn,a,b,c);,main()int a=1,b=1,c=1;printf(main:ta=%d b=%d c=%dn,a,b,c);sub(a,b);printf(main:ta=%d b=%d c=%dn,a,b,c);int a=2,b=2;printf(comp:ta=%d b=%d c=%dn,a,b,c);printf(main:ta=%d b=%d c=%dn,a,b,c);,“分程序”或“程序块”,程序输出结果:main:a=1 b=1 c=1sub:a=2 b=3 c=1main:a=1 b=1 c=1comp:a=2 b=2 c=1main:a=1 b=1 c=1,2023/6/27,45,5.5.3 全局变量及其作用域,全局变量(外部变量):在函数外部定义的变量。作用域:从定义变量的位置开始到本源文件结束。如在其作用域内的函数或分程序中定义了同名局部变量,则在局部变量的作用域内,同名全局变量暂时不起作用。,【例5.20】全局变量和局部变量的作用域。,2023/6/27,46,int a=5;void f(int x,int y)int b,c;b=a+x;c=a-y;printf(%dt%dt%dn,a,b,c);,程序输出结果:5 11-25 6 79 8 79 8 109 8 105 6 10,全局变量,2023/6/27,47,5.6 变量的存储类别及变量的生存期,5.6.1 变量的生存期与变量的存储分类,变量的生存期:变量在内存中占据存储空间的时间。,思考:1.何时为变量分配内存单元?2.将变量分配在内存的什么区域?3.变量占据内存的时间(生存期)?,动态存储变量,静态存储变量,2023/6/27,48,5.6.2 变量的存储类别,变量的属性,数据类型:决定为变量分配内存单元的长度,数据的存放形式,数的范围。,存储类别:决定了变量的生存期,给它分配在哪个存储区。,2023/6/27,49,变量定义语句的一般形式,存储类别 数据类型 变量名1,变量名n;,auto(自动的)register(寄存器的)static(静态的)extern(外部的),1自动变量(auto类别)局部变量可以定义为自动变量。,2023/6/27,50,内存分配调用函数或执行分程序时在动态存储区为其分配存储单元,函数或分程序执行结束,所占内存空间即刻释放。变量的初值定义变量时若没赋初值,变量的初值不确定;如果赋初值则每次函数被调用时执行一次赋值操作。生存期 在函数或分程序执行期间。作用域自动变量所在的函数内或分程序内。,自动变量,2023/6/27,51,2静态变量(static类别),除形参外,局部变量和全局变量都可以定义为静态变量。,2023/6/27,52,内存分配编译时,将其分配在内存的静态存储区中,程序运行结束释放该单元。静态变量的初值若定义时未赋初值,在编译时,系统自动赋初值为0;若定义时赋初值,则仅在编译时赋初值一次,程序运行后不再给变量赋初值。生存期整个程序的执行期间。作用域局部静态变量的作用域是它所在的函数或分程序。全局静态变量的作用域是从定义处开始到本源文件结束。,静态变量,2023/6/27,53,int c;static int a;main()float x,y;char s;f()static int b=1;,3.外部变量(extern类别),在函数外定义的变量若没有用 static说明,则是外部变量。外部变量只能隐式定义为extern类别,不能显式定义。,2023/6/27,54,内存分配编译时,将其分配在静态存储区,程序运行结束释放该单元。变量的初值若定义变量时未赋初值,在编译时,系统自动赋初值为0。生存期整个程序的执行期间。作用域从定义处开始到本源文件结束。此外,还可以用extern进行声明,以使其作用域扩大到该程序的其它文件中。,外部变量,问题:全局静态变量的作用域可以扩展到本程序的其它文件吗?,2023/6/27,55,外部变量声明的一般格式,extern 数据类型 变量名1,变量名n;或 extern 变量名1,变量名n;,注意:外部变量声明用关键字extern,而外部变量的定义不能用extern,只能隐式定义。定义外部变量时,系统要给变量分配存储空间,而对外部变量声明时,系统不分配存储空间,只是让编译系统知道该变量是一个已经定义过的外部变量,与函数声明的作用类似。,2023/6/27,56,int p=1,q=5;float f1(int a)extern char c1,c2;char c1,c2;char f2(int x,int y)main(),思考:在f1函数中声明c1、c2的作用是什么?如何修改程序使所有函数都可以使用外部变量而又不需要声明?,【例5.24】在一个文件内声明外部变量。,2023/6/27,57,【例5.25】在多文件的程序中声明外部变量。,file1.c文件中程序如下:int i;main()void f1(),f2(),f3();i=1;f1();printf(tmain:i=%d,i);f2();printf(tmain:i=%d,i);f3();printf(tmain:i=%dn,i);void f1()i+;printf(nf1:i=%d,i);,file2.c文件中程序如下:extern int i;void f2()int i=3;printf(nf2:i=%d,i);void f3()i=3;printf(nf3:i=%d,i);,程序输出结果:f1:i=2 main:i=2f2:i=3 main:i=2f3:i=3 main:i=3,声明外部变量,定义外部变量,2023/6/27,58,4.寄存器变量(register类别),只有函数内定义的变量或形参可以定义为寄存器变量。寄存器变量的值保存在CPU的寄存器中。受寄存器长度的限制,寄存器变量只能是char、int和指针类型的变量。,【例5.26】寄存器变量的使用。main()long int sum=0;register int i;for(i=1;i=1000;i+)sum+=i;printf(sum=%ldn,sum);,程序输出结果:sum=500500,2023/6/27,59,5.6.3 归纳变量的分类,1按照变量的作用域对变量分类 局部变量 全局变量2按照变量的生存期对变量分类 静态存储变量包括:局部静态变量和全局静态变量 动态存储变量包括:自动变量,2023/6/27,60,5.7 函数的存储分类,外部函数:extern int fan(char a,char b),静态函数:static int func(),外部函数和静态函数区别:外部函数允许本程序其他文件中的函数调用(与外部变量类似)。静态函数禁止本程序其他文件中的函数调用(与外部静态变量类似)。,extern可以省略,2023/6/27,61,5.8 指针与函数,5.8.1 指针变量作函数参数,1.变量的指针作函数参数,【例8.17】输入3个整数,按从小到大顺序输出。void swap(int*x1,int*x2)int t;t=*x1;*x1=*x2;*x2=t;return;void main()int a,b,c;scanf(%d%d%d,7 5 9,5,7,9,主调函数与被调函数之间数据传递的方法:实参与形参之间的数据传递;被调函数通过return语句把函数值返回到主调函数;通过全局变量交换数据;利用指针型参数在主调函数和被调函数之间传递数据。,7,9,7,5,7,5,形参x1和x2得到main函数中a和b的地址,这样x1和x2的目标变量就是main函数的变量a和b。在swap函数中交换*x1和*x2的内容,就是交换a和b的内容,所以当函数调用结束后,尽管x1和x2已经释放,但操作结果仍保留在main函数的变量a和b中,这就是通过指针形参指向域扩展到主调函数的方法,达到主调函数与被调函数间交换多个数据的目的。,2023/6/27,62,5.8 指针与函数,5.8.1 指针变量作函数参数,2.数组的指针作函数参数,一维数组的指针作函数参数 例如被调函数abc的定义形式有以下三种:void abc(int b10)void abc(int b)void abc(int*b)在主调函数有如下定义:int a10,*p=a;则调用abc函数时可用 abc(a)或 abc(p),当函数之间需要传递数组时,可以通过传递数组的首地址(即通过指针参数指向域的扩展),完成存取主调函数中数组元素的操作。,2023/6/27,63,5.8 指针与函数,5.8.1 指针变量作函数参数,2.数组的指针作函数参数,【例5.20】字符串复制函数。void copystr(char*t,char*s)/*字符指针变量t和s作形参*/while(*t+=*s+)!=0);main()char c80,*p=I am a student.;copystr(c,p);/*数组名c和字符指针变量p作实参*/printf(%sn,c);,2023/6/27,64,5.8 指针与函数,5.8.1 指针变量作函数参数,2.数组的指针作函数参数,二维数组的指针作函数参数,由于指向二维数组的指针分为行指针和元素指针,所以他们作为函数参数的形式也不同。,二维数组的行指针作函数参数 例如被调函数abc的定义形式有以下三种:void abc(int b24)void abc(int b 4)void abc(int(*b)4)在主调函数有如下定义:int a24,(*p)4=a;则调用abc函数时可用 abc(a)或 abc(p),2023/6/27,65,【例5.22】用函数输入输出整型二维数组,函数的形参为行指针。void inarr(int(*p1)4,int m)/*可改写为void inarr(int p1 4,int m)*/int i,j;for(i=0;im;i+)for(j=0;j4;j+)scanf(%d,*(p1+i)+j);,void utarr(int(*p2)4,int m)/*可改写为void outarr(int p234,int m)*/int i,j;for(i=0;im;i+)for(j=0;j4;j+)printf(%6d,p2ij);printf(n);,main()int a34,(*p)4;p=a;inarr(a,3);outarr(p,3);,5.8 指针与函数,5.8.1 指针变量作函数参数,2.数组的指针作函数参数,2023/6/27,66,5.8 指针与函数,5.8.1 指针变量作函数参数,2.数组的指针作函数参数,二维数组的指针作函数参数 指向二维数组元素的指针作函数参数,指向二维数组元素的指针作函数参数时,是利用二维数组元素按行连续存储的的特点,访问数组的每一个元素。被调函数的形参必须定义为指向二维数组元素的指针变量。,例如被调函数abc的定义形式如下:void abc(int*b)在主调函数有如下定义:int a24,*p=a0;则调用abc函数时可用 abc(a0)、abc(&a00)或 abc(p),2023/6/27,67,【例5.23】用函数输入输出整型二维数组,函数的形参为指向二维数组元素的指针。void inarr(int*p1,int m,int n)int i,j;for(i=0;im;i+)for(j=0;jn;j+)scanf(%d,p1+n*i+j);,5.8 指针与函数,5.8.1 指针变量作函数参数,void outarr(int*p1,int m,int n)int i,j;for(i=0;im;i+)for(j=0;jn;j+)printf(%6d,*(p1+n*i+j);printf(n);,2.数组的指针作函数参数,main()int a34,*p;p=,2023/6/27,68,5.8 指针与函数,5.8.2 带参数的主函数,1.带参数的主函数的定义,main(int argc,char*argv),main函数只能有两个形参,并且这两个形参的类型也是固定的。第一个形参必须是整型变量,第二个形参可以定义为字符型指针数组,也可以定义为二级字符指针变量,因此也可以写成 main(int argc,char*argv),2023/6/27,69,5.8 指针与函数,5.8.2 带参数的主函数,2.带参数的主函数的调用,带参数的主函数调用形式:可执行文件名 参数1 参数2 参数n 在DOS系统提示符下键入的这一行字符称为命令行。可执行文件名称为命令名,其后的参数称为命令行参数,命令名与各参数之间用空格进行分隔。,要调用带参数的主函数必须在操作系统环境下进行。假设C语言源程序文件file1.c,经过编译、连接生成一个可执行文件file1.exe。在DOS系统提示符后键入可执行文件名file1,即可执行该程序。,2023/6/27,70,5.8 指针与函数,5.8.2 带参数的主函数,3.主函数参数的作用,argc 称作参数计数器,它的值是包括命令名在内的参数个数。argv 指针数组的作用是存放命令行中命令名和每个参数字符串的首地址。C:file1 one two three,2023/6/27,71,5.8 指针与函数,5.8.2 带参数的主函数,【例5.24】显示命令行参数程序。void main(int argc,char*argv)int i=0;while(-argc0)printf(%sn,argv+i);,file1 one two three,one,two,three,注意:命令行参数所传送的数据全部都是字符串。即便传送的是数值,也是按字符串方式传送给主函数。程序中使用这些参数时,还需要将数字字符串转换成数值型数据。C语言标准库函数提供了一些相关的数据类型转换函数。,2023/6/27,72,5.8 指针与函数,5.8.3 指针型函数,1.指针型函数的定义,指针型函数定义的一般形式:数据类型标识符*函数名(形式参数表)其中函数名前的“*”表示函数的返回值是一个指针类型,“数据类型标识符”是指针所指向的目标变量的类型。,如果一个函数的返回值是指针,则称此函数为指针型函数。,2023/6/27,73,char*subcut(char*a,int s,int len)static char substrSIZE+1;/*substr用于存放子串*/int n;char*ps;ps=substr;if(sstrlen(a)|len1)printf(data errorn);/*数据错,子串为空*/else for(n=1,a+=s-1;n=len,5.8 指针与函数,5.8.3 指针型函数,【例5.26】编制一个函数,其功能是从已知字符串中指定位置s开始截取一个长度为len的子串。思路:在截取子串函数sutcut中需要从主调函数传送3个数据,源字符串、截取位置s、长度len。在形参中定义一个指针变量a接收源字符串的首地址,在函数中再定义一个存储类型为static的字符数组substr用于存放子串,指针变量ps指向substr数组。在截取子串的过程中,如果起始位置s小于1或大于源串则子串为空,如果截取长度len小于1子串也为空;否则循环复制子串,直到复制了len个字符或从源串读到 0 结束。最后函数将返回substr字符数组的首地址。,若起始位置s小于1或大于源串或截取长度len小于1,从第s个字符开始,复制len个字符,2023/6/27,74,5.8 指针与函数,5.8.3 指针型函数,2.指针型函数定义时应注意的问题,指针函数中return的返回值必须是与函数类型一致的指针。返回值必须是外部或静态存储类别的变量指针或数组指针,以保证主调函数能正确使用数据。,2023/6/27,75,5.8 指针与函数,5.8.4 指向函数的指针,1.函数指针变量的定义,函数指针变量定义的一般形式:数据类型标识符(*函数指针变量名)();其中“*函数指针变量名”必须用圆括号括起来,否则就成为声明一个指针型函数了。在定义中“(*函数指针变量名)”右侧的括号“()”表示指针变量所指向的目标是一个函数,“数据类型标识符”是定义指针变量所指向的函数的类型。例如:int(*p)();/*p是一个指向整型函数的指针变量*/float(*q)();/*q是一个指向单精度实型函数的指针变量*/,在C语言中,函数名具有与数组名类似的特性,数组名代表数组的首地址,函数名代表函数的起始地址(即该函数的程序代码段在内存中所占用的存储空间的首地址,也称函数入口)。因此也可以把函数名赋给一个函数指针变量,使其成为指向该函数的指针变量。函数名则可以看成是函数指针常量。,2023/6/27,76,5.8 指针与函数,5.8.4 指向函数的指针,2.用函数指针变量调用函数,用函数指针变量调用函数的一般形式:(*函数指针变量名)(实参表);由于优先级不同“*函数指针变量名”必须用圆括号括起来,表示间接调用指针变量所指向的函数;右侧括号中为传递到被调函数的实参。,函数指针与变量指针的共同之处是都可以做间接访问。变量指针指向内存的数据存储区,通过间接存取运算访问目标变量;函数指针指向内存的程序代码存储区,通过间接存取运算使程序流程转移到指针所指向的函数入口,取出函数的机器指令并执行函数,完成函数的调用。,2023/6/27,77,5.8 指针与函数,5.8.4 指向函数的指针,main()int max(),a,b,c;/*声明被调用的目标函数max*/int(*p)();/*定义p为指向整型函数的指针变量*/p=max;/*用指针变量存储函数入口地址*/scanf(“%d%d”,由于优先级的问题,()是必须的,目标函数必须要事先声明,即使是整型函数也要声明,(*p)中()是必须的,实参表应与函数的形参表一一对应,2023/6/27,78,将函数指针作为参数,可在主调函数和被调函数之间将第三个函数作为参数传递,实现在被函数中调用不同函数的目的,使被调函数成为通用函数。函数指针作函数参数时,形参一定要定义为指向函数的指针变量,实参则可以是函数名或指向函数的指针变量。,【例5.28】编制一个用弦截法求方程根的函数,求解下列方程。x3-5x2+6x-30=0 2x3-4x2+3x-6=0,5.8 指针与函数,5.8.4 指向函数的指针,

    注意事项

    本文(c语言 课件第5章.ppt)为本站会员(sccc)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开