第七章 函数 西安工程大学.

Slides:



Advertisements
Similar presentations
第8章 函数 信息管理系.
Advertisements

第一章 C语言概述 计算机公共教学部.
C语言基础——指针的高级应用 Week 05.
第8讲 函数 8.1 函数的定义与调用 8.2 函数的参数 8.3 函数重载与递归 8.4 标识符作用域与变量的存储特性.
C语言程序设计 第八章 函数.
Introduction to the C Programming Language
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
4.3函数 4.3.1函数的概念及定义 1、函数的概念: 可以被其它程序调用具有 特定功能的一段相对独立的 程序(模块),称函数。
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
第5章 函数及变量的存储类别 5.0 概述 5.1函数的定义 5.2函数调用 5.3变量的作用域和存储类别 5.4内部函数和外部函数
由C程序结构所知,一个完整的C语言程序是由一个且只能有一个main()函数(又称主函数)和若干个其他函数组合而成的。而前面各章仅学习main()函数的编程,本章将介绍其他函数的编程,包括其他函数的定义、调用、参数传递及变量的作用域等。
第八章 函数 §8.1 概述 一个较大程序一般分为若干个程序模块,每一个模块实现一个特定的功能。所有的高级语言中都有子程序的概念,在C中子程序就是函数。 一个C程序可由一个主函数和若干个函数构成,由主函数调用其它函数,其它函数也可以相互调用.
選擇排序法 通訊一甲 B 楊穎穆.
第3章 顺序结构程序设计 本章要点: 格式化输出函数──printf() 格式输入函数——scanf() 字符输出函数——putchar()
第4章 函数与预处理 4.1 概述 4.2 定义函数的一般形式 4.3 函数参数和函数的值 4.4 函数的调用 *4.5 内置函数
Chap 10 函数与程序结构 10.1 函数的组织 10.2 递归函数 10.3 宏定义 10.4 编译预处理.
C语言程序设计基础 刘新国.
项目六 用指针优化学生成绩排名 项目要求 项目分析
Introduction to the C Programming Language
目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
第7章 函 数 本章要点: C语言程序结构和特点 函数的定义 函数的返回值与函数的类型 函数的调用及参数的传递关系 函数的嵌套与递归
C程序设计 谭浩强 著 清华大学出版社.
第八章 函数.
第7章 函 数 为什么要使用函数? 函数定义、调用、声明 局部变量和全局变量 变量的存储类别 内部函数和外部函数 函数的嵌套调用和递归调用
QQ: 李祥 QQ: 欢迎多种方式的学习交流,祝大家学有所成.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第6章 函数 学习的意义.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
第7章 用函数实现模块化程序设计 7.1为什么要用函数 7.2怎样定义函数 7.3调用函数 7.4对被调用函数的声明和函数原型
第八章 使用指针.
第五章 习题课 电子信息与计算机科学系 曾庆尚.
第七章 函数及变量存贮类型 7.1 函数基础与C程序结构 7.2 函数的定义和声明 7.3 函数的调用 7.4 函数的嵌套与递归
数组 梁春燕 华电信息管理教研室.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
第8章 函数 函数参数和函数的值 概述 函数定义的一般形式 函数的调用(嵌套调用、递归调用) 数组作为函数参数
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C语言复习2----函数.
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
第7章 函 数 7.1 函数的定义与调用 7.2 函数的嵌套调用与递归调用 7.3 数组作为函数参数 7.4 内部变量与外部变量
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
C语言程序设计.
目录 7.1 用户自定义函数的种类 7.2 函数的定义 7.3 被调函数的声明 7.4 函数的调用 7.5 函数的嵌套调用
主讲:相方莉.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
Chap 5 函数 5.1 计算圆柱体积 5.2 数字金字塔 5.3 复数运算.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
C程序设计.
第5章 函 数.
第一章 C语言概述 教师:周芸.
第4章 Excel电子表格制作软件 4.4 函数(一).
C语言程序设计 李祥 QQ:
第九节 赋值运算符和赋值表达式.
习 题 课(作业).
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
第四章 函数 丘志杰 电子科技大学 计算机学院 软件学院.
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
第7章 用函数实现模块化程序设计 7.1为什么要用函数 7.2怎样定义函数 7.3调用函数 7.4对被调用函数的声明和函数原型
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
Chap 7 数 组 7.1 排序问题 7.2 找出矩阵中最大值所在的位置 7.3 进制转换.
第三章 高级函数特性.
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
计算机编程 信息管理与工程学院 2014年9月.
Presentation transcript:

