




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、编辑课件编辑课件 C语言是一种较现代的程序开发语言。它提供如下一些支持模块化软件开发的功能: (1) C语言用函数组织程序,在C语言程序中,一个程序由一个或多个程序文件组或,每一个程序文件就是一个程序模块,每一个程序模块由一个或多个函数组成。程序设计的任务就是设计一个个函数,并且确定它们之间的调用关系。在设计函数时要使每个函数都具有各自独立的功能和明显的界面。 (2) 通过给变量定义不同的存储类别,控制模块内部及外部的信息交换。 (3) 具有编译预处理功能,为程序的调试、移植提供了方便,也支持了模块化程序设计。编辑课件4.1.1 设计设计C语言程序就是设计函数语言程序就是设计函数 无论涉及的问
2、题是复杂还是简单,规模是大还是小,用C语言设计程序,任务只有一种,就是编写函数,至少也要编写一个main函数。执行C程序也就是执行相应的main函数。即从main函数的第一个前花括号开始,依次执行后面的语句,直到最后的后花括号为止。 模块化程序设计有一个原则:就是每个模块的规模一般不能太大(有人认为要控制在4060行之间),以便于阅读,便于检查其中的错误。在C语言中,减少主函数规模的一项基本措施就是通过调用其它函数来实现主函数需要的一些功能。编辑课件main(void) f1();f2();return 0;操作系统f1() f11();f1() f21();f 2 2( ) ;f11()f2
3、1()f22()main()f1()f2()f22()f21()f11()参数参数参数参数参数返回返回返回返回返回编辑课件 为了定义函数,必须首先了解函数的结构。一个C语言函数的结构形式如下:函数头函数体编辑课件1. 函数头函数类型 函数名(形式参数表列)一个函数的函数头的结构如下:(1)函数类型。指定函数值的类型,即函数返回值的类型。(2)函数名。函数名必须采用合法的用户标识符。(3)圆括号:在函数名后面的一对圆括号是“函数运算符”,表示进行函数运算,函数运算符具有很高的运算优先级别(4)形式参数表。形式参数表由写在一对圆括号(函数运算符)中的一系列参数组成。每一个参数由一个类型符和一个参数
4、名组成。参数名也应当是合法的用户关键字。函数可以没有参数,这时在函数运算符内写一个“void”,也可以空允白。编辑课件2. 函数体 函数体由一些语句组成。主要是三种类型的语句: 声明语句:声明在函数中要使用的变量等程序实体。 用来实现函数的功能的可执行语句:包括若干流程控制 语句和表达式语句,。 return语句。使流程返回到调用处。这里主要介绍return语句的用法。当函数执行到return语句时,将停止本函数的执行,将流程送回到调用处。同时,编译器将函数分为三类进行处理: 纯粹计算型函数,如squt()和sin()。这类函数将返回一个计算结果。 完成一项具体工作,返回完成的成败。如prin
5、tf()执行成功时,返回显示的字节数;失败时,返回一个负整数。 只执行一个过程的函数,不产生返回值,其类型应定义为void。C99规定,对于非void类型的函数,必须使用有返回值的return语句。编辑课件int absolutevalue (int x)return (x=0?x:-x); void spc (int n)int i;for (i=0; in;i+)它printf ( );return;编辑课件 作用域指的是一个程序段中的代码的作用范围,在一个函数中定义的变量只在本函数中有效,在其它函数中不能使用这个变量,因此说,该变量的作用域是它所在的函数(从定义该变量的行开始到函数末尾)
6、。即使在不同的函数中定义了同名的变量,它们数也指的是不同的变量。编辑课件#include int func(int x) x=5;return x+3;int main(void)printf(x=%dn,x);return 0;这个程序企图在main函数中使用func函数中的变量x。编译这个程序,系统将给出如下编译错误: c(13) : error C2065: x : undeclared identifier编辑课件空函数是一个不产生任何有效操作的函数,但它却是一个合法的C函数。例如函数void null (void)就是一个空函数。空函数多使用在模块化程序的设计或测试中。一般首先写好m
7、ain函数,确定需要调用的函数,然后逐步编写这些函数,如果在有一些函数还未编写好时想对已有俩编好的函数进行调试,可以先用空函数(函数名用将来使用的实际函数名,如sort)放在程序中原定的位置上,这样就可以调试程序的其它部分,等以后再逐步补上。编辑课件1. 函数定义函数定义是按照C语言的语法规则引入新的函数,并提供如下信息: 函数的返回值类型(如果有); 参数的个数及类型和名称; 调用函数时要执行的代码; 函数的有效性。编辑课件 函数声明是对所用到的函数的特征进行必要的声明。编译系统以函数声明中给出的信息为依据,对调用表达式进行检测,例如,形参与实参类型是否一致,使用函数返回值的类型是否正确,以
8、保证调用表达式与函数之间的参数正确传递。 声明语句提供的必要信息包括:函数名,函数的类型,函数参数的个数、排列次序以及每个参数的类型。函数声明的一般格式为:类型标识符 函数名(类型标识符形参,类型标识符形参,);编辑课件设有一函数的定义为:double func (double a, int b, char c)/* 函数体*/与之相应的函数声明应为:double func (double x, int y, char z);/* 注意末尾的分号 */编辑课件 一个函数中的函数体,只有在该函数被调用时才会执行。在函数被调用时,将要进行如下两个操作: 将函数调用中的实际参数值传送给函数定义中的形
9、式参数; 将流程从调用处转到被调用的函数的开头,开始执行函数体中的代码。编辑课件 参数是函数调用时进行信息交换的载体。实参是调用函数中的变量,形参是被调函数中的变量。在函数调用过程中实现实参与形参的结合。这称为“虚实结合”。float add( );int main(void)float x=1.5, y=-5.7;printf (%f+%f=%fn, x,y, add(x,y);float add (unsigned int a, unsigned int b) printf(a=%u, b=%un, a,b);return (a+b); 编辑课件 程序进行编译时,并不为形式参数分配存储空间
10、。只有在被调用时,形式参数才临时地占有存储空间,其过程如下:(1)调用开始,系统为形参开辟一个临时存储区,形参与实参各占一个独立的存储空间。(2)然后将各实参之值传递给形参,这时形参就得到了实参的值。这种虚实结合方式称为“值结合”。(3)函数返回时,临时存储区也被撤销。 要特别注意在C程序中实参与形参结合的传值传值调用调用(call by value) 的特点。即函数中对形参变量的操作不会影响到调用函数中的实参变量,即形参值不能传回给实参。编辑课件#include void swap (int x, int y);int main(void)int a=3, b=5;swap (a,b);pr
11、intf (a=%d, b=%dn, a,b);return 0;void swap (int x, int y)int temp;temp=x, x=y, y=temp; /* 交换变量的值交换变量的值 */printf(x=%d,y=%dn,x,y);执行结果:执行结果:x=5,y=3a=3,b=5编辑课件 由前面的学习已经知道,一个函数可以调用另一个函数。C语言还允许一个函数自己调用自己(直接地或间接地调用自己)。于是形成一种特殊的函数结构递归函数,并且,前者称为直接递归函数调用,后者称为间接递归调用函数。编辑课件 递归计算n!的函数rfact( )。通常,n的阶乘可以描述为: n!=1
12、2n但是,也可以描述为: n!= n(n-1)21或者可以写为: n!= n(n-1)!更一般的形式是: 1 (x1)n n!= = n(n-1)!)! (x1)编辑课件这就形成一个递归表达式。这个递归表达式可以用下面的函数实现。long rfact(int n)if (n0)printf(Negative argument to fact !n);exit (-1);else if (n=1)return (1);elsereturn (n*rfact (n-1); /*自己调用自己*/编辑课件rfact(5)5*rfact(4)4*rfact(3)3*rfact(2)2*rfact(1)1
13、2*13*25*244*6120编辑课件 据传古代印度布拉玛庙里僧侣们玩一种称为汉诺塔的游戏,据说游戏结束就标志着世界末日的到来。游戏的装置是一块铜板,上面有三根杆,最左杆自下而上、由大到小顺序串有64个金盘,呈一个塔形(图4.8)。游戏要求把左边杆上的金盘全部移到最右边的杆上,条件是一次只能够动一个盘,并且不允许大盘在小盘上面。容易推出,n个盘从一根杆移到另一根杆需要2n-1次,所以64个盘的移动次数为:264-1=18,446,744,073,709,511,615,这是一个天文数字,即使一台功能很强的现代计算机来解汉诺塔问题,每一微秒可能计算(不印出)一次移动,那么也需要几乎100万年。
14、而如果每秒移动一次,则需近5800亿年。编辑课件下面设计一个模拟僧侣们移动盘子的算法。假定僧侣们要把n个盘子按题中的规定由a杆借助c杆移到b杆。模拟这一过程的算法称为hanoi(n,a,b,c)。那么,很自然的想法是:a b cno1no2no3no4no1no3no4no2编辑课件第一步:先把上面的n-1个盘子设法借助b杆放到c杆,如图4.8中的箭头所示,记做hanoi(n-1, a,c,b)。第二步:把第n个盘子从a杆直接移到b杆,如图4.8中的箭头所示。第三步:把c杆上的n-1个盘子借助a杆移到b杆,如图4.8中的箭头所示,记做hanoi(n-1,c,b,a)。a b cno1no2no
15、3no4no1no3no4no2编辑课件#include void hanoi(int n, char a, char b ,char c);int main(void)int n;printf (*n);printf (*Program for simulating the solution*n);printf (* of the game of tower of Hanoi *n);printf (*n);printf (Please enter the number of disks to be moved:);scanf (%d, &n);编辑课件hanoi (n,a,b,c)
16、;return 0;void hanoi (int n, char a, char b, char c)/*汉诺塔问题*/if (n0)hanoi (n-1, a,c,b);printf ( Move disc %d from pile %c to %cn, n,a,b); (n-1, c,b,a);编辑课件编辑课件h(3,a,b,c)h(2,a,c,b); no3:a-b; h(2,c,b,a);h(2,a,b,c)h(1,a,b,c); no2:a-c; h(1,b,c,a);h(1,a,b,c)h(0,a,c,b); no0:a-b; h(0,c,b,a);h(1,b,c,a)h(0,b
17、,a,c);no1:b-c; h(0,a,c,b);h(1,c,a,b)h(0,c,b,a); no1:c-a; h(0,b,a,c);h(1,a,b,c)h(0,a,c,b); no1:a-b; h(0,c,b,a);h(2,c,b,a)h(1,c,a,b); no2:c-b; h(1,a,b,c);编辑课件 变量是对程序中数据存储的抽象。如前所述,C语言程序中的变量都是有类型的,数据类型是变量的运算属性的抽象,决定了该变量的取值范围和可以施加的运算种类。除此之外,变量还有变量一些属性,例如: 一个变量在程序的哪个范围内是可以使用的变量的可用域; 它什么时候生成以及什么时候被撤消变量的生存期
18、; 它存储在什么哪种类型的存储器中以及用什么机制进行存储变量的存储区。这些都称为变量的存储属性。编辑课件1. 局部变量和全局变量变量的可用域是指一个变量的标识符在程序的哪个域内才是可以被识别的,也称为可见(可见(或可用)的。大体上可以分为两种:全局可用全局变量全局变量与局部可用局局部变量部变量。局部变量是定义在一个程序块(用一对花括号括起的语句块)内的变量。程序块可能是一个函数体(主函数),也可能是一个循环体或是选择结构中的一个分支语句块,也可以是任何一个用花括号扩起的语句块。而全局变量是定义在函数之外的变量。一般说来,定义在什么范围的变量,其作用域就在那个范围,并且在从定义语句开始到这个域结
19、束的范围(域)内被使用,在这个域之外是不可见的。在C语言中,凡是声明在函数内部的变量都是局部变量。编辑课件#include int main(void)/* printf(a1=%d,a); */b的作用域a的作用域 int a=3; printf(a2=%d,a); int b=5; printf(b1=%d,b); /* printf(b2=%d,b); */printf(a3=%d,a);return 0;则运行可以得到如下结果:a2=3b1=5a3=3编辑课件任何一个运行中的程序,在内存中都被分成代码区和数据区两大部分,而数据区又被分为静态存储区、自动存储区和动态分配区等三部分。自动存
20、储区是按栈组织的存储区。除特别声明的外,局部变量通常被存放在栈区。这些变量在进入所在的块时被创建,所在的块结束时被撤销,当所在的块结束后,各变量的值不再保留。并且,变量必须有程序员显式地进行初始化,否则它们的初始值是不确定的。前面例存储区是在程序编译时就分配的存储区,分配在静态存储区的变量在程序开始执行时被创建并自动初始化(数值变量被初始化为0),当程序结束时才被撤销。所以常称静态变量的生存期是永久的。全局变量就是被分配在静态存储区的。下面的例子说明将例4.8中的程序改用全局变量实现后的情形。编辑课件根据程序中实际应用的需要,C语言将可用域和生存期整合成4种存储类型: 局部自动类型,在函数内部
21、用标识符auto或register声明。 静态局部类型,在函数内部,使用static声明。 静态全局类型,在函数外部,使用static声明,也称静态外部变量。 全局类型,不需要标识符声明。在函数外部直接声明即可,通称外部变量。编辑课件编辑课件 可以被多处修改将引起的副作用,又可以使函数基于前一次调用的值的基础上工作。编辑课件#include void increment(void);int main(void)increment ( );increment ( );increment ( );return 0;void increment(void)int x=0; /*auto*/x+;pr
22、intf (%dn,x);运行结果:运行结果:111编辑课件#include void increment (void);int main(void)increment ( );increment ( );increment ( );return 0;void increment (void)static int x=0; /*使用了使用了static说明符说明符 */x+;printf (%dn,x);运行结果:运行结果:1?23编辑课件 在多文件程序中,用static声明外部变量,这样,该外部变量的作用域仅限于所在的文件,而不用static声明的外部变量的作用域为整个程序。例如,某个程序中
23、要用到大量函数,而有几个函数需要共同使用几个全局变量时,可以将这几个函数组织在一个文件中,而将这几个全局变量定义为静态的,以保证它们不会与其他文件中的变量发生名字冲突,保证文件的独立性。编辑课件严格地说,定义与声明是两个不相同的概念。声明的含义更广一些,定义的含义稍窄一些,定义是声明的一种形式,定义具有分配存储的功能,凡是定义都属于声明,称为定义性声明(定义性声明(defining declaration)。另一种声明称为引用性声明引用性声明(referencing declaration),它仅仅是对编译系统提供一些信息,声明并不都是定义。前几章例题程序中定义变量的声明语句,是定义性声明,为
24、方便,一般简称为定义。定义。而函数声明就是引用性声明,它和函数定义的作用是不同的。一般把引用性声明简称为声明声明(狭义的声明明)。对同一作用域中的同一变量只能定义一次,如果对同一变量定义多次,就会出现语法错误。在定义变量时可以用auto,static, register等关键字声明该变量的存储类型。编辑课件对于外部变量(除了静态全局变量外),除了可以定义一次外部变量外,还可以多次进行声明(引用性声明)。(1)通过声明将外部变量的作用域在本文件范围内扩充向前引用编辑课件通常,一个外部变量的作用域是从其定义点到本文件末尾。对于位于定义点之前的函数,可以用extern声明使变量的作用域扩充到需要用到
25、它的函数。(2)利用声明语句将作用域扩大到其他文件建立对象的外部链接假设一个程序由两个以上的文件组成。当一个全局变量定义在文件file1中时,在另外的文件中使用extern声明,可以通知编译系统一个信息:“此变量到外部去找”。或者说在链接时,告诉链接器:“到别的文件中找这个变量的定义”。编辑课件 (4) 全局变量的副作用 前面已提到,如果没有外部变量,函数只能通过参数与外界发生数据联系,有了外部变量以后,增加了一条与外界传递数据的渠道。这种方法有利有弊。外部变量作为公共信息的一种载体,虽然给程序设计带来一些方便,但也会产生一些副作用 编辑课件 C语言除了可以为程序开辟栈区、堆区、静态区外,还可
26、以开辟一个只读区。既然只读区是内存的一个区,所以数据是以变量的形式存储的,但它又是只读的,即不可修改的。所以这也就是把变量定义为只读变量。定义只读变量的方法是在声明变量时使用修饰符const。格式为:const 数据类型 变量1=初始表达式1,变量2=初始表达式2,编辑课件4.3.1 分别编译分别编译 C语言是一种支持模块化程序设计的语言,它允许将一个大型程序分成多个程序文件分别进行编译。这样的好处在于 当程序的一个局部有错误或对局部进行了修改时,可以只重新编译该局部,不需要将整个程序都重新编译。 某些经过考验的函数的目标代码可以添加为的库函数,供其他程序中使用。编辑课件 多文件程序的编译、链
27、接过程是比较麻烦的。为了方便用户进行多文件程序的编译、链接,各种程序开发软件都提供了用项目(project)管理多文件程序的编译和链接过程。其使用方法因开发工具而异,请参考有关手册。编辑课件用户显式地保证程序一致性的基本方法是保持声明的一致性。保持声明一致性的简单办法是提供一个头文件,让头文件中的信息作为各模块之间的接口信息,有利于提供可重用的模块。使用头文件将把程序分为程序头和程序体两部分。好的头文件应包含如下一些内容: 类型定义,如定义一个枚举类型enum color RED,BLUE,GREEN,YELLOW; 函数声明,如extern int strlen const char*; 嵌
28、入函数声明,如inline char get() return *p+; 数据声明,如extern int a; 常量定义,如const float pi=3.141593; 包含指令,如#include 编辑课件 宏定义,如#define case break; case 注释好的头文件不能包含以下内容: 一般函数定义 数据定义,如int a; 常量聚集定义,如 const tbl=/* */;用户头文件是由用户自己定义的头文件。系统将用双引号方式进行搜索。 程序员可以用它们建立各文件之间的信息窗口。应当注意,修改了头文件时,所有涉及该头文件的程序都应重新编译, 所以在编制头文件时应尽量考虑
29、周全;另外,当使用很多头文件时,常常有重复嵌入的情形发生, 在这种情形下,应防止标识符重复定义的错误。为避免这些错误, 应使用条件编译来测试有无重复定义。编辑课件 编译预处理是以“#”开头的一些命令,它通知编译系统:在进行正式编译前应当先进行一些前期工作(即编译预处理)。目前,C语言的编译预处理功能主要有如下一些:(1)文件包含,使用命令:#include。(2)宏定义,使用命令:#define、#undef。(3)条件编译,使用命令:#if、#ifdef、#ifndef、#else、#endif、#elif、defind。(4)提供行号信息,使用命令:#line。(5)编译杂注,使用命令:#
30、progma。(6)错误信息,使用命令:#error。 在这些编译预处理中,应用最多的就是对宏的处理。它允许程序员使用define定义并应用宏名字书写C语言程序,同时也指示编译器在正式编译前通过宏替换,使程序能按照C语言的语法进行编译。编辑课件 define命令最简单的应用是将一个字符串定义为一个宏名,格式为: define 宏名宏名 字符串字符串 编译预处理时,预处理程序将把程序文件中在该宏定义之后的所有宏名,用#define命令中定义的字符串(称为宏体)替换,这个过程称为宏替换。符号常数的定义就是这种宏定义的一种应用。例如#define PI 3.14159265#define RADIU
31、S 2.0使用宏定义的好处是:(1) 提高了程序的可读性。如果人们看到以下语句return (2.0* 3.1415926536* 2.0);编辑课件和return (3.1415926536* 2.0* 2.0);是否能很快地看出它们在计算什么呢?显然不能。如果写成下面的形式return (2.0* PI* RADIUS);和return (PI *RADIUS* RADIUS);任何人一眼都可以看出:这是在计算圆周长和圆面积。使用宏定义可以提高可理解性。(2) 易修改性好。如要将RADIUS的值由2.0修改为3.0,只要在define命令中修改一处便可。而在不使用宏定义的文件中,要将3处的
32、2.0修改为3.0,而且很可能也错把circum函数中的第一个返回语句也修改成return (3.0*3.1415926536*3.0);编辑课件(3)宏定义可以给程序设计带来许多方便。如熟悉PASCAL的读者,完全可以用自己已习惯的风格来写程序。#define BEGIN #define END #define AND &#define OR |#define NOT !void func(void)BEGINif(a AND b)6) else if(c OR d)3) else if(NOT(e=9)END如果没有前面的宏定义,后面的程序是不符合C语言语法的。只有经过编译预处理,
33、程序部分符合C语言的语法。编辑课件(1)在#define命令中,宏名字与字符串(宏体)之间用一个或多个空格分隔。(2)宏名编辑课件#define A NAME SMISS则实际进行的宏定义是A为宏名字,宏体是“NAME SMISS”。 C程序员一般都习惯用大写字母定义宏名字。这样的表示方法使宏名与变量名有明显的区别,以避免混淆。此外有助于快速识别要发生宏替换的位置,提高程序的可读性。 不能进行宏名字的重定义。(3)定义一个宏名字以后,就可以在后面使用这个宏名字了,包括在后面的宏定义中使用。例如求圆的周长和面积的程序可以改写为#include 编辑课件#define PI3.1415926#de
34、fine R1.0#define CIRCUM2.0*PI*R /* 使用了前面定义的R和PI */#define AREAPI*R*R int main(void) printf(“The circum is %f and area is %fn”,CIRCUM,AREA); 这种宏定义称为嵌套宏定义。运行这个程序的结果为:The circum is 6.283185 and area is 3.141593下面是另外一种形式的宏定义:#include #define PI 3.14159265#define RADIUS 1.0#define CIRCUM return(2.0*PI* R
35、ADIUS); /* 最后的分号是return语句的一部分 */编辑课件#define AREA return(PI* RADIUS* RADIUS);double circum( )CIRCUMdouble area( )AREAint main(void) printf(The circum is %f and area is %fn,circum(),area();(4)不能进行的宏替换: 不可以替换作为用户标识符中的成分。例如,在例4.23中,不可以用“R”替换“CIRCUM”中的“R”。 不能替换字符串常量中的成分。编辑课件#include #define PI3.1415926#define R1.0#define CIRCUM2.0*PI*R#define AREAPI*R*R int main(void) printf(“The CI
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 镇江环氧坡道地坪施工方案
- 安徽中考初三数学试卷
- 铜板幕墙施工方案
- 大理石电视墙金属施工方案
- 五指山绿化排水板施工方案
- 嘉定区空调清洗施工方案
- 2025北京西城八年级(上)期末生物(教师版)
- 小区水电维修服务施工方案
- 危化企业安全文化建设方案
- 推动医务人员队伍建设的策略及实施路径
- 中药玫瑰花培训
- 广东省佛山市(2024年-2025年小学六年级语文)统编版小升初真题((上下)学期)试卷及答案
- 2025年吉林通化梅河新区(梅河口市)专项引进高层次教育人才40人高频重点提升(共500题)附带答案详解
- 湖北日报传媒集团(湖北日报社)招聘笔试冲刺题2025
- 危险性较大工程培训课件
- 建筑施工安全员述职
- 开封市第二届职业技能大赛无人机装调检修项目技术文件(国赛项目)
- 2024解析:第九章固体压强-基础练(解析版)
- 【MOOC】人工智能与信息社会-北京大学 中国大学慕课MOOC答案
- 移动式升降平台安全指导手册
- 人美版六年级美术教案下册全册
评论
0/150
提交评论