chap06函数与编译预处理.ppt_第1页
chap06函数与编译预处理.ppt_第2页
chap06函数与编译预处理.ppt_第3页
chap06函数与编译预处理.ppt_第4页
chap06函数与编译预处理.ppt_第5页
已阅读5页,还剩95页未读 继续免费阅读

下载本文档

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

文档简介

6.1 概 述 6.2 函数的定义 6.3 函数的调用 6.4 函数的嵌套及递归调用 6.5 数组作为函数参数 6.6 局部变量和全局变量 6.7 变量的存储类别 6.8 内部函数和外部函数 6.9 编译预处理 6.10 程序举例 第6章 函 数 6.1 概述 6.1.1 模块与函数 1.功能模块 求解较小问题的算法和程序称作“功能模 块”, 各功能模块可以先单独设计,然后将求 解所有子问题的模块组合成求解原问题的程 序。 “自顶向下”的模块化程序设计方法: 将一个大问题分解成多个解决小问题 的模块的设计思想。 2.由功能模块组成程序的结构图: 主控模块 模块1_1模块1_n模块2_1模块2_n模块n_1模块n_n 模块1 模块2模块n 3. 函数:完成相对独立功能的程序 【例】 输入年月日,计算出该日为该年的第 几天。 主控模块 判断闰年求某月的天数 输 出输 入求总天数 程序实现: (1)判断闰年。 int leap(int year) int lp; lp=(year%4=0 return lp; (2)求某月的天数。 int month_days(int year,int month) int ds,d; switch(month) case 1: case 3: case 5: case 7: case 8: case 10: case 12:d=31;break; case 2:d=leap(year)?29:28;break; default:d=30; return d; (3)求天数和。 int days(int year,int month,int day) int i,ds=0; for (i=1;i /* 包含math.h头文件 */ #include /* 包含 stdio.h 头文件 */ main( ) double a, b; scanf (“%f “, /*调用输入函数,输入变量a的值*/ b = sin (a); /*调用sin函数,求sin (a) 的值*/ printf( “%6.4f”, b); /*调用输出函数,输出变量b的值*/ 二、用户自定义函数 函数类型 无参函数 函数的定义无参数说明 有参函数 定义的参数有一个或一个以上的参数 空函数 当定义的函数既无参数也无执行语句。 空函数被调用时,什么也不做立即返回其 调用函数。 1、 无参函数的定义 类型说明符 函数名() 声明部分; 语句部分; 函数返回值类型 缺省int型 无返回值void 合法标识符 函数体 无参函数例子: printstar(void) printf(“*n”) printstar() *printstar函数* printf(“*n”); main() printstar( ); 注意:无参函数可以显式的在函数名后括号中加入关 键字void 2、有参函数定义 类型说明符 函数名(形式参数列 表) 声明部分; 语句部分; 函数返回值类型 缺省int型 无返回值void 形参需要定 义类型 有参函数例子: printstar(int n) *printstar函数* int i; for(i=1;iy) t = x; else t = y; return t; 若程序运行时输入为: 10,5 便有输出为: 10 1) 形参y之间值的传递如图所示。 a x b y 2) 关于形式参数和实际参数说明如下: 形式参数在函数被调用时才被分配内存。当函数执行完毕 返回时, 形式参数占用的内存空间便被释放。 实参可以是变量、常量和表达式。 如: y = power(x,4); y = power(x, i*2); 但实参必须有确定的值。 3) 形参和实参的类型必须相容。 4) 形参和实参之间的关系是: 单向的值的传递 101055 调用max函数时,实参a把值传给形参x, 实参b把值传给形 参y,按顺序传递, 与形参名称无关。 实参a和形参x, 实参 b和形参y一一对应。 值传递方式举例: 711a:b:调用前: 调用结束: 711a:b: 调用: 711x:y: 711a:b: swap: 711a:b: 117x:y: temp swap(int x,int y) int temp; temp=x; x=y; y=temp; #include main() int a=7,b=11; printf(“a=%d, b=%dn“,a,b); printf(“swapped:n“); swap(a,b); printf(“a=%d,b=%dn “,a,b); 四 、 函数的返回值和函数的类 型 v函数的返回值是通过函数中的return语句获得的 。 返回形式: return(表达式); 或 return 表达式; 或 return; 功能:使程序控制从被调用函数返回到调用(主调 )函数中, 同时把返值带给调用函数。释放在函数 的执行过程中分配的所有内存空间。 函数无返回值时使 用,也可以省略 void printstar(void) printf(“*n”) ; v 函数的类型:通常和函数的返回值类型一致。 为了明确表示“不带回值”,可以用“void”定义“无类型” (或称“空类型) 例:求两个整数的大者: int max(int x,int y) int ;*函数体中的声明部分 xy?xy; return(); main() int a,b,c; scanf(d,d,a,b); cmax(a,b); printf(“ax isdn,c); v其执行过程: 值传递方式 :函数调用时,为形参分配单元,并 将实参的值传递到形参中;调用结束,形参单 元被释放,实参单元仍保留并维持原值。 特点:形参与实参占用不同的内存单元,单向 传递。 注意:若函数类型与return语句中表达式值的 类型不一致,按函数类型为准,自动转换。例 如: int max(float x,float y) float ;*函数体中的声明部分 xy?xy; return(); main() float a,b,c; scanf(f,f,a,b); cmax(a,b); printf(“ax isfn,c); 运行时如果输入: 6.5,7.8 则结果为:ax is 7.00000 1.函数调用一般形式 有返回值的函数调用形式:有返回值的函数调用形式: 函数名 (实际参数列表) 如: c=max(a, ,b); max(a,b); 无返回值的函数调用形式:无返回值的函数调用形式: 函数名 () 如: printstar( ); 6.3函数的调用 v说明: 实参与形参个数 相等,类型一致 ,按顺序一一对 应 实参表求值 顺序,因系统而 定(Turbo C 自 右向左); 2.函数调用方法 (1)函数语句: (2)函数表达式: (3)函数参数: 如: printstar( ); 如: c=max(a,b); 如: m=max(a,max(b,c); printf(“%d”,max(a,b); 对被调用函数的说明: 在一个函数中调用另一个函数,需要具备 的条件: 1.首先被调用函数必须已经存在 2.如果使用库函数,还须用# #includeinclude命令 将调用有关函数时,所需用到的信息包含到 本文件中 如: # #include “math.h”include “math.h” 3.若用户自己定义一函数,且该函数与 调用它的函数在同一个文件中,一般还 应在主调函数中对被调用函数返值的类 型作说明 对被调用函数的说明: v函数声明: 形式: 函数类型 函数名(形参类型 形参名, ); 或 函数类型 函数名( ); 其位置:程序的变量说明部分(函数内或外) 可不作说明的情形: 若函数返值是char或int型,系统自动按int型处理 被调用函数定义出现在主调函数之前 void swap(int a, int b) int t; t = a; a = b; b = t; void main( ) int x, y; scanf(“%d%d“, swap(x, y); printf(“%d%d“, x, y); void main( ) int x, y; scanf(“%d%d“, swap(x, y); printf(“%d%d“, x, y); void swap(int a, int b) int t; t = a; a = b; b = t; void swap(int a, int b); 函数在被调用前必须先定义和声明! 函数调用小 结 函数调用时,实参计算值,传递给相应位 置的形参; 函数执行完后,通过return (exp),可返回 结果。 调用其他函数, 必须先说明! 有多个实参时 后面 的先计算 形参的改 变不影响 实参 数量、类型、 顺序一致 一个结果 6.4 函数的嵌套和递归调用 调用一个函数的过程中又调用了另一个函数,这种调用称为 函数的嵌套调用。 函数1 函数2 函数3 . . 调用函数2 调用函数3 . 6.4.1 嵌套调用 函数都是相互独立的,互相平行的 例题:计算 S=(1*1)!+(2*2)!+(3*3)!+(4*4)!+(5*5)! 6.4.2 递归调用 函数直接或间接的调用自身,称为函数的 递归调用。 递归调用形式如下: 直接递归 间接递归 int f(int x) int y,z; z=f(y); . return(2*z); int f1(int x) int y,z; z=f2(y); . return(2*z); int f2(int t) int a,c; c=f1(a); . return(3+c); f( ) 调f 调f2调f1 f1( )f2( ) 如果要求递归的过程不是无限制进行下去, 必须有一个结束递归的条件 用递归算法计算n! 讨论: 采用递归的方法计算。n!的递归定义形式 的: 编程: if (初始条件) 表达式; else 递推表达式; 1 n=0; n!= n* (n-1)! n0 例程序: #include long fac(unsigned n) long f ; if (n=0) f=1; /*递归结束条件*/ else f=n*fac(n-1); return f; main( ) long y; int n; scanf(“%d”, y = fac(n); printf(“%d!=%ldn”, n, y); 分析:当程序输入3时 y=fac(3) 3*fac(2) 2*fac(1) 1*fac(0) 1 6.5 数组作为函数参数 v 数组元素作函数实参值传递; v 数组名作函数参数地址传递; v 使用时与普通变量一样 v值传递方式 在函数调用时将值传递给 实参形参 6.5.1 数组元素做函数实参 举例: swap1(int x,int y) int t; t=x;x=y;y=t; main() int a2=2,4; printf(“na0=%d,a1=%dn”,a0,a1 ); swap1(a0,a1); printf(“a0=%d, a1=%dn”,a0,a1); 数组元素作为函数的实参,与用普通变量作实参一 样,是单向传递,即“值传送”方式。 地址传递方式,实参与形参共用同一地址空间 ,相当于对同一对象的两个不同名字。 在函数调用时将其地 址值传递给 实参形参 6.5.2 整个数组做函数的参数 (1)数组名代表数组的首地址,在数组 名作为函数的参数时,形参和实参都应该是 同类形数组。 在函数调用时,实参给形参传递的数据是 实参数组的首地址,即实参数组和形参数组 完全等同,是存放在同一存储空间的同一个 数组,形参数组和实参数组共享存储单元。 (2)如果在函数调用过程中形参数组的内 容被修改了,实际上也是对应地修改了实参 数组的内容。 数组名作为函数参数举例: #include float average(int stu10, int n); void main() int score10, i; float av; printf(“Input 10 scores:n“); for( i=0; ib?a:b; 形参a、b作用范围 return(c); main( ) int a=8; /*a为局部变量*/ 局部变量a的作用 范围 printf(“%d“,max(a,b); 全局变量b的作用 范围 运行结果为:8 全局变量a在main函数范围内不起作用,而全局变量 b在此范围内有效。因此printf函数中的max(a,b)相 当于max(8,5)。 一、变量按存在时间划分:静态变量,动态 变量 静态存储变量:生存期为程序执行的整个过程 ,在该过程中占有固定的存储空间,也称永久存 储。 动态存储变量:只生存在某一段时间内。 例如:函数的形参、函数体或分程序中定义的 变量,只有当程序进入该函数或分程序时才分配 存储空间,函数/分程序执行完后,变量的存储空 间又被释放。 6.7 变量的存储方式 1程序区 2静态存储区 3动态存储区 数据分别存放在静态存储区和动态存储区中; 全局变量及加static声明的局部变量存放在静态存储区中; 在动态存储区中存放以下数据: 函数形式参数。 自动变量。 函数调用时的现场保护和返回地址等。 二、 变量属性:数据类型,存储特性 完整的变量定义: 存储特性 数据类型 变量名; 内存中的供用户使用存储空间的情况,这个存储空间可以 分为三部分 : 3.变量的存储特性 1) auto型 有形式参数、函数内变量、分程序变量 。 进入程序自动分配内存,不长期占用内 存,仅局限于定义它的函数。 auto int a,b=3;等价于 int a,b=3; 自动型 auto 静态型 static 寄存器型 register 外部型 extern 2) static 型 静态局部变量 静态全局变量 长期占用内存 静态局部变量:定义在函数内,并用static声明的变量; 特点: 在编译时赋初值,并且只赋一次初值; 如果定义时,不赋初值,则系统默认初值为0或空字符; 离开函数,值仍然存在 静态全局变量:定义在函数外,并用static声明的变量; 特点: 该全局变量只限于被本文件中的函数使用,而不能被 其他文件中的函数使用; 例 f(int a) int b=0; static int c=3; b+;c+; printf(“%5d%5d%5d”,a,b,c); return(a+b+c); main() int a=2,k; for(k=0;k 说明: (1)一个#include命令只能指定一个被包含文 件,如果要包含n个文件,要用n个#include命令。 (2)如果文件1包含文件2,而文件2中要用到 文件3的内容,则可在文件1中用两个include命令 分别包含文件2和文件3,而且文件3应出现在文件 2之前,即在file1.c中定义: #include “file3.h” #include “file2.h” 这样,file1和file2都可以用 file3的内容。在 file2中不必再用#include了(以上是假设 file2.h在本程序中只被file1.c包含,而不出现在其 他场合)。 (3)在一个被包含文件中又可以包含另一个被包 含文件,即文件包含是可以嵌套的 (4)#include 命令中,文件名可以用双撇号或 尖括号括起来,如可以在file1.c中用 #include 预处理程序只则按系统指定的标准方式 检索文件目录。 或 #include “flie2.h” 预处理程序首先在原来的源文件目录 中检索该指定的文件,如果没找到,则按系统 指定的标准方式检索其他文件目录,直至找到 为止。 例:文件包含简单使用文件包含简单使用 #include “f2.c” main() float r=3.0,area; area=PI*r*r; PR(F,area); f1文件f2文件 #define PI 3.1415926 #define PR printf #define F “%fn” 6.8.3 条件编译 条件编译命令有以下几种形式: (1)#ifdef 标识符 程序段1 #else 程序段2 #endif 它的作用是当所指定的标识符已经被define 命令定义过,则在程序编译阶段只编译程序段1, 否则编译程序段2。其中#else部分可以没有,即 #ifdef 标识符 程序段1 #endif 例: 条件编译使用条件编译使用 #define LEN 1 #ifdef LEN #define PI 3.1415926 #else #define PI 3.14 #endif main() float r=3.65,area; area= PI*r*r; printf(“%f”,area); (2)#ifndef 标识符 程序段1 #else 程序段2 #endif 只是第一行与第一种形式不:将“ifdef”改为 “ifndef”。它的作用是若标识符未被定义过则编译程 序段1,否则编译

温馨提示

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

评论

0/150

提交评论