《编程C语言.pdf》由会员分享,可在线阅读,更多相关《编程C语言.pdf(240页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、C程序设计语言北航软件所 晏海华作业及参考书?教师:晏海华(软件所,逸夫馆505)?参考书:?(1)C程序设计语言,B.W.Kernighan,D.M.Ritchie,清华大学出版社影印;机械工业出版社,徐宝文等译;?(2)C语言教程,孙玉芳,孟庆昌编著;?(3)C程序设计语言,谭浩强,清华大学出版社;?作业:from C Programming Language-P13.1-4;P20 1-8,1-9,1-10;P24 1-13;P31 1-18;P34 1-20,1-22,1-23;P46 2-3;P49 2-6,2-8;P58 3-1;P60 3-2;P63 3-3;P64 3-5,3-
2、6;P71 4-1;P73 4-2;P79 4-4,4-6,4-10;P83 4-11;P88 4-13;P97 5-1,5-2;P107 5-3,5-5;P110 5-7;P118 5-13;P121 5-14;P126 5-19;P143 6-2,6-3共计34题,请选做其中的20道题,作业占总成绩的10分。前言前言前言C语言的产生、发展和它与UNIX系统的关系C语言的产生与UNIX操作系统是密不可分的:?UNIX由Bell Lab的K.Thompson和D.M.Ritchie最先在1969年开发的O.S.(它的前身是MIT和AE开发的Multies)。?1970年,V1,V2版在PDP-
3、7机上用汇编语言实现。?1971年V3 PDP11/23;1972年V4 PDP11/45。?1972年,D.M.Ritchie开发出新语言C。(C?B?BCPL?CPL单数据型语言)?1973年,Ritchie和Thompson用C改写了UNIX核心(90%)即V5前言C语言的发展经历三个阶段:第一阶段:78年以前,C称为UNIX C,即C被看成UNIX的一部分。第二阶段:78年D.Ritchie的C程序设计语言出版到88年ANSI C(标准C)标准出现。此C又称为K&R C。第三阶段:88年ANSI C标准(89年3月批准)。CPL-?BCPL-?B-?C-?C+1968 C.Strach
4、ey 1969 M.Richards 1970 K.Thompson 1972 D.M.Ritchie 1988 B.Stroustrup前言C语言特别适用于编写:?操作系统?编译程序?数据库管理系统?网络软件?图形软件?其它系统软件及软件工具?应用软件第一章C语言导论第一章C语言导论?C语言特点?C语言的一般介绍?C程序的编辑、编译和运行第一章C语言导论11 C语言特点1)表达能力强2)有先进的数据结构和控制结构,支持结构化、模块化程序设计,为大型软件开发提供有力工具。?数据类型第一章C语言导论 数据类型基本类型枚举类型enum构造类型指针类型用户定义类型 typdef整型 int shor
5、t long unsigned 实型 float double字符型char数 组结构 struct 联合union第一章C语言导论?控制流设施复合语句 语句序列 分程序 局部说明;语句序列 条件语句if if else循环语句while,do_while,for开关语句switch转向语句goto,continue,break,return?存贮类auto局部变量(自动变量)static静态存贮分配变量extern外部全程变量register寄存器变量?分块编译功能第一章C语言导论3)可通过预处理程序,进行宏定义,处理包含文件和条件编译4)语言简洁,键入量少(仅有五个基本类型和32个关键字)
6、如,=,+=,*=,+,-5)效率高C编写的程序仅比用汇编语言编写的程序相差20%6)可移植性好?C编译规模较小,用C记述的75%80%的代码相同。此外,C编译几乎在所有的系统上都有。?C语言本身提供某些设施,使C程序移植容易。第一章C语言导论C语言缺点?算符太多,优先级多,不便记忆。?相对来说,C语言类型转换随便,安全性较差(如指针)。?可读性比PASCAL语言差。第一章C语言导论12 C语言的一般介绍121词汇表数字:0,1,9英文字母:a,b,z,A,B,Z(一般用大、小写表示不同字符)连字符:_ 作用同英文字母标识符:以字母(或_)开头的字母(_)数字串。一般不要太长,依赖于实现。运算
7、符和分界符:+,-,*,/,%,.,&,&,|,=,=,!=,=,(,),,,?,:,“,#,第一章C语言导论1.2.2关键字int autogotoiffloatstaticreturnelsecharexternbreakwhileshortregistercontinueforlongdounsignedswitchdoublecasestructdefaultunionvoidenumtypedefsizeofconstsigneddefine,undef,include,ifdef,ifndef,endif,及line,虽不是关键字,但是最好把它们看作关键字,它们主要用于C预处理程序
8、中。第一章C语言导论1.2.3 C语言程序结构C程序由一系列外部说明和函数组成。一个C程序可由一个或多个函数(它们之间不能嵌套)组成,但其中必有一个(也只能有一个)命名为main(主函数),其它函数可由用户任取名字。程序运行时必需从main开始,但main函数在程序中的前后位置没有关系。组成C程序的各个函数可在一个源文件上,也可以分放在多个文件上(函数不能跨文件),每个源文件可单独编译。C源文件必须以.C作后缀(.h为C程序的头文件)。第一章C语言导论例1-1/*file:hello.c*/main()printf(“hello,worldn”);说明:1./*/为注释,不可嵌套2.main(
9、)为主函数定义3.printf为标准I/O库中格式化输出函数4.n为C语言转义字符,常用的有:n换行t制表b退格r回车f换页本身单引号ddd位模式“双引号5.分号(;)为语句的结束符(这与PASCAL语言不同,在PASCAL中分号为语句的分隔符)第一章C语言导论例1-2main()/*simple.c*/int a,b,c,sum;a=1;b=2;scanf(“%d”,&c);/*注意要用地址*/sum=a+b+c;printf(“Sum=%dn”,sum);说明:在scanf和printf中,%号开始的为格式转换字符,用来控制输入/出格式,常用的有:scanf printf%d%d十进制整数
10、%f%f十进制浮点数%c%c单个字符%s%s字符串%o八进制整数%x十六进制整数%本身同时,在%d,%f前还可以加数字,如%4d,%6.2f第一章C语言导论1.3 C程序的编辑、编译和运行编辑编译/连接运行有错?结果正确?有有编译错语法错运行错语义错使用编辑器如:vi(UNIX),edit(DOS)编译=.o 或.obj连接.o(.obj)=.exe第一章C语言导论1)UNIX编译环境Cc-o执行文件名 c 文件名?o:指定执行文件名,缺省为a.out?c:产生.o文件如:s1.c,s2.c s3.c组成一个C程序,则有:cc c s1.ccc c s2.c cc o s s1.o s2.o
11、s3.c2)DOS及Windows环境目前,在DOS和WINDOWS环境下的C编译系统已将C程序的编辑、编绎、连接、调试和运行集成到一起,如VC,BC等开发环境。3)输入/输出重定向?,输出重定向,将标准输出重定向到指定文件,如,C prog outfile?prog prog1|prog2第二章 数据、运算符、表达式第二章 数据、运算符、表达式21标识符和变量211标识符?标识符在C语言中可作为变量名、常量名、函数名、参数名、类型名、枚举名和标号等。?通常定义名用大写,其它名字用小写。?以连字符(_)开始的名字用户最好不用(通常系统取名以_开始)。好的标识符可使程序易读,也可以减少写程序或修
12、改程序时由于疏忽而产生的错误。第二章 数据、运算符、表达式212变量与变量说明在C中,所有变量必须先说明(定义)后使用。说明方式:存贮类存贮类 类型 变量(列)表;类型 变量(列)表;例:int lower,upper,step;char c,line100;extern double x;const double PI=3.1415926;const char msg =“Warning”;第二章 数据、运算符、表达式2.2常量221文字常量(literal)和常量定义例:line 66ci=3.141592*dia;si!=0;又如:#define PAGESIZE 66#define P
13、I 3.141592#define ENDSTRING 0则上面可以写成:line=A&c=0&si=9;i+)n=10*n+si 0;return(n);main()int n;char st100;scanf(“%s”,st);n=atoi(st);printf(“%dn”,n);第二章 数据、运算符、表达式?C语言类型转换通常是自动的-隐式类型转换1)字符与整数可以用整数的地方就可以用字符。而整数转换成字符时,超出8位就将高位丢掉。2)浮点数与整数3)无符号整数一般整数(int)和无符号整数(unsigned)混合使用,则简单整数转换成无符号整数。浮点整数截去小数部分第二章 数据、运算符
14、、表达式4)算术转换如果一个运算符,有不同类型的运算对象,那么“较低”类型会自动转换成“较高”类型。doublefloatlongunsignintshort,char此外,赋值号右边表达式的类型会自动转换为赋值号左边变量类型。第二章 数据、运算符、表达式?强制类型转换(cast)-显式类型转换()如:x=sqrt(double)n);第二章 数据、运算符、表达式2.5表达式和运算符C语言中一个表达式后跟一个分号可构成一条语句,如:;称为表达式语句在C语言中,分号是语句的结束符,而在PASCAL语言中分号是语句的分隔符。在其它语言里常见的赋值语句E1=E2;在C语言中称为赋值表达式语句。在C中
15、,a=b=c=0;是合法的赋值表达式语句。第二章 数据、运算符、表达式251表达式表达式:=即,相当于|:=变量名、常量名等|文字常量|()|(,*)|第二章 数据、运算符、表达式:=被赋变量|数组元素|.结构或联合成员|-同上|()|*指针变量,取指针所指对象作为被赋变量从上可以看出,一般只有变量、数组元素、结构成员才能做为左值。第二章 数据、运算符、表达式1.单目表达式由单目运算符构成的表达式,格式为::=*表达式取指针所指对象内容|&取变量地址|-单目减|+单目加|按位反|!逻辑反|()强制类型转换|sizeof 数据类型的大小,以字节计|sizeof()同上|+|-前置增/减量|+|-
16、后置增/减量第二章 数据、运算符、表达式例1指针和地址int x,y;int*px;x=10;px=&x;y=*px;(间接取,相当于y=x)指针变量用来存放所指对象的地址。注意:-只有才能取地址,即变量或数组元素能取地址。所以,&(3),&(x+5)等非法。-只有才可对它进行+或运算。X:10Y:1001000PX:第二章 数据、运算符、表达式例2前置和后置增(减)量n=5;n=5;x=+n;x=n+;结果:结果:前置运算是先进行增减量,再取其值。后置运算是先取其值,再进行增减量运算。n:6,x:6?x:5,n:6第二章 数据、运算符、表达式例3给出下列程序的输出结果#include mai
17、n()int a,b,c;a=b=c=0;a=+b+c;printf(“%d%d%dn”,a,b,c);a=b+c+;printf(“%d%d%dn”,a,b,c);a=+b+c+;printf(“%d%d%dn”,a,b,c);a=b-+-c;printf(“%d%d%dn”,a,b,c);a=+c+c;printf(“%d%d%dn”,a,b,c);/*2 1 1*/*2 2 2*/*5 3 3*/*5 2 2*/*不确定,取决于机器实现不确定,取决于机器实现*/第二章 数据、运算符、表达式2双目表达式:=:=*|/|%|+|-|=|,=,(p+1 n)&(0 右移,低位移出,对int为算
18、术右移(高位补符号位),对unsigned为逻辑右移(高位补0)。左移,高位移出,低位补0。/注意整除有别于浮点数相除。%整数求余。,逗号表达式,如e1,e2顺序求e1和e2,以e2值作为整个表达式结果的值。如,a=(t=3,t+2);结果为5。(逗号通常还用在变量说明以及函数参数表中,用作分隔符。)第二章 数据、运算符、表达式3三目表达式(条件表达式):=?:先计算表达式1,若其值为非零,则结果是表达式2的值,否则就是表达式3的值。例:if(a b)z=a;elsez=b;等价于:z=(a b)?a:b;第二章 数据、运算符、表达式4赋值表达式:=:=|+=|-=|/=|%=|*=|=|b_
19、back+=2编译程序产生效率高其用一个运算符完成其它语言中须多个运算符才能完成的功能。如:x+=n只有一个运算符,而x=x+n则有两个运算符。注意:y*=n+1;?y=y*(n+1),而不是y=y*n+1第二章 数据、运算符、表达式252 运算符的优先级和结合顺序优先级 运算符 结合律 初等量运算符 初等量运算符 1().-单目运算符 2-!+-&*(类型名)sizeof 右结合 单目运算符 双目运算符 3*/%算术运算符 4+-5 移位运算符 6 =关系运算符 7=!=8&按位运算符 9 10|11&逻辑运算符 12|三目运算符 13?:右结合 赋值运算符 14*=/=%=+=-=&=|=
20、右结合 逗号运算符 15,第三章 语句与控制流第三章 语句与控制流31概述概述C语言语句分成简单语句和构造语句两类。第三章 语句与控制流简单语句1)表达式语句赋值表达式语句,如:*x+=y*=z+3;其它表达式语句,如:+x;-y;函数调用语句等。2)转移语句goto标号;break;间断语句continue;继续语句return;return(表达式);3)空语句;第三章 语句与控制流构造语句1)复合语句(分程序)*注意:后没有分号(;),这与单个语句不同。2)条件语句if语句,if_else语句3)循环语句for语句while语句do_while语句4)开关语句switch语句(包括cas
21、e语句)第三章 语句与控制流32条件语句if(表达式)语句if(表达式)语句1else语句2表达式语句FT表达式语句1FT语句2第三章 语句与控制流注意:在if嵌套中,省略else会产生二义性。如:if(n 0)if(a b)z=a;elsez=b;即else与前面最接近的不带else的if相对应。若要使上面的else与第一个if相匹配,可使用。如:if(n 0)if(a b)z=a;else z=b;第三章 语句与控制流若if语句的else部分嵌套if语句,如:if()else if()else这是实现多路分支的最一般方法。第三章 语句与控制流例3-1:#include main()int
22、a,b;char ch;scanf(“%d%d”,&a,&b);ch=getchar();if(ch=y)int x;x=a;a=b;b=x;printf(“a=%d b=%dn”,a,b);else printf(“no swap!n”);第三章 语句与控制流3.3 while语句while(表达式)语句表达式语句FT计算表达式语句结束第三章 语句与控制流例3-2从键盘读入字符并输出#define EOF 1main()int c;while(c=getchar()!=EOF)putchar(c);第三章 语句与控制流例3-3有一阶梯,每跨2阶余1阶;每跨3阶余2阶;每跨5阶余4阶;每跨6阶
23、余5阶;每跨7阶正好不余,求共有几阶?main()int x=3;while(x%3!=2)x+=2;while(x%5!=4)x+=6;while(x%6!=5)x+=30;while(x%7!=0)x+=30;printf(“x=%dn”,x);第三章 语句与控制流3.4 for语句for(表达式1;表达式2;表达式3)语句其等价于:表达式1;while(表达式2)语句;表达式3;表达式2语句FT计算表达式2语句结束计算表达式1计算表达式3第三章 语句与控制流for特别适合于循环次数固定或有固定步长的循环,如下一个循环十次的循环:for(i=0;i=0&si=9;i+)n=10*n+si
24、0;return(sign*n);第三章 语句与控制流例3-5 将字符串颠倒void reverse(char s)int c,i,j;for(i=0,j=strlen(s)-1;i j;i+,j-)c=si;si=sj;sj=c;int strlen(char s)int i=0;while(si!=0)+i;return(i);第三章 语句与控制流注意注意:从语法上讲,表达式中任一个都允许省略,但分号不能省。:从语法上讲,表达式中任一个都允许省略,但分号不能省。如:for(;(c=getchar()!=EOF;)语句s;for(;)语句s;当表达式2不出现时,则认为条件为真,循环永远下去(
25、无穷循环),退出它只能用break或return语句。所以,一个while(A)B;等价于一个for(;A;)B;第三章 语句与控制流3.5 do_while语句3.5 do_while语句do 语句while(表达式);作用类似于while,但do_while是否终止,其判定条件是在循环体之后,即它总是先执行一次循环体,再判断表达式的值是否为真。表达式语句FT计算表达式语句结束第三章 语句与控制流总的说来,while(for)循环是在顶上测试循环终止条件,而do_while是在每次通过循环体之后,在底部进行测试,所以循环体至少要进行一次。注意注意:do_while与与Pascal语言中的语言
26、中的Repeatuntill不同不同-其布尔表达式为其布尔表达式为False时继续循环,若为时继续循环,若为True时,终止循环。时,终止循环。第三章 语句与控制流例3-6将一个整型数转换成字符串。void itoa(int n,char s)int i,sign;if(sign=n)0);if(sign 0)si+=-;si=0;reverse(s);一般来说,不管do_while中是单个语句还是复合语句,都用一对将其括起来,以使不致把while部分误认为是while循环的开始。第三章 语句与控制流三种循环主要的用途:?for通常用于固定步长的循环?while通常用于循环条件在头部判断的循环
27、?do_while通常用于至少循环一次的循环第三章 语句与控制流36开关开关(switch)语句语句 另一种表达多路支方式另一种表达多路支方式基本形式:switch(表达式)语句语句的表达形式为:case常量表达式:语句或空default:语句第三章 语句与控制流switch语句的常见形式为:swich(表达式)case常量表达式1:语句1或空;case常量表达式2:语句2或空;case常量表达式n:语句n或空;default:语句n+1或空;其语义动作为:1)先计算表达式的值;2)该值与每一个case后的常量进行比较;3)若匹配,则控制就转向该常量后的语句;4)若不匹配,若有default,
28、则转向default后的语句,否则什么也不做;S1S2SnSn+1EC1C2Cndefault第三章 语句与控制流注意注意:1)常量表达式必须是整型;2)在同一个switch中不应出现两个具有同样的情况常量;3)default语句如果有,只允许出现一次,default可出现在switch中的任何位置,通常放在最后;4)case和default本身不改变控制流(这与pascal中的case语句不同),中断离开switch要用break;5)case后的语句可以是单个语句,也可以是复合语句(但不带开头和结尾的花括号)C的switch语句与Pascal中case另一个不同是:C有default语句。
29、第三章 语句与控制流例 打印学生成绩片断char score;switch(score)case E:printf(“no passn”);break;case D:printf(“passn”);break;case C:printf(“bettern”);break;case B:printf(“rightn”);break;case A:printf(“all rightn”);break;第三章 语句与控制流3.7间断、继续、转移和返回语句(无条件转移语句)间断、继续、转移和返回语句(无条件转移语句)?break:迫使程序从包含它的最内层循环体或开关语句中跳出(循环只能跳出一层)。?c
30、ontinue:迫使程序从包含它的最内层循环体立即执行下一次循环(不管现在程序执行到何处)。?goto标号:使控制转移到标号处。?标号作用范围是当前函数;?只允许从里层转向外层,而不允许反过来由外层转向里层;?return:把控制返回调用程序。它有两种形式:(1)return;或(2)return(表达式);注意:(1)main不需要也不要return语句。(2)如函数无return语句,则程序执行完该函数最后一条语句后,便自动返回调用程序。第三章 语句与控制流国际上对goto语句作出结论:从理论上讲,goto语句决非是必要的语言成份,取消它同样可写出各种各样的程序,但有时不得不用goto语句
31、,如下程序段。应该是有选择地使用goto,以达到程序结构清晰、易读、易维护的目的。int i,j,k,x;float y;for(i=)for(j=)for(k=)scanf(“%d%f”,&x,&y);if(x 0&y 0)while(-n=0)if(linen!=&linen!=n&linen!=t)break;linen+1=0;printf(“%sn”,line);第三章 语句与控制流int getline(char s,int lim)int c,i;for(i=0;i=0&c=9)continue;count+;printf(“non digital character:%dn”,
32、count);第三章 语句与控制流本章综合练习:本章综合练习:例3-9:给出下面程序的输出结果。#include char input =“SSSWILTECH1111W1WALLMP1”;main()int i,c;for(i=2;(c=inputi)!=0;i+)switch(c)case a:putchar(i);continue;case 1:break;case 1:while(c=input+i)!=1&c!=0);case 9:putchar(S);case E:case L:continue;default:putchar(c);continue;putchar();putch
33、ar(n);结果:SWITCH SWAMP第三章 语句与控制流2给出下面程序段的输出结果。for(putchar(1);putchar(2);putchar(3)putchar(4);continue;putchar(5);结果:1243243.第三章 语句与控制流3简化下面程序段,去掉其中的无条件转移语句。while(A)if(B)contine;C;结果:while(A)if(!B)C;第四章 函数和程序结构第四章 函数和程序结构41概述使用函数的目的:(1)功能分解的需要;(2)代码重用;常用的标准库函数有:?标准I/O库函数#include (getchar,putchar)?标准数学
34、函数#include (sin,cos,sqrt)BCDA第四章 函数和程序结构4.2函数函数421函数结构(函数的定义和调用)在ANSI C标准中,函数定义形式为:类型 函数名(参数说明)局部变量定义或说明语句第四章 函数和程序结构?函数名一般是标识符,一个程序只有一个main函数,其它函数名可随意取,当然最好是有助于记忆的名字。?在ANSI C标准中,函数返回值不允许省略,即使是返回整型值(int),当函数无返回值时,应说明为void类型。?局部变量定义或说明可有可无。在C语言中,函数在概念上相当于Pascal中的过程(procedure)和函数(function)两种情况,无返回值时就是
35、过程。实际上,C的函数往往兼存函数和过程双重功能。注意注意:在C语言中,函数定义不允许嵌套,即在一个函数体内不能包含有其它函数的定义,这与Pascal语言不同。第四章 函数和程序结构函数调用形式:函数名(实参表)其中实参个数、类型、排列次序应和形参定义时一致。(老版本的C编译器往往不做这方面的检查)函数通过return语句将值返回给调用函数。第四章 函数和程序结构例4-1:计算x的幂。#include int power(int x,int n);main()int i;for(i=0;i=10;+i)printf(“%d%d%dn”,i,power(2,i),power(-3,i);int
36、power(int x,int n)int i,p;p=1;for(i=1;i 0;-n)p*=x;return(p);第四章 函数和程序结构例4-2 在输入中查找给定串。#define MAXLINE 1000int index(char s,char t);int getline(char line,int ml);main()char lineMAXLINE;while(getline(line,MAXLINE)0)if(index(line,“the”)=0)printf(“%s”,line);第四章 函数和程序结构int index(char s,char t)int i,j,k;f
37、or(i=0;si!=0;i+)for(j=i,k=0;tk!=0&sj=tk;j+,k+);if(tk=0)return(i);return(-1);第四章 函数和程序结构输入:Now is the timefor all goodmen to come to the aidof their party输出:this is the timemen to come to the aidof their party第四章 函数和程序结构422函数(返回值)类型说明即函数定义时,函数返回值类型的说明,在ANSI C标准中,函数类型必须显式说明,当函数无返回值时(即“过程”),则函数类型可说明成vo
38、id。在C语言中,函数返回值的类型可以是基本类型或指向其它类型的指针(也可返回结构或联合类型),但不能返回数组及函数。第四章 函数和程序结构例4-3 将一个浮点字符串转换成相应浮点数。double atof(char s)double val,power;int i,sign;for(i=0;si=|si=n|si=t;i+);sign=1;if(si=+|si=-)sign=(si+=+)?1:-1;for(val=0;si=0&si=0&si 0)printf(“t%.2fn”,sum+=atof(line);注意注意:函数原型说明的类型、参数类型、个数及次序必须与函数定义时一致,否则会产
39、生错误。:函数原型说明的类型、参数类型、个数及次序必须与函数定义时一致,否则会产生错误。函数原型第四章 函数和程序结构424参数?调用函数时,实参的类型、排列次序和个数应与函数定义时形参相对应(在ANSI C标准中,若不一致,将出现编译错误),但float将自动转换为double类型,char和short将转换为int类型。数组名将转换为指向该数组第一个元素的指针值(数组的首地址)。?C函数的参数传递全部采用传值,它没有Pascal中的变量形参,所以只能传递实参变量的值,而不能隐含传地址。-传值调用实际上重新拷贝了一个副本给形参,因此,我们可以把函数形参看作是局部变量。传值的好处是传值调用不会
40、改变调用函数实参变量的内容,因此,可避免不必要的副作用。?如何改变实参变量内容?第四章 函数和程序结构有时,确实需要改变实参变量的内容,如何实现?首先,我们来看一个例子,void swap(int x,int y)int temp;temp=x;x=y;y=temp;main()int a=2,b=3;swap(a,b);请问请问a和和b是否交换是否交换?不能!不能!a=2b=3调用swap(a,b)x=2y=3调用swap后x=3y=2第四章 函数和程序结构若要交换实参变量a和b,正确的做法应为:void swap(int*px,int*py)int temp;temp=*px;间接取*px
41、=*py;间接取,间接存*py=temp;间接存main()int a=2,b=3;swap(&a,&b);ab&apx&bpy第四章 函数和程序结构提示提示:这也是为什么用scanf读int,char,double类型数据时要取变量地址。因为需要改变变量内容。因此,在一定要改变实参变量内容时,应把函数的形参显式地说明为指向实参变量(类型)的指针,相应地调用时应该用变量的地址值作为参数。尽管C的函数和函数返回值一般应为基本类型,但它们却可以是指向任何类型(包括复杂的结构类型,甚至其它函数)的指针,这就大大扩充了C的功能和应用范围。第四章 函数和程序结构425递归一个函数直接或间接调用自已称为递
42、归。C语言允许函数递归调用,如下面例子:(1)x n=1n=0 x*x n-1n 0(2)n!=1n=0n*(n-1)!n 0第四章 函数和程序结构例4-5:n!#include int fact(int n);main()printf(“3!=%d,5!=%dn”,fact(3),fact(5);int fact(int n)if(n 0)hanoi(n-1,x,z,y);printf(“MOVE%d:%c?%cn”,n,x,z);hanoi(n-1,y,x,z);main()int n;printf(“Please input the number of hanoi tower:”);sc
43、anf(“%d”,&n);hanoi(n,A,B,C);ABC第四章 函数和程序结构43变量说明和初始化?变量说明和定义,在C语言中有不同含义,(Pascal语言中变量声明即变量定义)。?变量定义-不仅要说明变量类型和特性,而且在编译时要分配存贮区域(在此之前,我们所遇到的都是变量定义)。?变量说明-仅仅说明变量的类型和特征,并不需要分配存贮单元。实际上,只有外部(全程)变量有时需要对它们进行说明。注:函数定义与函数说明与此类似。第四章 函数和程序结构431变量的存贮类型变量的存贮类型变量的定义或变量说明的形式如下:存贮类存贮类 类型 说明符类型 说明符存贮类:?auto函数内部的局部变量(a
44、uto可省略不写)?static静态存贮分配,又分为内部和外部静态?extern全程变量(用于外部变量说明)?register 参数和自动变量分配在硬件寄存器中第四章 函数和程序结构1)自动变量 局部变量,在一个函数开头或段开头处说明的变量?作用域为定义它的函数(局部变量)。?编译程序不对自动变量给予隐含的初值,故其初值不确定。因此,每次使用前,必须明确地置初值。?形参是自动变量,作用域仅限于相应函数内。?在分程序开头说明的变量作用域为定义它的分程序。?自动变量随函数的引用而存在和消失,由一次调用到下一次调用之间不保持值。第四章 函数和程序结构2)外部变量?在函数外部定义的变量即为外部变量,它
45、的作用域是整个程序(全程变量)。?C程序可以分别放在几个文件上,每个文件可作为一个编译单位分别编译。外部变量只需在某个文件上定义一次,其它文件若要引用此变量时,应用extern加以说明。(外部变量定义时不必加extern关键字。?在同一文件中,若前面的函数要引用后面定义的外部(在函数之外)变量时,也应在函数里加以extern说明。引进外部变量的原因:解决函数单独编译的协调;与变量初始化有关;外部变量的值是永久的;解决数据共享;注意:函数本身通常也被认为是外部变量。第四章 函数和程序结构3)静态变量 内部静态变量?在局部变量前加上static关键字就成为内部静态变量。?内部静态变量仍是局部变量,
46、其作用域仍在定义它的函数内。但该变量采用静态存贮分配(由编译程序在编译时分配,而一般的自动变量和函数形参均采用动态存贮分配,即在运行时分配空间),当函数执行完,返回调用点时,该变量并不撤消,其值将继续保留,若下次再进入该函数时,其值仍存在。外部静态变量?在函数外部定义的变量前加上“static”关键字便成了外部静态变量。?外部静态变量的作用域为定义它的文件,即成为该文件的的“私有”(private)变量,其它文件上的函数一律不得直接进行访问,除非通过它所在文件上的各种函数来对它进行操作,这可实现数据隐藏。(在C+中提供进行一步的数据隐藏。)第四章 函数和程序结构4)寄存器变量?只有自动(局部)
47、变量和函数参数可进一步指定为寄存器存贮类。?使用register变量可以提高存取速度,但寄存器变量的数目依赖于具体机器(早期为23个),即使用户希望多说明几个寄存器变量也没有用,只有前面几个有效。?只限于int,char,short,unsigned和指针类型可使用register存贮类。?不能对register变量取地址(即&操作)。第四章 函数和程序结构外部变量外部静态变量内部变量或内部静态变量程序文件函数变量作用域图第四章 函数和程序结构432变量初始化?外部和静态变量由编译程序给予隐含的初值0。?程序员可在变量定义时对它进行初始化(不是赋值表达式)。如:binary(int x,int
48、 y,int n)int low=0;int high=n 1;?旧的程序设计(非ANSI C标准)中,静态和外部的数组、结构和联合(构造类型)可以在它们定义时初始化,但自动的构造类型变量不能初始化。注意:在ANSI C标准中无此限制。如:int x =1,3,3,3;static char pattern =“the”;static char pattern =t,h,e,0;如上所示,外部或静态数组初始化时,数组元素个数可以不写,编译程序可根据初始化时给定的值来确定。第四章 函数和程序结构?自动变量的初始化每进入该函数时便初始化一次。?外部或静态变量的初始化仅在编译时进行一次。?自动变量或
49、寄存器变量只能显式初始化,否则,自动变量和寄存器变量有不确定的值。?外部数据的说明,如果带有初始化项,即当成一个定义。第四章 函数和程序结构44程序结构程序结构在C语言中,函数不能嵌套定义。如,下面定义在C语言中是不充许的:f()g()但在C语言中,变量可以嵌套定义,如:if(n 0)int i;/*declare a new*/for(i=0;in;i+)第四章 函数和程序结构如果出现同名变量,则内层变量将屏蔽外层变量。例4-7:int i=0;main()int i=1;printf(“i=%d,”,i);int i=2;printf(“i=%d,”,i);i+=1;printf(“i=%
50、d,”,i);printf(“i=%d,”,i);printf(“i=%dn”,i);结果:?i=1,i=2,i=3,i=3,i=1第四章 函数和程序结构4.5 C语言预处理程序语言预处理程序预处理关键字:#define#undef#include#if#ifdef#ifndef#else#endif#line(注意:#前面不能留空格)#include#define#ifC预处理程序C编绎器执行程序C源程序第四章 函数和程序结构451包含文件(包含文件(include)格式:#include “文件名”一般文件#inlcude 系统文件编译程序以该文件名的内容来替换该控制行,通常在每个源文件开