第七章 函数 西安工程大学

本章内容: 函数概述 函数的定义与调用 数组作为函数参数 函数的嵌套调用和递归调用 变量的属性 变量的存储类别 内部函数与外部函数

7.1 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块 特点及优点: 各模块相对独立、功能单一、结构清晰、接口简单 控制了程序设计的复杂性 提高元件的可靠性 缩短开发周期 避免程序开发的重复劳动 易于维护和功能扩充 开发方法: 自上向下,逐步分解,分而治之 使每一个模块成为相对独立、功能单一、结构清晰、接口简单、容易理解的程序 每个模块可以独立设计算法,单独编写和测试 一个模块中的错误不易扩散和蔓延到其它模块, 众人可同时进行集体性开发 软件具有模块结构,软件开发工作如同搭积木,一个模块可以在不同程序中多次使用

C是模块化程序设计语言 C程序结构 C是函数式语言 必须有且只能有一个名为main的主函数 C程序的执行总是从main函数开始,在main中结束 函数不能嵌套定义,可以嵌套调用

Getchar() Printf(“%d”,a) 函数分类 从用户角度 标准函数(库函数) 用户自定义函数 从函数形式 无参函数 有参函数 例如: Printf(“%d”,a ); Scanf(“%d”,&a); Getchar() Putchar(a); Abs(x); Sqrt(x); Getchar() Printf(“%d”,a) 使用库函数应注意: 1、函数功能 2、函数参数的数目和顺序,及各参数意义和类型 3、函数返回值意义和类型 4、需要使用的包含文件

7.2 函数的定义和调用 7.2.1 函数的定义 7.2.2 函数的返回值与函数类型 7.2.3 对被调用函数的说明和函数原型 7.2.1 函数的定义 7.2.2 函数的返回值与函数类型 7.2.3 对被调用函数的说明和函数原型 7.2.4 函数的调用 7.2.5 函数的形参与实参

7.2.1 函数的定义 一般格式 { 说明部分; 语句部分; } 函数返回值类型 缺省int型 无返回值void 函数首部 函数类型 函数名(数据类型 参数[,数据类型 参数2……] ) { 说明部分; 语句部分; } 合法标识符 函数体 例 有参函数(现代风格) int max(int x,int y) { int z; z=x>y?x:y; return(z); } 例 空函数 dummy( ) { } 函数体为空 例 无参函数 void printstar( ) { printf(“**********\n”); }

函数的定义说明 (1)函数定义不允许嵌套。 在一个函数的函数体内,不能再定义另一个函数,即不能嵌套定义。 (2)空函数──既无参数、函数体又为空的函数。其一般形式为: [函数类型] 函数名(void) { }

7.2.2 函数的返回值与函数类型 函数的返回值和return语句 有参函数的返回值,是通过函数中的return语句来获得的。 7.2.2 函数的返回值与函数类型 函数的返回值和return语句 有参函数的返回值,是通过函数中的return语句来获得的。 return语句的形式: return(表达式); 或 return 表达式; 或 return; 功能:返回调用函数,并将“返回值表达式”的值带给调用函数。

说明: 函数中可有多个return语句 若无return语句,并不是不返回一个值,而是遇}时,自动返回调用函数,并带回一个不确定的值。 为了明确表示不返回值,可以用“void”定义成“无(空)类型”。 若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换------函数调用转换 例 无返回值函数 void swap(int x,int y ) { int temp; temp=x; x=y; y=temp; }

