《C语言程序设计课程教学大纲 .doc》由会员分享,可在线阅读,更多相关《C语言程序设计课程教学大纲 .doc(29页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第1章 C语言导论为什么称之为C语言?这通常是C程序设计语言初学者最先提出的问题之一。答案为C语言是从B语言演变而来!但B语言不是从A语言演变而来,而是从BCPL(Basic Combined Programming Language)语言演变而来。BCPL是由Martin Richards 在1967年设计出来的,是一种无数据类型的语言,它直接处理机器系统的字和地址。在BCPL的启发下,Ken Thompson在1970年开发了无数据类型的程序设计语言B,B语言和汇编语言被用来开发UNIX操作系统的第一个版本。1972年,Dennis Ritchie设计出了C语言,该语言既吸收了BCPL和B
2、语言的许多思想,又具备数据有类型的特色(整型、浮点型等)。直到1989年,C语言的定义还是沿用了Brian W.Kernighan和Dennis M.Ritchie在The C Programming Language(Englewood Cliffs,NJ:Prentice-Hall,1978)一书中的描述,我们称C语言的这个版本为传统C语言。由于该语言的发展和扩充、最初定义中有一些不明确之处以及出于其他方面的考虑,1983年,美国国家标准化协会(ANSI)组织一个委员会“提供明确的和与机器无关的C语言的定义”,并于1989年通过了所制定的标准。本书介绍的C语言基于ANSI C标准,此后简称
3、为标准C语言。本章将举例介绍一些基本的语言概念:C语言程序的结构、标识符、while和do while循环、条件语句(if-else)、输入、输出和文件,在以后的章节中会就这些主题展开详细描述。1.1 第一个C语言程序下列程序打印输出的信息如下:ANSI - A kinder and gentler C!/* 该程序打印输出如下信息: ANSI - A kinder and gentler C! */#include main() printf( ANSI - A kinder and gentler C!n );在C语言中,符号/*标记注释行的开始,符号*/标记注释行的结束,编译器忽略注释行
4、。如下行是一条预处理指令(preprocessor directive): #include 它表示在把程序实际翻译成机器代码之前还需要做某个预处理动作(预处理器在编译之前执行预处理指令,将在4.6节详细介绍预处理器)。预处理指令总是以井号(#)开头。这里的#include 预处理指令使得预处理器把名为stdio.h的文件内容准确地插入到#include行出现的地方,这样的文件称为头文件(header file),扩展名.h即来自于这种命名法。实际上,头文件stdio.h提供使用库函数printf的适当接口。附录B列出了标准所要求的头文件,附录D列出了一些有用的库函数以及对应需要的头文件。一个
5、C语言程序由一个或多个函数(function)组成,其中必须有一个main函数。程序从main函数开始执行。任何一个函数的所有语句用一对大括号 括起来。在本例中,程序仅由一个main函数组成,该main函数仅含一条语句:printf( ANSI - A kinder and gentler c!n );C语言中的单条语句,如:printf( ANSI - A kinder and gentler C!n);是以分号“;”结束的。除了特殊的字符如反斜杠“”之外,函数printf简单地复制两个双引号里面的字符到视频显示器上。因此如下语句:printf(ANSI - A kinder and gen
6、tler C!n);在屏幕上打印输出:ANSI - A kinder and gentler C!反斜杠“”作为特殊的转义字符。字符组合n的意思是换行,并使下一个输出从下一行的行首开始,这里下一个输出是系统提示符。像大部分现代高级语言编译器一样,C语言编译器不需要程序的语句以任何特定的格式出现。本书格式化编写的程序,尤其是采用缩排的形式,目的是便于阅读。附录F描述如何在Borland C+和Windows下的Microsoft Visual C+中编译、连接和运行C语言程序。附录E讨论UNIX C编译器。练习1在你的系统上编译运行本节的程序。2修改并运行本节的程序。尝试删除程序的某部分,例如省
7、略如下行:#include 再如,省略一个大括号,省略一个双引号。若有错误的话,说明是什么错误,并解释这些错误。1.2 应用举例:长度转换问题从键盘读入以码(yd)为单位的长度,把该长度转化成对应的英尺(ft)和英寸(in),并将转换后的长度输出到屏幕上。假设输入的长度是非负整数(如:0,1,2,中的一个),程序以输入负数结束(如:-1,-2,中的一个)。这些单位之间的换算关系如下:1 yd = 3 ft1 yd = 36 in输入/输出举例输入部分用斜体字标出,输出部分用黑体字标出,如下所示:Enter next length 22 yd =6 ft72 inEnter next lengt
8、h 3030 yd =90 ft1080 inEnter next length 99* END OF PROGRAM * 用C语言实现/* 程序从键盘读入以码(yd)为单位的长度,把该长度转化成对应的英尺(ft)和英寸(in), 并将转换后的长度输出到屏幕上。 假设输入的长度是非负整数,程序以输入负整数结束。 */#include main() int yard, foot, inch; printf( Enter next length ); scanf( %d, &yard ); while ( yard = 0 ) foot = 3 * yard; inch = 36 * yard;
9、printf( n%d yd=n, yard ); printf( %d ftn, foot ); printf( %d inn, inch ); printf( Enter next length ); scanf( %d,&yard ); printf( * END OF PROGRAM *n);讨论在C语言中所有变量都必须在被定义后才能使用。在C语言中定义变量就是为特定数据类型的变量申请存储空间。本程序首先定义3个变量yard、foot和inch:int yard, foot, inch;因为这些变量被定义为int类型(整型),所以每个变量都能存储一个有符号整数。我们把类型(如:int型
10、)对应的存储空间称为单元(cell)。定义变量yard、foot和inch的结果如图1.1(a)所示。这时,这些单元所含的值与系统有关,不能认为每个单元存储的值是零或其他特殊的值。一般说这些单元含有“垃圾数据”,因为它们现在所含的值对程序是无意义的。可以在定义变量yard、foot和inch的同时对它们进行初始化。例如,下面语句定义变量yard、foot和inch:int yard = 0, foot = 1, inch = 8;同时初始化yard值为0、foot值为1和inch值为8,如图1.1所示。(a)分配3个存放整型数的单元(b)赋初值图1.1 分配3个整型单元并初始化其值为了提示用户
11、输入长度,程序使用了在1.1节中介绍的printf函数。其中由双引号括起来的字符串称为格式字符串(format string),由于该格式字符串不包含特殊字符(如,反斜杠),当执行下列语句时:printf( Enter next length );将在显示器上输出如下信息:Enter next length其次,本程序使用库函数scanf从键盘读入一个整数,函数scanf也需要一个格式字符串。一个scanf的格式字符串包含一个或多个以百分号(%)作为标志的格式描述符(format descriptors),这些格式描述符决定了下一个输入项的类型(如int型)和如何存储这个值(如按二进制补码表示
12、一个有符号整数)。跟在格式字符串之后的是那些将用于存储数据的单元的地址,符号&称为地址运算符(address operator)。例如,&yard的值是yard单元的地址。必须给函数scanf提供变量的地址,这样函数scanf就知道将输入的内容存储到何处,因此执行如下语句时:scanf( %d, &yard );读取下一个由用户提供的数值,将它解释成十进制整数并存储到变量yard中(位于地址&yard处)。在scanf语句之后是while循环。注意while循环的如下循环体是由大括号括起来的,右大括号后面并没有分号。foot = 3 * yard;inch = 36 * yard;printf
13、( n%d yd=n, yard );printf( %d ftn, foot );printf( %d inn, inch );printf( Enter next length ); scanf( %d, &yard );若while循环的循环体只由一条语句组成,则大括号可以省略。只要while循环中的如下条件成立,就将执行while循环体:yard = 0除了=(大于或等于)之外,C语言提供了如下关系运算符: 大于 小于 = 0至此while循环结束。这时执行while循环之后的语句:printf( * END OF PROGRAM *n );输出内容:* END OF PROGRAM
14、*由于这是main函数的最后一条语句,程序就此结束。练习1编写一个程序,从键盘读入以磅为单位的重量,转换成以盎司为单位的重量,并将转换后的重量输出到屏幕。假设重量是非负整数,在输入负整数时程序结束。2编写一个程序,提示用户输入整数,当用户输入负整数时,程序停止读入数据并且输出已输入的所有非负整数的和,假定至少输入一个非负整数。1.3 标 识 符在写程序的时候,需要给变量、函数等取名字。在高级语言中,标识符(Identifier)是用于命名的有效字符序列。在C语言中标识符必须满足下列条件:l 只能以字母(从AZ或从az)或下划线(_)作为第一个字符。l 只能由字母(从AZ或从az)、数字(从09
15、)和下划线(_)组成。l 不能是关键字。关键字(keyword)是诸如int或while等有特殊意义的单字或字符序列。在附录B中给出了关键字的完整列表。例1.3.1下列名称是合法的标识符:totaltotal_cars_sumcolumn3TOTAL 除了7.4节才会提到的全局名称以外,一个标识符的至少前31个字符是有意义的。大写字母与小写字母是有区别的,因此total和TOTAL是两个不同的标识符。系统一般使用以下划线作为首字符的标识符。所以,建议不要使用下划线作为自定义的标识符的第一个字符,因为这有可能使该自定义标识符与某个系统标识符产生冲突。例1.3.2下列名称是非法的标识符: tota
16、l$(非法字符 $)2nd_sum(以数字符开头)long(关键字)second sum(不能含空格字符)TOTAL-CARS(非法字符-) 练习1标识符name和NAME不同吗?解释原因。2允许标识符为长名称有什么优点?请说明从练习3练习10的每个名称是否为合法的标识符?若名称不是合法标识符,解释原因。3sum_of_credits4_type_of_car5while6SECTION_67bingo-square83_4_879initial tree10final_#11下列两个标识符必然不同吗?为什么?chapter_3_section_xi_example_3_6chapter_3_
17、section_xi_example_3_31.4 while语句在1.2节简要介绍了while语句,本节将详细讨论while循环。while语句的格式如下:while ( expression )action在执行while语句时,首先判断表达式expression是否为真,如图1.3所示。C语言要求表达式expression由圆括号括起来。若表达式为真,执行动作action部分,并回到循环顶部;再次判断表达式,若表达式为真,执行动作并回到循环顶部。重复该过程,一旦在循环顶部判断表达式为假时,就跳到紧跟在动作action之后的语句。在上述while循环语句的格式中,动作action部分由一条
18、未加大括号的语句或者包含在大括号中的一条或多条语句组成。例1.4.1 执行如下程序片段时:int x;x = 0;while ( x != 2 )x = x + 1;printf( x= %dn, x );图1.3 while语句产生如下输出:x = 2如下语句将x赋值为0:x = 0;因为字符组合 != 是关系运算符“不等于”,表达式 x != 2 值为真,因此执行如下语句将x加1:x = x + 1;然后回到while循环顶部。这时x值为1,表达式x != 2为真,因此再次将x加1,再回到while循环顶部。这时x值为2,至此表达式x != 2为假;因此结束while循环。然后执行如下语句
19、:printf( x = %dn, x );产生如下输出:x = 2 练习1下列程序片段的输出结果是什么?int x;x = 7while ( x = 0 ) printf( %dn, x ); x = x - 2;2下列程序片段的输出结果是什么?int x;x = 7while ( x = 0 ) x = x - 2; printf( %dn, x );3下列程序片段的输出结果是什么?int x;x = 7while ( x = 0 ) x = x - 2;printf( %dn, x );4下列程序片段的输出结果是什么?int x;x = 1while ( x = 1 ) x = x -
20、1; printf( %dn, x );5下列程序片段的输出结果是什么?int x;x = 1while ( x = 1 ) x = x - 1; printf(%dn,x);6下列程序片段在哪里有语法错误?while ( x 0 ) do x = x - 1;printf( %d, x );1.5 do while语句do while语句类似于while语句,惟一的区别是控制循环的表达式在循环底部测试其是否为真,因此循环体总是至少被执行一次。do while语句的格式如下:do action while ( expression );在执行do while语句时,首先执行动作action部分
21、,然后判断表达式expression值是否为真,若为真,回到循环的顶部,重复该过程,如图1.4所示。即先执行动作,再判断表达式值。一旦在循环底部表达式值为假时,就跳转到紧随while(expression)之后的语句。在上述do while循环中,动作部分由一条不加大括号的语句或者包含在大括号中的一条或多条语句组成。图1.4 do while语句例1.5.1do while循环适用于在循环底部判断条件的情况,例如,校验用户输入。该情形下,在用户输入值以后对输入的值进行检查。下面的代码要求用户输入一个正数,然后对其进行有效性检查,如若输入无效,提示用户再次输入。do printf( Enter
22、a positive integer: ); scanf( %d, &response ); while ( response = 1 );2用while循环替代do while循环改写例1.5.1中的程序片段。1.6 应用举例:计算所得税问题某国有一个特别简单的征税系统。对收入在6000元(greenback)(该国货币的基本单位)以下的人征收30%的税,对收入大于等于6000元的人征收60%的税。编写一个读取收入并打印出应付税金的程序。程序依次读取收入,直到用户输入文件结束标志(end-of-file)。假定收入是一个整数,截除税金的小数部分,使得输出为整数。输入/输出举例输入部分用斜体标
23、出,输出部分用黑体标出。1000Income = 1000 greenbacksTax = 300 greenbacks7000Income = 7000 greenbacksTax = 4200 greenbacks2904Income = 2904 greenbacksTax = 871 greenbacks32067Income = 32067 Tax = 19240Exit在行Tax = 19240之后,由于输入了表示输入文件结束的控制符,所以系统输出信息Exit(请参见随后的讨论部分)。解决方案使用一个while循环来反复读取收入数据,while循环中的条件是判断文件结束标记值。在w
24、hile循环内,判断收入是否高于或低于6000元,并据此计算税金。用C语言实现/* 程序反复读取收入数据和打印输出应付税金,直到遇文件结束标志为止。 收入在6000元以下,征收30%的税;收入大于等于6000元,征收60%的税。 假定收入是一个整数,税金也以整数输出。 */#include main() int income, tax; while ( scanf( %d, &income) != EOF ) printf( Income = %d greenbacksn, income ); if ( income 6000 ) tax = 0.3 * income; else tax =
25、0.6 * income; printf( Tax = %d greenbacksn, tax ); 讨论文件stdio.h含有常量EOF的定义。EOF的值通常被定义为0或-1,对于特定的系统,可以通过包含头文件stdio.h的方式,得到EOF的正确值。当函数scanf成功读入一个值时,它返回不等于EOF的值。这时,如下表达式为真:scanf( %d , &income ) != EOF于是执行while循环的循环体。当函数scanf读到文件结束时,返回值EOF。此时,如下表达式为假:scanf( %d , &income ) != EOFwhile循环就此结束。可以通过从键盘输入一些控制字符
26、来表示文件的结束。在UNIX中,control-D表示文件结束;在VAX/VMS或MS-DOS中,这样的控制字符是control-Z。当从键盘输入文件结束标志时,系统向屏幕输出一些字符确认收到了该控制字符。例如,在VAX/VMS中,当用户按下control-Z键,系统输出信息Exit;在UNIX中,当用户按下control-D键,系统输出信息D;在MS-DOS中,当用户按下control-Z键,系统输出信息Z。在如下的if-else 语句中:if ( income 6000 ) tax = 0.3 * income;else tax = 0.6 * income;若如下所示的条件成立:inco
27、me 6000那么就执行如下语句:tax = 0.3 * income;反之,若如下所示条件不成立:income 6000那么就执行如下语句:tax = 0.6 * income;这样,在任何一种情况下,都能够正确地计算税金。注意:if语句不包括单词then;同时也请注意单词else后没有分号。在如下两条计算税金的语句中:tax = 0.3 * income;tax = 0.6 * income;乘积可能带小数,但由于该结果被赋给整型变量tax,所以小数部分被截除。1.7 if语句在1.6节介绍了if语句,本节将详细讨论if语句。利用if语句可以有条件地执行某一段代码,if语句的一种格式如下所
28、示:if ( expression )action类似于while语句,表达式expression必须用圆括号括起来。在执行if语句时,首先判断表达式expression的值是真还是假,如图1.5所示。若该表达式值为真,就执行动作action部分的语句,然后继续执行紧跟在动作action之后的语句。若该表达式值为假,不执行动作action部分的语句,而是跳过它,执行紧跟在动作action之后的语句。在if语句中标明为动作action的部分由一条不加大括号的语句,或者包含在大括号中的一条或多条语句组成。 图1.5 if语句例1.7.1在执行如下程序片段时:int code;code = 1;if
29、 ( code = 1 ) printf( The water was too warmn );printf( * End of fishing excuses * );输出结果如下:The water was too warm* End of fishing excuses * 为了判断相等,使用双等于号(=)而不是单等于号(=),当需要双等于号(=)的时候使用单等于号(=)是时常发生且很难发现的一个错误。单等于号是赋值运算符;双等于号用于判断相等。如下编写形式在语法上是正确的:if ( x = 1 )但系统解释上述语句的方式通常不是用户所认为的方式,请参见例2.4.8。例1.7.2说明了动
30、作部分由多条语句组成的if语句。例1.7.2在执行如下程序片段时:int code;code = 1;if ( code = 1 ) printf( The water was to warmn ); printf( The waters were all fished out n ); printf( It was too late in the seasonn );printf( * End of fishing excuses * );输出结果如下:The water was to warmThe waters were all fished outIt was too late in
31、the season* End of fishing excuses * if语句的另一种格式如下:if ( expression ) action 1else action 2执行这种格式的if语句时,首先判断表达式expression的值是否为真,如图1.6所示。若该表达式的值为真,执行动作action1部分的语句,然后执行紧跟在动作action2部分后面的语句,这种情形不执行动作action2部分的语句。与此相反,若该表达式值为假,执行动作action2部分的语句,然后执行紧跟在其后面的语句,该情形下不执行动作acion1部分的语句。不论是动作acion1部分还是动作action2部分,
32、都可由一条不加大括号的语句或者包含在大括号中的一条或多条语句构成。例1.7.3执行如下程序片段时:int code;code = 1;if ( code = 1) printf( The water was too warmn )else printf( The waters were all fished outn )printf( * End of fishing excuses * );输出结果如下:The water was too warm* End of fishing excuses * 图1.6 if-else语句例1.7.4执行如下程序片段时:int code;code =
33、2;if (code != 2 ) printf( The water was too warmn ); printf( The waters were all fished outn );else printf( It was too late in the seasonn ); printf( The bait was wrongn );printf( * End of fishing excuses * );输出结果如下:It was too late in the seasonThe bait was wrong* End of fishing excuses * 因为if或if-el
34、se本身是一条语句,所以if或if-else可以是另一个if或if-else语句的动作。例1.7.5如下程序片段可以解释为外层if语句的动作部分恰巧是一个if-else语句。if ( no_fish = 1 ) if ( code 2 ) printf( The water was too warmn ); else printf( The waters were all fished outn );也就是说,该程序片段是具有如下形式的语句:if ( no_fish = 1 ) action其中动作部分是如下的单条语句(single statement)(一个if-else语句被认为是一单条语
35、句):if ( code 2 ) printf( The water was too warmn );else printf( The waters were all fished outn );在执行如下程序片段时:int no_fish, code;no_fish = 1;code = 2;if ( no_fish = 1 ) if ( code 2 ) printf ( The water was too warmn ); else printf ( The waters were all fished outn );printf ( * End of fish story * );输出
36、结果如下: The waters were all fished out* End of fish story *首先给no_fish赋值1,给code赋值2。因为条件no_fish = 1为真,所以执行动作部分的如下语句:if ( code 2 ) printf( The water was too warmn );else printf( The waters were all fished outn );因为表达式code 2值为假,所以执行else后面的如下语句:printf( The waters were all fished outn );然后执行如下语句:printf( * End of fish story * ); 由于编译器不受缩进格式(缩排)的影响,因此若把前面的程序片段改写成如下形式:int no_fish, code;no_fish = 1;code = 2;if ( no_fish = 1 ) if ( code 2 ) printf( The water was too warmn );else printf( The waters were all