第6章 函数 学习的意义
学习的意义 …… …… …… …… 达积木 软件项目 功能模块1 功能模块2 功能模块n C语言程序 子模块1 子模块2 子模块n
第6章 函数 本章要求 本章重点 本章难点 理解模块化程序设计思想; 掌握函数的定义与调用方法; 第6章 函数 本章要求 理解模块化程序设计思想; 掌握函数的定义与调用方法; 掌握C语言的参数传递方式,尤其是数组参数的传递特点; 掌握变量的作用域和存储方式。 本章重点 函数的定义与调用 参数传递 变量的作用域和存储方式 本章难点 参数传递 变量的作用域和存储方式
第6章 函数 6.1 函数概述 6.2 函数的定义 6.3 函数调用与参数传递 6.4 函数与指针 6.5 main函数的参数 第6章 函数 6.1 函数概述 6.2 函数的定义 6.3 函数调用与参数传递 6.4 函数与指针 6.5 main函数的参数 6.6 函数与变量的作用域 6.7 应用程序举例
6.1 函数概述 6.1.1 程序化设计方法 模块化程序设计方法: 人们在求解某个复杂问题时,通常采用逐步分解、分而治之的方法,也就是将一个大问题分解成若干个比较容易求解的小问题,然后分别求解。程序员在设计一个复杂的应用程序时,往往也是把整个程序划分成若干个功能较为单一的程序模块,然后分别予以实现,最后再把所有的程序模块象达积木一样装配起来,这种在程序设计中分而治之的策略,被称为模块化程序设计方法。
6.1 函数概述 例6-1 编写一个显示欢迎信息的程序,要求所有的信息均在一个星号组成的矩形框中显示。 程序输出如下: 例6-1 编写一个显示欢迎信息的程序,要求所有的信息均在一个星号组成的矩形框中显示。 程序输出如下: *************************** *Please input your name! * *Xiao Qiang * *Welcome to the C world! *
程序代码如下: #include <stdio.h> #include <string.h> #define USERNAME "XiaoQiang" void message(char *s); //函数声明 void main() { char name[10]; message("Please input your name!"); //函数调用 scanf("%s",name); if(strcmp(name,USERNAME)==0) message("Welcome to the C world!"); else message("Error Username"); //函数调用 } void message(char *s) //函数定义 { int n,i; n=strlen(s); //求字符串S的长度 for(i=1;i<=n+4;i++) printf("%c",'*'); printf("\n"); printf("* %s *\n",s); }
6.1 函数概述 程序输出如下: C程序的层次关系 *************************** *Please input your name!* XiaoQiang *Welcome to the C world!* C程序的层次关系
6.1 函数概述 C语言使用函数作为程序的组成单元的优点是: 1)简化程序设计: 2)便于调试和维护: 将常执行的一些操作写成函数后,可以像利用库函数一样 调用。 2)便于调试和维护: 庞大的程序分成若干功能独立的小模块,便于管理和调试。
6.1 函数概述 6.1.2 C函数的分类 从使用角度划分 从函数形式划分 从函数的结果划分 从函数的存储类型划分 标准函数,即库函数 (#include) 自定义函数 (为解决不同问题而编写) 从函数形式划分 无参函数 (函数定义时圆括号内为空或者void) 有参函数 从函数的结果划分 无返回值函数 (完成某项任务不向主函数返回函数值) 有返回值函数 (返回结果) 从函数的存储类型划分 外部函数(extern) (可以被其他文件中的函数调用) 静态函数(static) (只限于本文件中的函数用)
6.2 函数的定义 6.2.1一般格式 格式一: 函数返回值类型 合法标识符 缺省int型 无返回值void 函数类型 函数名(形参类型说明表) { 说明部分( (即:变量定义) ) 语句部分 } 格式一: 函数体 例 无参函数 printstar( ) { printf(“**********\n”); } 或 printstar(void ) 例 有参函数 int max(int x, y) { int z; z=x>y?x:y; return(z); } 例 有参函数 int max(int x,int y) { int z; z=x>y?x:y; return(z); } 例 空函数 dummy( ) { } 函数体为空
6.2 函数的定义 6.2.2 函数返回值 说明: C语言通过return语句获得函数返回值的,其格式如下: return 表达式; 或 return(表达式); 说明: 表达式的值即函数返回值,它应与所定义的函数返回值的类型一致 一个函数可以有多条return语句,执行到哪一条return语句,哪一条起作用 return语句的另一作用是终止执行函数 为增加程序的可读性,建议只在函数结尾处使用一次return语句
6.2 函数的定义 6.2.3 形式参数的设计 设计形式参数应从函数的功能分析入手,那个数据需要调用函数提供,这就应定义一个形式参数接收该数据 。 例6-3 编写一个函数求一个3位正整数的逆序数,如123的逆序数是321。 #include <stdio.h> int fun(int n); //函数声明 void main() { int x,y; do { printf(" Enter a number x=?:"); scanf("%d",&x); }while(x<100||x>999); y=fun(x); //函数调用 printf("Inverse number:%d\n",y); } int fun(int n) //函数定义 { int a,b,c,m; a=n%10; b=n/10%10; c=n/100; m=a*100+b*10+c; return(m);
6.2 函数的定义 6.2.4 函数原型 在使用自定义函数时,除了进行函数的定义外,还需要在调用该函数之前对其进行原型声明 函数原型声明和函数定义的区别 函数原型声明的作用是将函数类型告诉编译系统,使程序在编译阶段对调用函数的合法性进行全面的检查,避免函数调用时出现参数的个数或类型不一致的运行错误。 函数定义部分则是函数的实际实现代码 函数原型声明的格式:类型符 函数名(形式参数); 说明: (1)函数原型声明语句最后的分号不能省略,其作用是表示该语句是进行函数声明而不是函数定义。 (2)在原型声明中,形式参数名可以省略。 (3)如果被调用函数的定义出现在调用函数之前,可以不对被调用函数进行原型声明。 (4)如果被调用函数已在所有函数定义之前进行了原型声明,则在各个调用函数中不必再对该函数进行原型声明 。
例: 函数说明举例 void main( ) { float add(float,float); //函数原型声明 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); 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型函数可不作函数说明(BC、VC下不行) 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); 被调函数出现在主调函数之前,不必函数说明
6.3 函数调用与参数传递 6.3.1 函数的调用方式 有参函数调用的格式:函数名(实际参数) 无参函数的调用格式:函数名( ) 说明 函数总是在某个函数体中被调用 函数调用可以在结尾处加上分号,单独作为一条语句 对于有返回值的函数,其调用也可以出现在某条语句中 函数的调用过程
void 函数名( void ); 或 void 函数名( ); 6.3 函数调用与参数传递 必须为合法的标识符 四类函数的详细说明 1、无参数无返回值的函数 定义格式 void 函数名 (void) { 变量声明部分 执行部分 } 空类型,表明函数无返回值,不可省! 表明无参数,可缺省! 函数体 函数用途 此类函数用于完成某项固定的处理任务,执行完成后不向调用者返回函数值。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 函数的原型声明 void 函数名( void ); 或 void 函数名( ); C规定,对函数调用前必须对其原型加以声明,否则会出现编错! 17
注意:不能将这种函数调用赋值给任何变量,因为它没有返回值。调用时,( )中间不能有void。 1、无参数无返回值的函数 #include <stdio.h> #include <math.h> void showerror ( ); //声明showerror函数的原型 void main ( ) { int a; scanf ("%d", &a); while (a < 0) showerror( ); } printf ("sqrt(a) = %.2f\n", sqrt(a)); void showerror( ) //函数的定义,无参数无返回值 printf("input error!\n"); //函数体,没有声明变量 函数的调用 函数名( ); 注意:不能将这种函数调用赋值给任何变量,因为它没有返回值。调用时,( )中间不能有void。 实例 注意:对函数调用之前,必须要先声明或先定义,否则编译错! 调用showerror 函数 返回 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 18
文件包括(如include <stdio.h>等,用于标准库库函数原型声明) 常量定义(根据需要而定,如#define PI 3.1415等) 变量定义(根据需要而定) 用户自定义函数原型声明 main函数 用户自定义函数 例如: void showyes ( ) { char key; key = getchar ( ); if (strupr(key) != 'Y') return; printf ("YES! "); } 函数showyes的功能是: 如果输入的字符不是'Y'或'y',则什么都不输出,直接返回,否则,输出"YES! " 函数的返回 形式 ① rerurn (表达式); //有返回值 ② rerutn 表达式; //有返回值 ③ return; //无返回值 标准库函数,其功能是将小写字符转换成大写字符 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 功能 使程序控制从被调用函数返回到调用函数中,如果有返回值,同时把返值带给调用函数。 说明 函数中可以有多个return语句。在无返回值的函数中,return语句的形式只能是第③种形式。 19
此类函数用于完成某项固定的处理任务,执行完成后向调用者返回函数值。 2、无参数有返回值的函数 必须为合法的标识符 定义格式 返回值类型符 函数名 (void) { 变量声明部分 执行部分 } 可以为除数组类型外的任何类型,缺省时,默认为int型 函数体 表明无参数,可缺省! 函数用途 此类函数用于完成某项固定的处理任务,执行完成后向调用者返回函数值。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 函数的原型声明 返回值类型符 函数名( void ); 或 返回值类型符 函数名( ); 函数的调用 函数名( void ); 或 变量 = 函数名( ); 20
rerurn (表达式); 或 rerutn 表达式; 2、无参数有返回值的函数 函数的返回 格式 rerurn (表达式); 或 rerutn 表达式; #include <stdio.h> int sum ( ); void main ( ) { int x; x = sum ( ); printf (“x = %d\n", x); } int sum ( ) int i, tot = 0; for (i = 1; i <= 100; i ++) tot += i; 因sum函数无return语句, x的值将是无法预知的! 应加上 return tot; 语句 说明 表达式的值即是函数的返回值; 函数体中一般都包含return(表达式)语句, 如果没有, 函数也会返回一个值。这个值是不可预知的, 将会使程序可能犯有逻辑错; 一般情况下,表达式值的类型应与函数返回值类型一致; 当return(表达式)语句中的表达式的类型与函数的返回值类型不一致时,编译器将对表达式进行强制类型转换, 将表达式的值强制转换成函数返回值类型, 然后返回给调用者。 注意:如果不将函数调用赋值给任何变量,它的返回值将被丢弃! 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 int func ( ) { float f = 5; f = f / 2; return ( f ); } 函数将返回2,而不是2.5 21
此类型的函数主要是根据形参的值来进行某种事务的处理。灵活性上要比无形参的函数强,它更能体现调用函数与被调函数之间的数据联系。 3、有参数无返回值的函数 至少要有一项,形参之间要用逗号“,”分开 定义格式 void 函数名 (类型符1 形参名1, 类型符2 形参名2, … , 类型符n 形参名n ) { 变量声明部分 执行部分 } 形参列表 函数体 不允许对 形参赋初值 指明形参类型 函数用途 此类型的函数主要是根据形参的值来进行某种事务的处理。灵活性上要比无形参的函数强,它更能体现调用函数与被调函数之间的数据联系。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 函数的原型声明 void 函数名(类型符1 形参名1, 类型符2 形参名2, … , 类型符n 形参名n ); 或 void 函数名(类型符1 , 类型符2 , … , 类型符n ); 22
(1) 实参列表中的实参必须与函数定义时的形参数量相同、类型相符。 (2) 赋值对应关系: 实参1 -> 形参1 3、有参数无返回值的函数 实参可以是常量、变量、表达式、函数等 函数调用 函数名( 实参1,实参2,……,实参n ); 注意事项: (1) 实参列表中的实参必须与函数定义时的形参数量相同、类型相符。 (2) 赋值对应关系: 实参1 -> 形参1 实参2 -> 形参2 …… 实参n -> 形参n (3)实参表求值顺序(即实参赋值给形参的顺序) 因系统而定。TC、BC、VC均是自右向左,也就是说最右边的实参最先赋值给最右边的形参, 最左边的实参最后赋值给最左边的形参。但VC与TC、BC在具体赋值时稍有不同,注意它们之间的区别。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 23
3、有参数无返回值的函数 运行结果(在VC下) i 2 j 3 a b 实参 形参 2 2 3 #include <stdio.h> void compare (int a, int b); void main ( ) { int i = 2,j=3; compare ( i, j ); printf ("i = %d,j=%d\n", i,j); } void compare ( int a, int b ) printf ("a = %d b = %d\n", a, b); if ( a > b) printf ("a > b\n"); else if (a == b) printf ("a = b\n"); printf ("a < b\n"); 原型声明 i,j为实参 a、b为形参 a = 2 b = 3 a < b i = 2,j=3 运行结果(在VC下) 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 i 2 j 3 a b 实参 形参 2 ② ① 2 3 24
此类型的函数主要是根据形参的值来进行某种事务的处理,同时可将处理后的结果值返回给调用函数 。它最能体现调用函数与被调函数之间的数据联系。 4、有参数有返回值的函数 定义格式 返回值类型符 函数名 (类型符1 形参名1, … … , 类型符n 形参名n ) { 变量声明部分 执行部分 } 形参列表 函数体 函数用途 此类型的函数主要是根据形参的值来进行某种事务的处理,同时可将处理后的结果值返回给调用函数 。它最能体现调用函数与被调函数之间的数据联系。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 函数的原型声明 返回值类型符 函数名(类型符1 形参名1, …… , 类型符n 形参名n ); 或 返回值类型符 函数名(类型符1 , 类型符2 , …… , 类型符n ); 25
变量名 = 函数名( 实参1,实参2,……,实参n ); 4、有参数有返回值的函数 函数调用 函数名( 实参1,实参2,……,实参n ); 或 变量名 = 函数名( 实参1,实参2,……,实参n ); #include <stdio.h> int max (in t a, int b); //函数的原型声明 void main ( ) { int a, b, c; scanf ("%d%d", &a, &b); c = max (a, b); //函数调用(a、b为实参) printf ("the biggest number is : %d\n", c); } int max (int a, int b) //函数定义(a、b为形参) return (a > b ? a : b); 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 运行结果: 5 9↙ the biggest number is 9 26
6.3 函数调用与参数传递 函数调用和函数说明小结 函数调用 函数语句: 例:printstar ( ); printf (“Hello,World!\n”); 函数表达式: 例: m = max (a, b) * 2; 函数参数: 例: printf (“%d”, max(a,b)); m = max (a, max(b,c)); 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 27
函数说明 对被调用函数要求: 必须是已存在的函数 库函数: #include <*.h> 用户自定义函数: 函数类型说明 一般形式: 函数类型 函数名(形参类型 [形参名],….. ); 或 函数类型 函数名( ); 作用:告诉编译系统函数类型、参数个数及类型,以便检验 函数定义与函数说明不同 函数说明位置:程序的数据说明部分(函数内或外) 下列情况下,可不作函数说明 若函数返值是char或int型,系统自动按int型处理 被调用函数定义出现在主调函数之前 有些系统(如BC、VC)要求函数说明指出函数返值类型和形参类型,并且对void 和 int 型函数也要进行函数说明
6.3 函数调用与参数传递 6.3.2 参数传递 参数是函数调用进行信息交互的载体,分形参和实参。 形式参数又称为形参或虚参:定义函数时,写入函数圆括号内的参数。事实上,形参是一种局部变量,它在函数被调用前并没有被分配存储空间,也没有具体的值。形参仅仅是一个“符号”。 实际参数又称为实参:调用函数时,写入函数圆括号内的参数,可以是常量、变量或表达式,它有具体的值。对于实参变量而言,它已经被分配了相应的存储空间。 函数之间参数的传递: 调用有参函数,系统根据形参的类型为其分配存储空间,其内容为形参的值。调用时应该提供与形参匹配的实参,匹配——个数和类型。
例: 交换两个数(值传递方式) Why? 7 x 11 y ① 调用前 7 x 11 y ① 调用前 7 x 11 y ① 调用前 7 x #include <stdio.h> void swap (int a, int b); void main ( ) { int x = 7, y = 11; printf ("before swapped: "); printf ("x=%d, y=%d\n", x, y); swap (x, y); printf ("after swapped: "); } void swap (int a, int b) int temp; temp = a; a = b; b = temp; 7 x 11 y ② 调用 7 x 11 y ② 调用 7 x 11 y ② 调用 7 x 11 y ② 调用 7 a 11 b ③ swap 7 x 11 y a b temp ③ swap 7 x 11 y a b temp ③ swap 7 x 11 y a b temp Why? 11 7 7 运行结果: before swapped: x = 7, y = 11 after swapped: x = 7, y = 11 7 x 11 y ④ 调用结束 7 x 11 y ④ 调用结束
#include <stdio.h> void swap (int a, int b); void main ( ) { 6.3.3 指针变量作参数(仍为值传递) 7 x 11 y ① 调用前 7 x 11 y ① 调用前 7 x 11 y ① 调用前 #include <stdio.h> void swap (int a, int b); void main ( ) { int x = 7, y = 11; printf ("before swapped: "); printf ("x=%d, y=%d\n", x, y); swap (&x, &y); printf ("after swapped: "); } void swap (int *a, int *b) int temp; temp = *a; *a = *b; *b = temp; 7 x 11 y ② 参数传递 &x a &y b ③ swap 11 x 7 y &x a &b b ③ swap ③ swap ③ swap ③ swap ③ swap 7 y &x a &x a &x a &x a &b b &b b &b b 运行结果: before swapped: x = 7, y = 11 after swapped: x = 11, y =7 11 x 7 y ④ 调用结束
6.3 函数调用与参数传递 注意:不能试图通过调用以下函数来交换实参变量的值。 程序代码如下: void swap(int *a,int *b) { int *t; t=a; a=b; b=t; }
6.3 函数调用与参数传递 C语言中的参数传递是一种单向的“值传递”。 1、值传递方式 方式: 函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值。 特点: ① 形参与实参占用不同的内存单元 ② 单向传递 这种参数传递过程被形象的称为“虚实结合”。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 33
6.3 函数调用与参数传递 6.3.4 数组参数 当程序中需要处理一批相关数据时,往往用数组。若要实现函数功能时需要获取一批相关数据作为原始信息,这个时候就可以考虑用数组参数。 本节主要讨论的是数组整体作为参数传递。 单个数组元素作为实参仍然为值传递
6.3 函数调用与参数传递 数组元素作为参数 求三个数的平均值: 程序的运行: main( ) { float fun(float a,float b,float c); float a[3]={1,2,3}; float ave=0; ave=fun(a[0],a[1],a[2]); } float fun(float a,float b,float c) { float sum,aver; sum=a+b+c; aver=sum/3.0; return(aver); main( ) a[0] 1 a[1] 2 a[2] 3 数组元素a[0] , a[1],a[2]作实参 值传递 ave ①传值 fun( ) a 1 b 2 c 3 ②执行 函数体 sum 6 ③返回函数值 释放相应空间 aver 2
6.3 函数调用与参数传递 一维数组参数(与值传递方式不同) 例6-7 定义一个函数max_value用于返回一个10个元素组成的一维整型数组中的最大值。
程序代码如下: #include <stdio.h> #include <stdlib.h> #include <time.h> int max_value(int a[]); //函数原型声明 void main() { int x[10],i; printf("Array:"); srand(time(NULL)); //初始化随机数发生器 for(i=0;i<10;i++) { x[i]=rand()%90+10; //随机产生两位正整数 printf("%3d",x[i]); } printf("\nMax value:%2d\n",max_value(x)); //函数调用 int max_value(int a[]) //求最大值函数 { int i,t; t=a[0]; for(i=1;i<10;i++) if(a[i]>t)t=a[i]; return(t);
6.3 函数调用与参数传递 一维数组参数 数组参数传递 通常情况下,数组做函数参数,需要再定义一个整型形参,用于传递数组元素个数的信息。 传递数组的首地址 通常情况下,数组做函数参数,需要再定义一个整型形参,用于传递数组元素个数的信息。
数组名作为函数参数 求三个数的平均值: 程序的运行: #include <stdio.h> main( ) { float fun2(float x[3]); float a[3]={87.5,90,100}; float ave=0; ave=fun2(a); } float fun2(float x[3]) { float sum,aver; sum=x[0]+x[1]+x[2]; aver=sum/3.0; return(aver); main( ) a a[0] 87.5 x[0] a[1] 90 x[1] a[2] 100 x[2] 地址传递 ave 地址传递 ①传地址 fun2( ) x sum 277.5 ③返回 函数值 释放相 应空间 aver 92.5 ②执行 函数体 形参与实参共用地址空间
释放 地址传递使形参与实参共用地址空间, 形参值改变,则实参值也改变 两个数交换数值: 程序的运行: #include <stdio.h> main( ) { void swap(int x[2]); int a[2]={4,9}; swap(a); printf(“%d,%d\n”,a[0],a[1]); } void swap(int x[2]) { int t; t=x[0]; x[0]=x[1]; x[1]=t; main( ) 释放 a a[0] 4 x[0] a[1] 9 x[1] 9 4 swap( ) x ①传地址 t 4 长度2可省 实参数组必须指定长度,形参数组则不必。 形参数组并没有另外分配空间,而是共享实参数组的数据。 使用形参数组时不要超过实参数组的长度。 ③返回 函数值 释放相 应空间 ②执行 函数体
2、地址传递方式 定义形式:类型名 形参数组名[] 方式: 函数调用时,将数据的存储地址(同类型数组名称)作为参数传递给形参 特点: ① 形参与实参占用同样的存储单元 ② 双向传递 ③ 实参和形参必须是地址常量或变量 判断以下定义形式哪些是正确的? int max(int x[3]) int max(int x[]) int max(x[3]) int max(int x) 用数组名作为函数参数时还应注意以下几点: 形参数组和实参数组的类型必须一致,否则将引起错误。 形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。 多维数组也可以作为函数的参数。在函数定义时对形参数组可以指定每一维的长度,也可省去第一维的长度。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 41
6.3 函数调用与参数传递 例6-8编写一个实现一维数组排序的函数。 #include <stdio.h> 程序代码如下: #include <stdio.h> #include <stdlib.h> #include <time.h> void sort(int a[],int n); //函数原型声明 void main() { int x[10],i; srand(time(NULL)); printf("Before sorting:\n"); for(i=0;i<10;i++) { x[i]=rand()%90+10; printf("%3d",x[i]); } sort(x,10); //函数调用 printf("\nAfter sorting:\n");
6.3 函数调用与参数传递 void sort(int a[],int n) //排序函数 { int i,j,k,t; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(a[k]>a[j])k=j; if(k!=i) { t=a[i]; a[i]=a[k]; a[k]=t; }
6.3 函数调用与参数传递 多维数组参数 #include <stdio.h> 多维形参数组的定义形式为:类型名 形参数组名[][数值]……[数值],即除了最左边的方括号可能留空外,其余都要填写数值。 调用使用多维数组参数的函数时,与形参数组对应的实参是一个同类型的数组名,也不需要加上任何方括号。 例6-10 编写一个函数用于查找并返回3×4的矩阵中的最大元素。 程序代码如下: #include <stdio.h> #include <stdlib.h> #include <time.h> int max_value(int a[][4],int n, int *row, int *col); void main() { int x[3][4]; int m,i,j,r,c; srand(time(NULL)); for(i=0;i<3;i++) { for(j=0;j<4;j++)
6.3 函数调用与参数传递 { x[i][j]=rand()%90+10; printf("%3d",x[i][j]); } printf("\n"); m=max_value(x,3,&r,&c); printf("The max value is %d\n",m); printf("The position is %d row, %d column\n",r,c); int max_value(int a[][4],int n, int *row, int *col) { int max,i,j; max=a[0][0]; *row=0; *col=0; for(i=0;i<n;i++) for(j=0;j<4;j++) if(max<a[i][j]) { max=a[i][j]; *row=i; *col=j; return(max);
实参与形参的小结 实参 形参 传递方式 常量、变量、表达式、数组元素 变量 传值(单向) 数组名 数组 传数组首地址
6.3 函数调用与参数传递 6.3.5 函数的嵌套与递归调用 1、函数的嵌套调用 ——函数嵌套调用的示意图 C规定:函数定义不可嵌套,但可以嵌套调用函数 嵌套调用:在调用一个函数的过程中又调用了另外一个函数,叫作函数的嵌套调用。 嵌套调用的执行过程:从什么地方调用函数,就返回到什么地方。 main( ) 调用函数a 结束 a函数 b函数 调用函数b ——函数嵌套调用的示意图
函数的嵌套调用 main( )函数 a( )函数 b( )函数 ① ② ③ ④ . 调用函数a . 调用函数b ⑤ ⑧ ⑥ ⑦ ⑨ 结束
【例】计算三个数中最大数与最小数的差。 #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); } 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) r = x < y ? x : y; return (r < z ? r : z); main( ) dif函数 max函数 调用函数dif 调用函数max min函数 输出 结束 调用函数min
6.3 函数调用与参数传递 例6-11 编写一个小学四则运算练习程序,程序可根据用户的选择随机生成加、减、乘、除练习题目,并分析运算结果是否正确。 程序代码如下: #include <stdio.h> #include <stdlib.h> #include <time.h> void exam(int n); void add(void); void sub(void); void mul(void); void division(void);
6.3 函数调用与参数传递 void main() { int n; while(1) { printf("********\n"); printf("*1-ADD *\n"); printf("*2-SUB *\n"); printf("*3-MUL *\n"); printf("*4-DIV *\n"); printf("*0-EXIT*\n"); printf("********\n"); printf("Please select 0-4:"); scanf("%d",&n); if(n<0||n>4)printf("Invalid number!\n"); else if(n==0)break; else exam(n); }
6.3 函数调用与参数传递 void exam(int n) { switch(n) case 1:add(); break; case 2:sub(); break; case 3:mul(); break; case 4:division(); }
6.3 函数调用与参数传递 void add(void) //求两随机整数之和 { int x,y,z,result; srand(time(NULL)); //初始化系统随机数发生器 x=rand()%100; //产生0~99的随机整数 y=rand()%100; z=x+y; printf("%d+%d=",x,y); scanf("%d",&result); if(result==z)printf("OK\n"); else printf("Sorry\n%d+%d=%d\n",x,y,z); }
6.3 函数调用与参数传递 void sub(void) //求两随机整数之差 { int x,y,z,result; srand(time(NULL)); x=rand()%100; y=rand()%100; z=x-y; printf("%d-%d=",x,y); scanf("%d",&result); if(result==z)printf("OK\n"); else printf("Sorry\n%d-%d=%d\n",x,y,z); }
6.3 函数调用与参数传递 void mul(void) //求两随机整数之乘积 { int x,y,z,result; srand(time(NULL)); x=rand()%100; y=rand()%100; z=x*y; printf("%d*%d=",x,y); scanf("%d",&result); if(result==z)printf("OK\n"); else printf("Sorry\n%d*%d=%d\n",x,y,z); }
6.3 函数调用与参数传递 void division(void) //求两随机整数之商 { int x,y,z,result; srand(time(NULL)); do //产生两随机整数使得x能被y整除 { x=rand()%100; y=rand()%100; }while(x%y!=0||y==0); z=x/y; printf("%d/%d=",x,y); scanf("%d",&result); if(result==z)printf("OK\n"); else printf("Sorry\n%d/%d=%d\n",x,y,z); }
6.3 函数调用与参数传递
2、函数递归调用 说明 定义:函数直接或间接的调用自身叫函数的递归调用 int f (int x) int f1 (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( ) 直接递归 间接递归 说明 C编译系统对递归函数的自调用次数没有限制 递归调用应注意的问题: 要防止无限次的递归调用。 防止无限递归调用的方法:使用 if 语句设置一个递归过程结束 的条件,且在递归过程中使该条件逐步趋于成立
递归过程及其实现 递归:函数直接或间接的调用自身叫递归 实现:建立递归工作栈 【例1】递归的执行情况分析 运行结果: 1, 2,2, #include <stdio.h> void print (int w); void main ( ) { print ( 3 ); } void print (int w) //递归函数 { int i; if ( w != 0) //递归结束条件 print (w-1); for (i = 1; i <= w; ++i) printf ("%d ", w); printf ("\n"); } 运行结果: 1, 2,2, 3,3,3,
递归调用执行情况如下: 1 print(0); (3)w=1 (2)w=2 (1)w=3 top (4)输出:1 w (4)w=0 (4)w=0 (3)w=1 (2)w=2 (1)w=3 top w void main ( ) { print ( 3 ); } 2 print(1); (2)w=2 (1)w=3 top (3) 输出:2, 2 w 返回 (3) 1 (2) 2 (1) 3 top (4) 0 3 print(2); (1)w=3 top (2) 输出:3, 3, 3 w (4)输出:1 (3) 1 (2) 2 (1) 3 top 主程序 void print (int w) //递归函数 { int i; if ( w != 0) //递归结束条件 print (w-1); for (i = 1; i <= w; ++i) printf ("%d ", w); printf ("\n"); } } (3) 输出:2, 2 (2) 2 (1) 3 top (1) print(w) w=3; (2) 输出:3, 3, 3 (1 ) 3 top 结束 (1)
【例2】求n的阶乘n! 方法一:利用循环 因为n! = n * (n-1) * (n-2) * … * 2 * 1,我们完全可以用循环语句来编写这个非递归函数factn: long factn (int n) { long L = 1; int i; for (i = 1; i <= n; i++) L *= i; return ( L ); } 方法二:利用递归 n! = 1 当n = 1时 n * (n - 1)! 当n > 1时 long factn (int n) { long L; if (n == 1) return (1); L = n * fact (n-1); return (L); }
递归调用执行情况如下: void main ( ) { … L = factn(4); } long factn(4) { long L; 返回24 long factn(4) { long L; … L = 4*factn(3); return (L); } long factn(3) { long L; … L = 3*factn(2); return (L); } long factn(2) { long L; … L = 2*factn(1); return (L); } long factn(1) { long L; … return (1); } 返回6 返回2 返回1
6.3 函数调用与参数传递 总结函数递归调用: 递归条件: (1)原有的问题能够分解为一个新问题,而新问题又用到了原有的解法,这就出现了递归。递归公式。 (2)按照这个原则分解下去,每次出现的新问题是原有问题的简化的子问题 (3)最终分解出来的新问题是一个已知解的问题。递归结束条件 递归调用过程(两个阶段) (1)递推阶段:将原问题不断地分解为新的子问题,逐渐从未知的向已知的方向推测,最终达到已知的条件,即递归结束条件,这时递推阶段结束。 (2)回归阶段:从已知条件出发,按照“递推”的逆过程,逐一求值回归,最终到达“递推”的开始处,结束回归阶段,完成递归调用。
6.4 函数与指针 6.4.1 返回指针值的函数 定义形式为: 类型名 *函数名(形式参数) 6.4 函数与指针 6.4.1 返回指针值的函数 当需要将一批数据作为一个整体返回时,常使用返回指针值的函数。 定义形式为: 类型名 *函数名(形式参数) 例如:int *f(int a,int b); f的返回值是一个指向整型数据的指针。 例6-13 有30个学生成绩(每人5门课程),要求编写一个函数用于查询指定学生的成绩。 #include <stdio.h> #include <stdlib.h> #define M 30 #define N 5 int *search(int score[][N],int num); // 函数原型说明
6.4 函数与指针 void main() { int score[M][N],i,j,num; int *p; 6.4 函数与指针 void main() { int score[M][N],i,j,num; int *p; srand(time(NULL)); for(i=0;i<M;i++) { for(j=0;j<N;j++) { score[i][j]=rand()%100; printf("%4d",score[i][j]); } printf("\n"); printf("Input a number(1-30):"); scanf("%d",&num); p=search(score,num); printf("No.%d scores:",num); for(j=0;j<N;j++) printf("%3d",*(p+j));
6.4 函数与指针 int *search(int score[][N],int num) { int *p; 6.4 函数与指针 int *search(int score[][N],int num) { int *p; p=&score[num][0]; // 取得第num行的第0行的元素地址 return(p); } 备注:返回的指针必须是该函数调用结束后不被释放的内 存地址
6.4 函数与指针 6.4.2 *函数的指针 C程序需要编译后才能执行,构成C程序的每一个函数在编译时都被分配了一块存储空间,其中存放着实现该函数功能的各条指令。函数名代表了函数存储空间的起始地址,即函数的指针。 C语言允许定义一个指针变量存放函数的入口地址,这种指针变量被称为指向函数的指针变量,其定义形式如下: 类型名 (*指针变量名)(参数类型); int (*p)(void)
6.4 函数与指针 例6-14 编写一程序,根据用户输入的半径,分别计算圆柱体和圆锥体的体积。 6.4 函数与指针 例6-14 编写一程序,根据用户输入的半径,分别计算圆柱体和圆锥体的体积。 #include <stdio.h> #define PI 3.14 float v1(float r,float h); float v2(float r,float h);
6.4 函数与指针 void main() { float (*v)(float,float),r,h; int n; 6.4 函数与指针 void main() { float (*v)(float,float),r,h; int n; printf("You want to calculate the volume of:1-Cylind,2-Cone?"); scanf("%d",&n); switch(n) case 1:v=v1;break; case 2:v=v2;break; default:v=NULL; }
6.4 函数与指针 if(v!=NULL) { printf("Input r,h="); scanf("%f,%f",&r,&h); 6.4 函数与指针 if(v!=NULL) { printf("Input r,h="); scanf("%f,%f",&r,&h); printf("%f",(*v)(r,h)); } float v1(float r,float h) return(PI*r*r*h); float v2(float r,float h) return(PI*r*r*h/3.0);
6.4 函数与指针 说明: (1)与其它指针变量相同,指向函数的指针变量在使用前也必须进行初始化操作,具体形式为“指针变量=函数名”。不要写成“指针变量=函数名(形式参数)”的形式。 (2)指向函数的指针变量可以先后指向不同的函数,但需注意函数返回值的类型与定义指针变量时所说明类型的一致性(例题中所示)。 (3)通过指向函数的指针变量调用函数时,只需将“(*指针变量名)”代替传统调用中的函数名即可。 (4)对于指向函数的指针变量,++和--等运算是无意义的。
6.4 函数与指针 6.4.3 指向函数的指针变量作参数 例6-15 设计一个函数,调用它时可以计算圆柱体或者圆锥体的体积。 6.4 函数与指针 6.4.3 指向函数的指针变量作参数 例6-15 设计一个函数,调用它时可以计算圆柱体或者圆锥体的体积。 #include <stdio.h> #define PI 3.14 float v1(float r,float h); float v2(float r,float h); float vol(float r,float h,float (*f)(float,float));
6.4 函数与指针 void main() { float r,h; printf("Input r,h="); 6.4 函数与指针 void main() { float r,h; printf("Input r,h="); scanf("%f,%f",&r,&h); printf("Volume of cylind:%f\n",vol(r,h,v1)); printf("Volume of cone:%f\n",vol(r,h,v2)); } float v1(float r,float h) /* 求圆柱体的体积 */ return(PI*r*r*h);
6.4 函数与指针 float v2(float r,float h) /* 求圆锥柱体的体积 */ { 6.4 函数与指针 float v2(float r,float h) /* 求圆锥柱体的体积 */ { return(PI*r*r*h/3.0); } float vol(float r,float h,float (*f)(float,float)) return((*f)(r,h));
6.5 main函数的参数 带参数的main函数头部的定义形式如下: main(int argc,char *argv[]) /*或者main(int argc,char **argv)*/ C程序的执行流程是从main函数开始的,而main函数则是由系统调用的,因此传递给main函数的实参来自系统 例6-16 main函数的参数。 #include<stdio.h> main(int argc,char **argv) {int i; printf("The command line has %d arguments:\n",argc-1); for(i=1;i<argc;i++) printf("%d: %s\n",i,*(argv+i)); }
6.6 函数与变量的作用域 6.6.1、局部变量与全局变量 变量的作用域 6.6 函数与变量的作用域 6.6.1、局部变量与全局变量 变量的作用域 即变量的作用范围(或有效范围)。表现为变量有的可以在整个程序或其它程序中进行引用,有的则只能在局部范围内引用。 按其作用域范围可分为两种:即局部变量和全局变量 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 76
#include <stdio.h> #include <stdlib.h> 变量作用域 例6-17 变量作用域示例。 #include <stdio.h> #include <stdlib.h> #include <time.h> void trans(void); //函数原型声明 void main() { int a[10],i; printf("Before:\n"); srand(time(NULL)); for(i=0;i<10;i++) { a[i]=rand()%10; printf("%2d",a[i]); } trans(); printf("\nAfter:\n");
6.6 函数与变量的作用域 void trans(void) //倒置数组 { int i,t; for(i=0;i<5;i++) { t=a[i]; a[i]=a[9-i]; a[9-i]=t; }
在函数内作定义说明的变量,也称为内部变量 。 作用域 仅限于函数内,离开函数后不可再引用。 生存期 2、局部变量 定义 在函数内作定义说明的变量,也称为内部变量 。 作用域 仅限于函数内,离开函数后不可再引用。 生存期 从函数被调用的时刻到函数返回调用处的时刻(静态局部变量除外)。 int f1 ( int x, int y ) { int z; z = x > y ? x : y; return (z); } void f2 ( ) printf ("%d\n", z ); 局部变量 变量x、y、z的作用域 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 引用错误! 79
说明 (1) 主函数main( )中定义的变量也是局部变量,它只能在主函数中使用,其它函数不能使用。同时,主函数中也不能使用其它函数中定义的局部变量。 int f3 (int x); void main ( ) { int a = 2, b; b = a + y ; printf ("%d\n", b); } int f3 ( int x ) int y; y = a + 5; return ( y ); 局部变量 变量a、b的作用域 错误! 局部变量 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 变量x、y的作用域 错误! 80
(2) 形参变量属于被调用函数的局部变量;实参变量则属于全局变量或调用函数的局部变量。 说明 (2) 形参变量属于被调用函数的局部变量;实参变量则属于全局变量或调用函数的局部变量。 (3) 允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。 void subf ( ) { int a, b; a = 6, b = 7; printf("subf: a = %d, b = %d\n",a,b); } #include <stdio.h> void subf ( ); void main ( ) { int a, b; a=3, b=4; printf ("main: a = %d, b = %d\n", a, b); subf ( ); } 变量名相同 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 运行结果: main: a = 3, b = 4 subf: a = 6, b = 7 81
(4) 在复合语句中定义的变量也是局部变量,其作用域只在复合语句范围内。其生存期是从复合语句被执行的时刻到复合语句执行完毕的时刻。 说明 (4) 在复合语句中定义的变量也是局部变量,其作用域只在复合语句范围内。其生存期是从复合语句被执行的时刻到复合语句执行完毕的时刻。 #include <stdio.h> void main ( ) { int a = 2, b = 4; int k, b; k = a + 5; b = a * 5; printf ("k = %d\n", k); printf ("b = %d\n", b); } a = k + 2; main中的局部变量 main中 变量a、b 的作用域 复合语句中的局部变量 复合语句中 变量k、b 的作用域 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 输出k = 7 输出b = 10 错误! 输出b = 4 82
从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件。 生存期 3、全局变量 从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件。 生存期 与程序相同。即从程序开始执行到程序终止的这段时间内,全局变量都有效。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 83
3、全局变量 #include <stdio.h> #include <stdlib.h> #include <time.h> void trans(void); int a[10]; //a作用域开始 void main() { int i; printf("Before:\n"); srand(time(NULL)); for(i=0;i<10;i++) { a[i]=rand()%10 ; printf("%2d",a[i]); } trans(); printf("\nAfter:\n"); void trans(void) { int i,t; for(i=0;i<5;i++) { t=a[i]; a[i]=a[9-i]; a[9-i]=t; } //a作用域结束
全局变量在程序全部执行过程中始终占用存储单元 降低了函数的独立性、通用性、可靠性及可移植性 降低程序清晰性,容易出错 说明 (1) 应尽量少使用全局变量。 全局变量在程序全部执行过程中始终占用存储单元 降低了函数的独立性、通用性、可靠性及可移植性 降低程序清晰性,容易出错 (2) 若外部变量与局部变量同名,则外部变量被屏蔽。要引用全局变量,则必须在变量名前家上两个冒号“::” 注意:局部变量与全局变量同名极易导致程序员犯逻辑错误。 #include <stdio.h> int a = 10; //全局变量 void main ( ) { int a = 100; //局部变量(与全局变量同名) printf ("local a = %d\n", a); printf ("global a = %d\n", ::a); } 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 运行结果: local a = 100 global a = 10 85
① 数据类型:变量所持有的数据的性质(操作属性)。规定了它们的取值范围和可参与的运算 。 6.6.2 动态存储变量与静态存储变量 概述 变量是对程序中数据的存储空间的抽象 变量的属性 ① 数据类型:变量所持有的数据的性质(操作属性)。规定了它们的取值范围和可参与的运算 。 ② 存储类型: 规定了变量占用内存空间的方式,也称为存储方式。 存储器类型:寄存器、静态存储区、动态存储区 auto---------自动型 register-----寄存器型 static -------静态型 extern-------外部型 例如: auto char c1, c2; //c1, c2为自动字符变量 register i; //i为寄存器型变量 static int a, b; //a, b为静态整型变量 extern int x, y; //x, y为外部整型变量 动态存储 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 静态存储 变量定义的完整形式应为: 存储类型说明符 数据类型说明符 变量名1,变量名2,…,变量名n; 86
[auto] 数据类型说明符 变量名1,变量名2,…,变量名n; 定义格式 [auto] 数据类型说明符 变量名1,变量名2,…,变量名n; 说明 存储类型说明符auto可以省略。 自动变量只能在函数内或复合语句中定义,它属于局部变量。 注意:在函数外部定义的没有带存储类型说明符的全局变量是外部变量,属于静态存储类型。 如:int k; //k为外部变量,属静态存储类型 void func ( ) { …… } 自动变量不可定义在函数外 void func ( ) { int i, j, k; …… } 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 auto int k; void func ( ) { …… } 错误! 等价于 auto int i, j, k; 87
1、系统在程序运行期间为其分配固定存储空间的变量称为静态存储变量 2、全局变量就是一种静态存储变量。 2、静态存储变量(static型变量) 1、系统在程序运行期间为其分配固定存储空间的变量称为静态存储变量 2、全局变量就是一种静态存储变量。 系统在程序开始执行时为其分配存储空间,直到程序执行完 毕才释放,因此整个程序执行期都是全局变量的生存期 3、可以使用static关键字将局部变量的存储方式声明为静态存储方式。 在函数调用结束后保留其局部变量的值,即不释放局部变量所占据的存储空间,从而在下一次调用该函数时可能继续使用上一次调用结束时的结果,这样用static关键字将局部声明为静态存储方式。 用auto关键字或者缺省的局部变量为动态局部变量。 1946年,第一台电子计算机问世,应用领域迅速扩大,软硬件飞速发展,程序设计语言相继问世。 程序设计语言:将自然语言形式化为有格式的语言 1。机器语言: 计算机能够认识的语言 计算机的基础是数字电路 机器语言就是数字电路里的电信号 将在《计算机组成》课程中学习 都是二进制文件 一条机器语言成为一条指令 指令是不可分割的最小功能单元 定义:一种CPU的指令系统,由该CPU可识别的0、1序列构成的指令码组成。 特点: 执行效率高 不直观,不易查错,生产效率低。 2。汇编语言 定义:用助记符号描述的指令系统 生产效率高,质量好,执行效率较高; 要经汇编程序汇编成目标程序(机器语言)才能执行,依赖硬件。 (面向机器的语言----依CPU不同而异) 3。高级语言 编程效率高,不必考虑硬件; 执行效率低,要经编译、连接后才能执行。 面向过程的程序设计语言 认为解题过程是数据被加工的过程 程序=数据结构+算法 C语言是面向过程的高级语言 面向对象的程序设计语言 一种结构模拟方法。认为:现实世界由对象组成,对象是数据和方法的封装体;客观世界可以分类,每个对象是类的一个实例。 特点:比面向过程的语言更清晰、易懂,适宜编更大规模程序,是程序设计的主流 程序设计语言基本成分: 。数据成分 。运算成分 。控制成分 。传输成分 程序设计语言定义:用于书写计算机程序的语言。通常指实现高级语言。 语言的基础是一组记号与一组规则。 程序设计语言包括: 语法:记号的组合规则 语义:记号的特定意义 语用:程序与使用者的关系 88
6.6 函数与变量的作用域 例6-19 编程计算1-1/2!+1/3!-1/4!+…+(-1)n-1/n!,精度为0.000001。 程序代码如下: #include<stdio.h> double term(int n); void main() { int i=1,k=1; double s=0.0,t; do { t=term(i); s=s+k/t; i++; k=-k; }while(1.0/t>1e-6); printf("%lf\n",s); } double term(int n) static double t=1.0; /*静态局部变量的声明与初始化*/ t=t*n; return(t);
6.6函数与变量的作用域 说明: 静态局部变量的生存期是从该变量被分配存储空间开始,即定义该变量的函数被调用开始,直到程序结束。但是,静态局部变量的作用域仍然局限于定义它的函数,静态局部变量在上一次调用结束后被保留下来的值,也只能在该函数的下一次调用中使用,而不能被其它函数使用。 可以使用static关键字将全局变量的作用域局限于定义它的文件中,而不能被其它文件访问。
6.6函数与变量的作用域 6.6.3 内部函数与外部函数 内部函数 static 类型符 函数名(形式参数) { 函数体 }
6.6函数与变量的作用域 外部函数 如果一个函数可以被其它文件中的函数调用,则称之为外部函数 定义 通过使用extern关键字,可以在一个文件中将一个函数定义为外部函数,定义格式如下: extern 类型符 函数名(形式参数) { 函数体 } 声明 在需要调用此外部函数的其它文件中,使用extern关键字声明该函数的原型
6.7 程序应用举例 例6-20 验证哥德巴赫猜想,即一个大于等于6的偶数可以表示为两个素数之和,如6=3+3、8=3+5、10=3+7……。 #include <stdio.h> int prime(int n); /*声明函数原型*/ void guess(int n); /*声明函数原型*/ void main() { int n,n1,n2; do /*此循环确保输入的n为大于等于6的偶数*/ printf("Please input an even number(>=6):"); scanf("%d",&n); }while(!(n>=6&&n%2==0)); guess(n); /*调用函数*/ }
6.7 程序应用举例 void guess(int n) //定义函数 { int n1,n2; for(n1=3;n1<n/2;n1+=2) n2=n-n1; if(prime(n1)&& prime(n2)) //调用函数 printf("%d=%d+%d\n",n,n1,n2); }
6.7 程序应用举例 int prime(int n) /*定义函数*/ { int i,flag; flag=1; for(i=2;i<=n/2;i++) if(n%i==0) flag=0; break; } return(flag);
6.7 程序应用举例 例6-21设计一个函数用于删除一个字符串中的指定字符,从而得到一个新的字符串。例如,从字符串“Welcome”中删除“e”后,字符串变为“Wlcom”。 #include <stdio.h> #define N 20 void del_char(char *a,char ch); //声明函数原型 void main() { char a[N]="AscADef"; printf("%s\n",a); del_char(a,'A'); //调用函数 }
6.7 程序应用举例 //定义从字符中删除指定字符的函数 void del_char(char *a,char ch) { char *p; while(*a!='\0') //判断字符串是否结束 { if(ch==*a) //判断是否为指定字符 for(p=a;*p!='\0';p++) //删除指定字符 *p=*(p+1); else a++; } 可否将删除指定字符的del_char函数写成如下形式?
6.7 程序应用举例 void del_char(char *a,char ch) { while(*a!='\0') { if(ch==*a) strcpy(a,a+1); //通过覆盖方法,将指定字符删除 else a++; }
[extern/static] 类型说明符 函数名([形参列表]){ 声明部分 执行部分 } 本章小结 1、函数的分类 标准库函数:由C系统提供的函数; 用户自定义函数:由用户自己定义的函数; 有返回值的函数:向调用者返回函数值,应说明函数类型(即返回值的类型); 无返回值的函数:不返回函数值,说明为空(void)类型; 有参函数:主调函数向被调函数传送数据; 无参函数:主调函数与被调函数间无数据传送; 内部函数:只能在本源文件中使用的函数; 外部函数:可在整个源程序中使用的函数。 2、函数定义的一般形式 [extern/static] 类型说明符 函数名([形参列表]){ 声明部分 执行部分 }
[extern] 类型说明符 函数名([形参列表]); 本章小结 3、函数说明的一般形式 [extern] 类型说明符 函数名([形参列表]); 4、函数调用的一般形式 函数名([实参列表]) 5、函数的参数分为形参和实参两种,形参出现在函数定义中,实参出现在函数调用中,发生函数调用时,将把实参的值传送给形参。 6、函数的值是指函数的返回值,它是在函数中由return语句返回的。 7、函数调用时参数的传递方式有两种:传值调用和传址调用。 8、C语言中,不允许函数嵌套定义,但允许函数的嵌套调用和函数的递归调用。
本章小结 9、可从三个方面对变量分类,即变量的数据类型,变量作用域和变量的存储类型。 10、变量的作用域是指变量在程序中的有效范围,分为局部变量和全局变量。局部变量和形参的作用域是函数内部,全局变量的作用域是整个文件。但可以通过声明一个extern的全局变量扩展全局变量的作用域,也可以通过定义一个static的全局变量限制这种扩展。 11、变量的存储类型是指变量在内存中的存储方式,分为静态存储和动态存储,表示了变量的生存期。动态存储类型的变量有auto型、register型,静态存储类型的变量有extern型、static型。静态的局部变量只能被赋一次初值,并且生存期与全局变量相同,但作用域仍是函数内部。 12、当小作用域内的变量名与大作用域内的变量名同名时,在小作用域内引用这个变量时,遵从最小作用域原则。