{ printf("**********"); } void main() { int a; a=printstar(); 例 函数带回不确定值 printstar() { printf("**********"); } void main() { int a; a=printstar(); printf("%d",a); void printstar() { printf("**********"); } void main() { int a; a=printstar(); printf("%d",a); 输出:10 编译错误!

void 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); 例 函数返回值类型转换

7.2.3 对被调用函数的说明 一般形式: 函数类型 函数名(形参类型 [形参名],….. ); 或 函数类型 函数名(); 对被调用函数要求: 必须是已存在的函数 库函数: #include <*.h> 用户自定义函数: 函数类型说明 函数说明 一般形式: 函数类型 函数名(形参类型 [形参名],….. ); 或 函数类型 函数名(); 作用:告诉编译系统函数类型、参数个数及类型,以便检验 函数定义与函数说明不同 函数说明位置:程序的数据说明部分(函数内或外) 下列情况下,可不作函数说明 若函数返值是char或int型,系统自动按int型处理 被调用函数定义出现在主调函数之前

float add(float x, float y) { float z; z=x+y; return(z); } void main() 例 函数说明举例 float add(float x, float y) { float z; z=x+y; return(z); } void main() { float a,b,c; scanf("%f,%f",&a,&b); c=add(a,b); printf("sum is %f",c); 被调函数出现在主调函数 之前,不必函数说明 void 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); int型函数可不作函数说明 void main() { float add(float,float); /*function declaration*/ float a,b,c; scanf("%f,%f",&a,&b); c=add(a,b); printf("sum is %f",c); } float add(float x, float y) { float z; z=x+y; return(z); float add();

7.2.4 函数的调用 调用形式 函数名(实参表); 调用方式 函数语句 例 printstar(); printf(“Hello,World!\n”); 函数表达式: 例 m=max(a,b)*2; 函数参数: 例 printf(“%d”,max(a,b)); m=max(a,max(b,c)); 注意: 实参与形参个数相等,类型一致,按顺序一 一对应

7.2.5 函数参数及其传递方式 形参与实参 形式参数:定义函数时函数名后面括号中的变量名 实际参数:调用函数时函数名后面括号中的表达式

例 比较两个数,并输出大较者 void main() { int a,b,c; scanf("%d,%d",&a,&b); c=max(a,b); printf("Max is %d",c); } max(int x, int y) { int z; z=x>y?x:y; return(z); 实参 c=max(a,b); (main 函数) (max 函数) max(int x, int y) { int z; z=x>y?x:y; return(z); } 形参

函数调用过程演示 Main函数 Max函数 x a 5 5 b y 7 7 c z 7 7

说明: 实参必须有确定的值 形参必须指定类型 形参与实参类型一致,个数相同 若形参与实参类型不一致,自动按形参类型转换———函数调用转换 形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放

x 例 计算x的立方 a product #include <stdio.h> float cube(float x) ×× 1.2 1.2 1.728 #include <stdio.h> float cube(float x) { return(x*x*x); } void main() { float a, product; printf("Please input value of a:"); scanf("%f",&a); product=cube(a); printf(”Cube of %.4f is %.4f\n",a,product); x

参数传递方式之一——值传递 值传递方式 方式: 函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值 特点: 形参与实参占用不同的内存单元 单向传递

调用前: x 7 y 11 调用时: a b 11 7 11 7 调用结束: temp 7 例 交换两个变量的值。 调用前: x 7 y 11 #include <stdio.h> void main() { int x=7,y=11; printf("x=%d,\ty=%d\n",x,y); printf("swapped:\n"); swap(x,y); } swap(int a,int b) { int temp; temp=a; a=b; b=temp; 调用时: a b 11 7 11 7 调用结束: 交换开始了 temp 7

练习: char fun(char x , char y) { if(x<y) return x; return y; }    }    void main( )   {  int a=’9’,b=’8’,c=’7’;      printf(“%c\n”,fun(fun(a,b),fun(b,c)));   }   程序的执行结果是 A、函数调用出错   B、8    C、9   D、7

写出下列程序的运行结果: void swap(int x,int y) { int t; t=x;x=y;y=t;printf("%d %d ",x,y); } void main() { int a=3,b=4; swap(a,b);printf("%d %d\n",a,b); } 答案:4 3 3 4

7.3 数组作为函数参数 数组元素作函数实参——值传递 #include <stdio.h> void main() { int a[10],b[10],i,n=0,m=0,k=0; printf("Enter array a:\n"); for(i=0;i<10;i++) scanf("%d",&a[i]); printf("Enter array b:\n"); scanf("%d",&b[i]); { if(large(a[i],b[i])==1) n=n+1; else if(large(a[i],b[i])==0) m=m+1; else k=k+1; } /* Output */ int large(int x,int y) { int flag; if(x>y) flag=1; else if(x<y) flag=-1; else flag=0; return(flag); 例 两个数组比较大小 4 3 2 1 5 a 56 23 12 10 76 88 b 21 43 98 66 54 a和b为有10个元素的整型数组 比较两数组对应元素 变量n,m,k记录a[i]>b[i], a[i]==b[i], a[i]<b[i]的个数 最后 若n>k,认为数组a>b 若n<k,认为数组a<b 若n==k,认为数组a==b i n=0 m=0 k=1 i n=0 m=1 k=1 i n=1 m=1 k=1 i n=1 m=1 k=2 i n=2 m=1 k=2 i n=3 m=1 k=2 n=0 m=0 k=0

说明: 用数组元素作实参时,只要数组元素类型和函数的形参类型一致即可,并不要求函数的形参也是下标变量。换句话说,对数组元素的处理是按普通变量对待的。

float average(int stu[10], int n) { int i; float av,total=0; 例 求10位学生的平均成绩 float average(int stu[10], int n) { int i; float av,total=0; for( i=0; i<n; i++ ) total += stu[i]; av = total/n; return av; } #include <stdio.h> float average(int stu[10], int n); void main() { int score[10], i; float av; printf("Input 10 scores:\n"); for( i=0; i<10; i++ ) scanf("%d", &score[i]); av=average(score,10); printf("Average is:%.2f", av); } . 2 1 9 score 56 23 12 …. 88 stu 实参用数组名

a k array j j i=0 j k j k j j j j j void main() { int a[10],i; void sort(int array[],int 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; if(k!=i) { t=array[i]; array[i]=array[k]; array[k]=t; } void main() { int a[10],i; for(i=0;i<10;i++) scanf("%d",&a[i]); sort(a,10); printf("%d ",a[i]); printf("\n"); 例 数组排序----简单选择排序 1 2 3 4 5 6 7 8 9 a 9 k array 49 68 57 32 9 99 27 13 76 88 j j i=0 j k 49 j k j j j j j

a array k j k i=1 j k j j j k j k j j void main() { int a[10],i; for(i=0;i<10;i++) scanf("%d",&a[i]); sort(a,10); printf("%d ",a[i]); printf("\n"); } 例 数组排序----简单选择排序 void sort(int array[],int 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; if(k!=i) { t=array[i]; array[i]=array[k]; array[k]=t; } 1 2 3 4 5 6 7 8 9 a 49 68 57 32 99 27 13 76 88 array 13 k j k i=1 j k j j j k 68 j k j j

a array i=8 void main() { int a[10],i; for(i=0;i<10;i++) void sort(int array[],int 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; if(k!=i) { t=array[i]; array[i]=array[k]; array[k]=t; } void main() { int a[10],i; for(i=0;i<10;i++) scanf("%d",&a[i]); sort(a,10); printf("%d ",a[i]); printf("\n"); 1 2 3 4 5 6 7 8 9 a 13 27 32 49 57 68 76 88 99 array i=8 例 数组排序----简单选择排序

地址传递 方式:函数调用时,将数据的存储地址作为参数传递给形参 特点: 形参与实参占用同样的存储单元 “双向”传递 实参和形参必须是地址常量或变量

int max_value(int array[3][4]) { int i,j,k,max; max=array[0][0]; 例 求二维数组中最大元素值 int max_value(int array[3][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); } void main() { int a[3][4]={{1,3,5,7}, {2,4,6,8},{15,17,34,12}}; printf("max value is %d\n",max_value(a)); 1 3 5 7 2 4 6 8 15 17 34 12 i j max=1 1 3 5 7 2 4 6 8 15 17 34 12 i j max=3 1 3 5 7 2 4 6 8 15 17 34 12 i j max=5 多维形参数组第一维维数 可省略,第二维必须相同  int array[][4] j 1 3 5 7 2 4 6 8 15 17 34 12 i max=7 j 1 3 5 7 2 4 6 8 15 17 34 12 i max=7 j 1 3 5 7 2 4 6 8 15 17 34 12 i max=34

get_sum_row(int x[][3], int result[] ,int row, int col) { int i,j; 例 求二维数组中各行元素之和 get_sum_row(int x[][3], int result[] ,int row, int col) { int i,j; for(i=0;i<row;i++) { result[i]=0; for(j=0;j<col;j++) result[i]+=x[i][j]; } void main() { int a[2][3]={3,6,9,1,4,7}; int sum_row[2],row=2,col=3,i; get_sum_row(a,sum_row,row,col); printf("The sum of row[%d]=%d\n",i+1,sum_row[i]); x result 3 1 4 6 7 9 a sum_row 18 12

数组名作函数参数 用数组名作函数参数,要求形参和相对应的实参都必须是类型相同的数组,或指向数组的指针变量。 实参数组和形参数组大小不要求必须一致,C编译系统对形参数组大小不作检查,只将实参数组的首地址传给形参数组。 形参数组可以不指定大小, 但若是二维数组,则第二维必须指定大小,第一维可以不指定。 用数组名作为函数实参时,不是把数组的值传递给形参,而是把实参数组的起始地址传递给形参数组,两数组共用同一段存储单元。

#include <stdio.h> void swap2(int x,int y) { int z; z=x; x=y; y=z; } void main() { int a[2]={1,2}; swap2(a[0],a[1]); printf("a[0]=%d\na[1]=%d\n",a[0],a[1]); 例 数组元素作函数参数与数组名作函数参数的比较 值传递 1 2 a 调用 a[0] a[1] x y 2 1 x y 交换 1 2 a 调用前 a[0] a[1] 1 2 a 返回

#include <stdio.h> void swap2(int x[]) { int z; z=x[0]; x[0]=x[1]; x[1]=z; } void main() { int a[2]={1,2}; swap2(a); printf("a[0]=%d\na[1]=%d\n",a[0],a[1]); 例 数组元素作函数参数与数组名作函数参数的比较 地址传递 1 2 a 调用前 1 2 a x 调用 2 1 a x 交换 2 1 a 返回

写出下列程序的运行结果: #define N 20 fun(int b[ ],int n,int m) {int i,j; for(i=m;i>=n;i--)b[i+1]=b[i]; } void main() { int i,a[N]={1,2,3,4,5,6,7,8,9,10}; fun(a,2,9); for(i=0;i<5;i++)printf("%d",a[i]);

b 1 2 3 4 5 6 7 8 9 a m 1 9 2 3 n 2 3 4 4 5 5 6 6 7 7 8 8 9 10 9 10

以下程序的功能是计算函数F(x,y,z)=(x+y)/(x-y)+(z+y)/(z-y)的值,请选择填空。 #include<stdio,h> #include<math.h> float fun1(float,float); void main(void) { float x,y,z,sum; scanf("%f%f%",&x,&y,&z); sum=fun1( ① )+ fun1 ( ② ); printf("sum=%f\n",sum); } float fun1(float a,float b) { float num; num=a/b; return num; }

答案:abcbcc #include “stdio.h” void main() {char ch[]="abc",x[3][4];int i; for(i=0;i<3;i++)strcpy(x[i],ch); for(i=0;i<3;i++)printf("%s",&x[i][i]); printf("\n"); } 答案:abcbcc

7.4 函数的嵌套调用和递归 C语言规定:函数定义不可嵌套,但可以嵌套调用函数

int dif(int x,int y,int z) { return max(x,y,z)-min(x,y,z); } int max(int x,int y,int z) { int r; r=x>y?x:y; return(r>z?r:z); } int min(int x,int y,int z) { int r; r=x<y?x:y; return(r<z?r:z); #include <stdio.h> int dif(int x,int y,int z); int max(int x,int y,int z); int min(int x,int y,int z); void main() { int a,b,c,d; scanf("%d%d%d",&a,&b,&c); d=dif(a,b,c); printf("Max-Min=%d\n",d); } 例 求三个数中最大数和最小数的差值 main( ) 调用函数dif 输出 结束 dif函数 max函数 调用函数max 调用函数min min函数

递归调用 定义:函数直接或间接的调用自身叫函数的递归调用 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); int f(int x) { int y,z; …… z=f(y); ……. return(2*z); } 调f2 调f1 f1( ) f2( ) f( ) 调f

例 求n的阶乘 #include <stdio.h> int f(int n) { int f; if(n<0) printf("n<0,data error!"); else if(n==0||n==1) f=1; else f=f(n-1)*n; return(f); } void main() { int n, y; printf("Input a integer number:"); scanf("%d",&n); y=f(n); printf("%d! =%15d",n,y); 例 求n的阶乘

main() f(5) f(4) f(1) f(3) f(2) . f(5) . f(4)*5 . f(3)*5 . f(2)*5 . Return(1) 说明 C编译系统对递归函数的自调用次数没有限制 每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出

第一步:先把小盘和中盘从A借助于C移至B柱; (1)先把小盘移至C; (2)再把中盘移至B; (3)再把小盘移至B; 第三步:再把小盘和中盘从B借助于A移至C柱; (1)先把小盘子移至A; (2)再把中盘子移至C; (3)再把小盘子移至C; 例 Hanoi问题 A B C

第一步:先把n-1个盘从A借助于C移至B柱; hanoi(n-1,A,C,B); hanoi(n,A,B,C); 第一步:先把n-1个盘从A借助于C移至B柱; hanoi(n-1,A,C,B); 第二步:把大盘子移至C柱; Move(n,c); 第三步:再把n-1个盘从B借助于A移至C柱; hanoi(n-1,B,A,C); 例 Hanoi问题 A B C

void move(char getone, char putone) { printf("%c--->%c\n",getone,putone); } void hanoi(int n,char A,char B,char C) { if(n==1) move(A,C); else { hanoi(n-1,A,C,B); move(A,C); hanoi(n-1,B,A,C); } void main() { int m; printf("Input the number of disks:"); scanf("%d",&m); printf("The steps to moving %3d disks:\n",m); hanoi(m,'A','B','C'); 例 Hanoi问题 A B C 思考:什么样的问题可以用递归来解决?

7.5 变量的属性 概述 变量是对程序中数据的存储空间的抽象 main() { int a; a=10; printf(“%d”,a); } 内存 ……. main() { int a; a=10; printf(“%d”,a); } 编译或函数调用时为其分配内存单元 2000 2001 10 变量在某一时刻存在,则这时属变量的“生存期”(从给变量分配内存至所分配内存被系统收回的时间间隔 程序中使用变量名对内存操作

变量定义格式: [存储类型] 数据类型 变量表; 变量的属性 数据类型:变量所持有的数据的性质(操作属性) 存储属性 存储器类型:寄存器、静态存储区、动态存储区 生存期:变量在某一时刻存在-------静态变量与动态变量 作用域:变量在某区域内有效-------局部变量与全局变量 变量的存储类型 auto -----自动型 register-----寄存器型 static ------静态型 extern -----外部型 变量定义格式: [存储类型] 数据类型 变量表; 如: int sum; auto int a,b,c; register int i; static float x,y;

局部变量与全局变量 定义:在函数内定义,只在本函数内有效 说明: 局部变量---内部变量 main中定义的变量只在main中有效 运行结果:5 4 3 2 1 例 复合语句中变量 #define N 5 main() { int i; int a[N]={1,2,3,4,5}; for(i=0;i<N/2;i++) { int temp; temp=a[i]; a[i]=a[N-i-1]; a[N-i-1]=temp; } for(i=0;i<N;i++) printf("%d ",a[i]); 例 不同函数中同名变量 void main() { int a,b; a=3; b=4; printf("main:a=%d,b=%d\n",a,b); sub(); } sub() a=6; b=7; printf("sub:a=%d,b=%d\n",a,b); 运行结果: main:a=3,b=4 sub:a=6,b=7 例 不同函数中同名变量 main() { int a,b; a=3; b=4; printf("main:a=%d,b=%d\n",a,b); sub(); } sub() a=6; b=7; printf("sub:a=%d,b=%d\n",a,b); 例 复合语句中变量 #define N 5 main() { int i; int a[N]={1,2,3,4,5}; for(i=0;i<N/2;i++) { int temp; temp=a[i]; a[i]=a[N-i-1]; a[N-i-1]=temp; } for(i=0;i<N;i++) printf("%d ",a[i]); 局部变量与全局变量 局部变量---内部变量 定义:在函数内定义,只在本函数内有效 说明: main中定义的变量只在main中有效 不同函数中同名变量,占不同内存单元 形参属于局部变量 可定义在复合语句中有效的变量 局部变量可用存储类型:auto register static (默认为auto) float f1(int a) { int b,c; ……. } char f2(int x,int y) { int i,j; …… main() { int m,n; a,b,c有效 x,y,i,j有效 m,n有效

外部变量说明: extern 数据类型 变量表; 全局变量---外部变量 定义:在函数外定义,可为本文件所有函数共用 有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件 外部变量说明: extern 数据类型 变量表; 外部变量定义与外部变量说明不同 若外部变量与局部变量同名,则外部变量被屏蔽 > 定义 说明 次数: 只能1次 可说明多次 位置: 所有函数之外 函数内或函数外 分配内存: 分配内存,可初始化 不分配内存,不可初始化 外部变量可用存储类型:缺省 或 static 应尽量少使用全局变量,因为: 全局变量在程序全部执行过程中占用存储单元 降低了函数的通用性、可靠性,可移植性 降低程序清晰性,容易出错

float average(float array[], int n) { int i; float sum=array[0]; float max,min; float average(float array[], int n) { int i; float 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+=array[i]; } return(sum/n); void main() { int i; float ave,score[10]; /*Input */ ave=average(score,10); printf("max=%6.2f\nmin=%6.2f\n average=%6.2f\n",max,min,ave); 作用域 max min

int p=1,q=5; float f1(int a) { int b,c; ……. } int f3() {….. char c1,c2; char f2(int x,int y) { int i,j; …… main() { int m,n; c1,c2的作用范围 p,q的作用范围 extern char c1,c2; c1,c2 的作用范围 扩展后 c1,c2 的作用范围 扩展后 extern char c1,c2;

例 外部变量定义与说明 int max(int x, int y) { int z; z=x>y?x:y; return(z); } void main() { extern int a,b; printf("max=%d",max(a,b)); int a=13,b=-8; extern int a,b; int max() { int z; z=a>b?a:b; return(z); } void main() { printf("max=%d",max()); int a=13,b=-8; 运行结果:max=13

printf("max=%d",max(a,b)); 例 外部变量与局部变量 /*ch7_17.c*/ int a=3,b=5; max(int a, int b) { int c; c=a>b?a:b; return(c); } void main() { int a=8; printf("max=%d",max(a,b)); 运行结果:max=8

例 外部变量副作用 int i; void main() { void prt(); for(i=0;i<5;i++) prt(); 例 外部变量副作用 int i; void main() { void prt(); for(i=0;i<5;i++) prt(); } void prt() { for(i=0;i<5;i++) printf(“%c”,’*’); printf(“\n”); 运行结果:*****

动态变量与静态变量 存储方式 内存用户区 生存期 程序区 静态存储区 全局变量、局部静态变量 形参变量 静态存储:程序运行期间分配固定存储空间 动态存储:程序运行期间根据需要动态分配存储空间 内存用户区 生存期 静态变量:从程序开始执行到程序结束 动态变量:从包含该变量定义的函数开始执行至函数执行结束 程序区 静态存储区 动态存储区 全局变量、局部静态变量 形参变量 局部动态变量(auto register) 函数调用现场保护和返回地址等

7.6变量存储类型 局部变量 外部变量 register 局部static auto 外部static 外部 存储类别 静态 动态 存储方式 静态存储区 动态区 存储区 寄存器 程序整个运行期间 函数调用开始至结束 生存期 作用域 定义变量的函数或复合语句内 本文件 其它文件 编译时赋初值,只赋一次 每次函数调用时 赋初值 自动赋初值0或空字符 不确定 未赋初值 局部变量默认为auto型 register型变量个数受限,且不能为long, double, float型 局部static变量具有全局寿命和局部可见性 局部static变量具有可继承性 extern不是变量定义,可扩展外部变量作用域

例 文件file1.c int a; void main( ) { ……. ……. f2; f1; } f1( ) { ……. ……. f2; f1; } f1( ) { auto int b; ……… …….. f2( ) { static int c; a作用域 main f2 f1 a生存期: b生存期: c生存期: b作用域 C作用域

例 auto 变量的作用域 void main() { int x=1; void prt(void); { int x=3; prt(); printf(“2nd x=%d\n”,x); } printf(“1st x=%d\n”,x); void prt(void) { int x=5; printf(“3th x=%d\n”,x); x=1作用域 x=3作用域 运行结果: 3th x=5 2nd x=3 1st x=1 x=5作用域

{ void increment(void); increment(); 例 局部静态变量值具有可继承性 void main() { void increment(void); increment(); } void increment(void) { int x=0; x++; printf(“%d\n”,x); void main() { void increment(void); increment(); } void increment(void) { static int x=0; x++; printf(“%d\n”,x); 运行结果:1 1 运行结果:1 2 3

#include <stdio.h> int i=1; void main() { static int a; i:1 a:0 b:-10 c:0 全局i 1 main: a b:-10 register main:c 静态 存储区 动态 other: a 2 other: b 43 33 75 #include <stdio.h> int i=1; void main() { static int a; register int b=-10; int c=0; printf("-----MAIN------\n"); printf("i:%d a:%d \ b:%d c:%d\n",i,a,b,c); c=c+8; other(); printf("i:%d a:%d \ i=i+10; } 例 变量的寿命与可见性 ------Other------ i:33 a:4 b:0 c:15 4 6 6 4 -------Main----- i:33 a:0 b:-10 c:8 -------Other------- i:75 a:6 b:4 c:15 other: c 10 other: c 10 15 15 8 other() { static int a=2; static int b; int c=10; a=a+2; i=i+32; c=c+5; printf("-----OTHER------\n"); printf("i:%d a:%d \ b:%d c:%d\n",i,a,b,c); b=a; }

void main() { void gx(),gy(); extern int x,y; printf(“1: x=%d\ty=%d\n”,x,y); y=246; gx(); gy(); } void gx() { extern int x,y; x=135; printf(“2: x=%d\ty=%d\n”,x,y); int x,y; void gy() { printf(“3: x=%d\ty=%d\n”,x,y); 例 用extern扩展外部变量作用域 运行结果: 1: x=0 y=0 2: x=135 y=246 3: x=135 y=246

int global; float x; extern int global; extern float x; 例 引用其它文件中的外部变量 int global; extern float x; main() { int local; . } extern int global; static int number; func2() { . float x; func3() { extern int global; file1.c file2.c file3.c

例 引用其它文件中的变量,输出ab和a的m次方 int a; void main() { int power(int n); int b=3,c,d,m; printf("Enter the number a and its power:\n"); scanf("%d,%d",&a,&m); c=a*b; printf("%d*%d=%d\n",a,b,c); d=power(m); printf("%d**%d=%d",a,m,d); } extern int a; int power(int n) { int i,y=1; for(i=1;i<=n;i++) y*=a; return(y);

写出下列程序的运行结果: f(int x)       {int a=1; static int b=2; b+=1;a++; return(a+b+x); } void main() { int i=0; for(  ;i<3;i++) printf(“%d”,f(i));

上面的C程序段的输出结果是__________。 void fun(int *x, int *y) { *x=3; *y=4; } void main() { int x=1,y=2; printf("%d %d ",x, y); fun(&y,&x); printf("%d %d",x, y); 上面的C程序段的输出结果是__________。 a)2 1 4 3 b) 1 2 1 2 c)1 2 4 3 d)2 1 1 2

7.7 内部函数和外部函数 内部函数 外部函数 static 类型标识符 函数名(形参表) extern 类型标识符 函数名(形参表) 只能被本文件中其它函数调用的函数。 定义形式: static 类型标识符 函数名(形参表) 外部函数 可以被其它文件中的函数调用的函数。 extern 类型标识符 函数名(形参表) extern可以省略。 在需要调用本函数的文件中,用extern声明所调用的函数是外部函数。