本书作为C语言程序设计的入门与应用教材, 共有11章及3个附录。11章的主要内容包括: C语言概述、基本数据类型和运算符及表达式、数据的输入输出、结构化程序设计、数组、函数、编译预处理、指针、构造数据类型、位运算、文件等。3个附录分别是: 常用字符与ASCII代码对照表、运算符的优先级和结合性、常用的C语言库函数。
本书据有如下特色:易于教学和自学,适合初学者;注重基础内容,突出实用性;强化编程思想,突出应用性。本书不只是讲解C语言的语法规则,更重要的是培养读者的C语言程序设计能力。全书始终强化编程思想,通过例题、程序案例、习题,有意识地不断强化,给读者以潜移默化的影响。本书介绍的知识和程序具有通用性,基本可以适用于任何计算机系统和C版本。
本书可作为教材,也可用于培训、考级、考试的参考用书。
C语言是一种在国际上广泛流行的计算机语言,具有很多突出的优点,如很强的数据处理能力,目前已成为计算机程序设计的主流语言。C语言不仅适合于系统软件的设计,还适合于应用软件的设计。在操作系统、工具软件、图形图像处理软件、数值计算、人工智能、数据库处理、嵌入式系统等多个方面都有广泛的应用。目前,全国计算机等级考试、职业资格认定、技能大赛等都将C语言列入考查范围。学习和使用C语言已经成为广大计算机应用人员和学生的迫切需求。因此,我国绝大部分高等院校都将C语言作为学习程序设计入门的语言,同时,C语言也为进一步学习C++以及Visual C++ 奠定了基础。
本书作为C语言程序设计的入门与应用教材,共分11章及3个附录。全书包括以下内容: 第1章C语言概述;第2章基本数据类型、运算符及表达式;第3章顺序结构程序设计;第4章选择结构和循环结构程序设计;第5章数组;第6章函数;第7章编译预处理;第8章指针;第9章构造数据类型;第10章位运算;第11章文件。3个附录分别是: 附录A,常用字符与ASCII代码对照表;附录B,运算符的优先级和结合性;附录C,C语言的库函数。本书注重基础,突出应用,每章的案例尽量贴近生活和应用,以便读者能够综合运用本章所学知识,提高实际编程能力。
本书具有以下特色。
1. 易于教学和自学,适合初学者
充分考虑到初学者学习C语言的特点,本书按照循序渐进、难点分散的原则组织内容。通过通俗易懂的叙述,阐明复杂、灵活的概念。对于难点与重点,通过丰富的例题,进行详尽的解释。力求做到语言通俗、概念清晰、易学实用,以使读者能够做到上手快、学得会、用得着。
2. 注重基础内容,突出实用性
C语言博大精深。本书精选了对初学者最基本、最重要、最实用的内容进行介绍,不刻意追求全面和详尽。对于较生僻的内容,也从概念讲解入手进行简单介绍,以保证C语言的完整性。力求做到内容新颖、实用,逻辑性强,完整性好,且又突出重点。
3. 强化编程思想,突出应用性
本书不只是讲解C语言的语法规则,更重要的是培养读者的C语言程序设计能力。不是只给读者一座花园,而是送给读者整个春天。全书始终有意识地不断强化编程思想,通过例题、程序案例、习题,给读者以潜移默化的影响。由于程序设计语言是实践性很强的课程,故建议读者多上机实践,以尽快掌握C语言的编程方法和提高调试程序的能力。为了加强读者的实践动手能力以及满足参加二级C语言等级考试需要,本书还配套出版了《C语言程序设计实训》。衡量这门课程学习得好坏,不是看“知不知道”,而是看“会不会用”。
本书介绍的知识和程序具有通用性,基本可以适用于任何计算机系统和C版本,但是应说明,不同的C版本是有一些差别的。本书所有程序均在Visual C++ 6.0开发环境中调试通过。
本书由武汉职业技术学院贾学斌、宋海民任主编,胡大威任副主编,其中第1、2、3、9章由宋海民编写;第4、5章由胡大威编写;第6、7、8、10、11章及附录由贾学斌编写。以上各编者都是具有丰富教学实践经验的教师。在本书的编写过程中,得到许多领导及教师的热情支持,还得到了陈觎、周桂枝、张伟的帮助,在此一并表示感谢。
感谢使用本书的各位读者,本书力争写出作者的经验和体会,但由于编者水平有限,书中不足之处在所难免,恳请广大读者批评指正。
编者
2017年4月
第1章C语言概述1
1.1初识C语言1
1.1.1C语言的由来2
1.1.2C语言的特点3
1.2C语言的语法基础4
1.2.1基本符号4
1.2.2标识符4
1.2.3保留字5
1.3设计简单的C程序6
1.3.1赋值语句6
1.3.2printf()函数7
1.3.3scanf()函数8
1.3.4库函数和头文件9
1.4C程序的开发过程10
1.4.1C程序的实现步骤10
1.4.2C语言常用集成开发环境12
1.5在Microsoft Visual C++6.0中开发C程序12
1.5.1VC++6.0集成开发环境简介13
1.5.2建立控制台应用程序15
1.6程序案例19
1.7本章小结23
1.8习题24
第2章基本数据类型、运算符及表达式27
2.1C语言的数据类型27
2.2常量28
2.2.1常量的概念28
2.2.2常量的分类28
2.3变量32〖2〗〖3〗〖4〗2.3.1变量的定义32
2.3.2整型变量34
2.3.3实型变量37
2.3.4字符变量39
2.4运算符和表达式41
2.4.1运算符的分类41
2.4.2运算符的优先级与结合性42
2.4.3算术运算符和算术表达式43
2.4.4增1、减1运算符及表达式44
2.4.5赋值运算符和赋值表达式46
2.4.6关系运算符和关系表达式48
2.4.7逻辑运算符和逻辑表达式50
2.4.8逗号运算符和逗号表达式52
2.4.9sizeof运算符53
2.5数据类型的转换54
2.5.1自动类型转换54
2.5.2强制类型转换55
2.6程序案例56
2.7本章小结57
2.8习题58
第3章顺序结构程序设计62
3.1结构化程序设计基础62
3.1.1算法的概念62
3.1.2算法的特点63
3.1.3算法的描述65
3.1.4结构化程序设计69
3.2输入语句71
3.2.1输入/输出(I/O)函数71
3.2.2字符输入函数和字符输入语句72
3.2.3格式输入函数和格式输入语句73
3.2.4通过scanf()函数从键盘输入数据74
3.2.5scanf()函数输入中常见错误分析75
3.3输出语句76
3.3.1字符输出函数和字符输出语句77
3.3.2格式输出函数和格式输出语句78
3.4程序案例85
3.5本章小结86
3.6习题87
第4章选择结构和循环结构程序设计93
4.1if语句93
4.1.1if语句94
4.1.2if语句的嵌套98
4.1.3条件运算符和条件表达式100
4.2switch语句102
4.3选择结构程序设计案例106
4.4while语句107
4.4.1while语句的一般格式108
4.4.2while语句的执行过程108
4.5do...while语句110
4.5.1do...while语句的一般格式110
4.5.2do...while语句的执行过程110
4.5.3do...while语句和while语句的区别与联系111
4.6for语句112
4.6.1for语句的一般格式112
4.6.2for语句的执行过程114
4.6.3for语句的变形114
4.6.4for、while、do...while 3种语句的比较117
4.7循环嵌套117
4.8break语句和continue语句119
4.8.1break语句119
4.8.2continue语句120
4.9语句标号和goto语句121
4.10程序案例122
4.11本章小结124
4.12习题125
第5章数组132
5.1数组的概念132
5.2一维数组133
5.2.1一维数组的定义133
5.2.2一维数组元素的引用134
5.2.3一维数组的初始化135
5.2.4一维数组的应用136
5.3二维数组140
5.3.1二维数组的定义140
5.3.2二维数组元素的引用141
5.3.3二维数组的初始化141
5.3.4二维数组的应用143
5.4字符数组144
5.4.1字符数组的定义144
5.4.2字符数组的初始化144
5.4.3字符数组的引用145
5.4.4字符串和字符串结束标志146
5.4.5字符数组的输入和输出146
5.4.6字符串处理函数148
5.4.7字符数组的应用150
5.5程序案例151
5.6本章小结153
5.7习题155
第6章函数159
6.1C程序的模块化设计159
6.1.1函数的概念159
6.1.2C程序的模块化设计160
6.1.3函数的分类161
6.2函数的定义162
6.3函数的参数与返回值164
6.4函数的调用166
6.4.1函数调用的一般格式166
6.4.2函数调用的方式166
6.4.3对被调函数的声明168
6.4.4函数的嵌套调用170
6.4.5函数的递归调用171
6.5数组作为函数参数175
6.5.1数组元素作函数实参175
6.5.2数组名作函数参数176
6.5.3二维数组名作函数参数177
6.6变量的作用域和存储类别178
6.6.1变量的作用域178
6.6.2变量的存储类别180
6.6.3局部变量的存储类别180
6.6.4全局变量的存储类别186
6.7函数的作用域和存储类别189
6.8程序案例190
6.9本章小结193
6.10习题195
第7章编译预处理203
7.1宏定义203
7.1.1不带参数的宏定义203
7.1.2带参数的宏定义206
7.1.3取消宏定义210
7.2文件包含210
7.3条件编译213
7.4程序案例216
7.5本章小结216
7.6习题218
第8章指针223
8.1指针概述223
8.1.1内存地址与变量的地址223
8.1.2指针与指针变量224
8.2指针变量226
8.2.1指针变量的定义与初始化226
8.2.2指针变量的引用227
8.2.3指针变量作为函数的参数230
8.3通过指针引用数组233
8.3.1指向数组元素的指针233
8.3.2指针变量的运算234
8.3.3通过指针引用数组元素237
8.3.4数组名和指针变量作函数参数240
8.4指针与字符串243
8.4.1字符串指针变量的定义与使用243
8.4.2字符串指针变量与字符数组的区别246
8.5指针与函数247
8.5.1函数指针变量247
8.5.2指针型函数249
8.6指针数组和二级指针250
8.7main()函数的形参、动态存储分配和void指针253
8.7.1指针数组作为main()函数的形参253
8.7.2动态存储分配254
8.7.3void指针类型255
8.8程序案例256
8.9本章小结257
8.10习题259
第9章构造数据类型264
9.1结构体类型264
9.1.1结构体类型声明264
9.1.2结构体变量的定义265
9.1.3结构体变量的初始化以及成员的引用269
9.2结构体数组271
9.3结构体与函数273
9.3.1结构体变量作为函数参数273
9.3.2结构体变量为函数的返回值275
9.4结构体与指针277
9.4.1结构体变量指针278
9.4.2结构体数组指针280
9.4.3用指向结构体的指针作函数参数282
9.5结构体应用——链表283
9.6共用体类型288
9.7枚举类型290
9.8用typedef定义类型292
9.9程序案例294
9.10本章小结296
9.11习题297
第10章位运算304
10.1位运算符与位运算304
10.2位段309
10.3程序案例310
10.4本章小结311
10.5习题312
第11章文件316
11.1文件概述316
11.1.1文件的概念316
11.1.2文件指针317
11.1.3缓冲文件系统和非缓冲文件系统318
11.2文件的打开和关闭319
11.2.1用fopen()函数打开文件319
11.2.2用fclose()函数关闭文件322
11.3文件的顺序读写323
11.3.1文本文件中字符的输入/输出323
11.3.2文本文件中字符串的输入/输出324
11.3.3文本文件的格式化输入/输出326
11.3.4二进制文件的输入/输出327
11.4文件的随机读写328
11.5文件检测函数329
11.6程序案例330
11.7本章小结332
11.8习题333
附录A常用字符与ASCII代码对照表338
附录B运算符的优先级和结合性339
附录CC语言的库函数341
参考文献348
第3章第3章顺序结构程序设计 Project 3顺序结构是C程序中最简单、最基本、最常用的一种程序结构。也是进行复杂程序设计的基础。顺序结构的特点是完全按照语句出现的先后顺序依次执行程序。在日常生活中,需要“按部就班、依次进行”处理和操作的问题随处可见。赋值操作和输入/输出操作是顺序结构中最典型的操作。 本章学习目标
1. 掌握结构化程序设计基础知识
2. 掌握输入语句的使用方法
3. 掌握输出语句的使用方法
3.1结构化程序设计基础 初学者常常会有这样的一种感觉: 读别人编写的程序比较容易,自己虽然学了程序设计语言,可编写程序,却不知从何下手。其中一个重要的原因就是没有掌握程序设计的灵魂——算法。所以,多了解、掌握和积累一些计算机常用的算法,养成编写程序前先设计好算法的习惯至关重要。
3.1.1算法的概念〖*2〗1. 基本概念一个程序应包括对数据的描述和对数据处理的描述。 对数据的描述,即数据结构(Data Structure)。数据结构是计算机学科的核心课程之一,有许多专门著作论述,本书不再赘述。 对数据处理的描述,即算法(Algorithm)。算法是为解决一个问题而采取的方法和步骤,是程序的灵魂。为此,著名计算机科学家尼克劳斯·沃思(Niklaus Wirth)提出了一个公式: 程序=数据结构+算法 实际上,一个程序除了以上两个主要因素之外,还应考虑程序设计的方法以及用何种计算机语言来描述。因此,程序还可以这样表示: 程序=算法+数据结构+程序设计方法+语言工具和环境 所以,在设计一个程序时要综合运用这4方面的知识。在这4个方面中,算法是灵魂,数据结构是要处理的对象,语言是工具,编程需要采用合适的方法。算法是解决“做什么”和“怎么做”的问题。程序中的操作语句,实际上就是算法的体现。 〖2〗〖3〗〖4〗无论是解决数学问题,还是解决日常生活和工作中的问题,都必须采用一定的方法,并且按照一定的步骤来解决。因此,广义地认为,算法是指为解决一个问题而采取的方法和步骤。 对于不同的问题有不同的算法,而对于同一个问题,也可以有不同的算法。例如,求1+2+3+4+5+6+7+8+9+10的和,就有多种算法。 其一,按照数的先后顺序,从左至右一个数一个数地相加,直到加完10为止; 其二,将1与9相加,2与8相加……即原式=(1+9)+(2+8)+(3+7)+(4+6)+10+5=5×10+5=55。 还有其他算法。显然,在这里第二种算法比第一种算法优越,也就是说,对于同一个问题,不仅有不同的算法,而且这些算法又有优劣之分。有的算法只需很少的步骤,而有些算法则需要较多的步骤。一般地说,应采用简单的和运算步骤少的算法。因此,为了有效地进行解题,不仅需要保证算法正确,还要考虑算法的质量,选择好的算法。 对于计算机而言,考虑的当然只限于计算机算法,即计算机所能执行的算法。例如,1+2+3+4+5,或者是将50名学生的成绩打印出来,并且统计及格学生人数。这是计算机可以做到的。
2. 算法分类 计算机算法可分为两大类,数值运算算法和非数值运算算法。 数值运算算法,如求方程的根,求一个函数的定积分等。其目的是求数值解,它们属于数值运算范围。 非数值运算算法,如图书检索、人事管理、车辆调度管理等,其范围十分广泛。 目前,计算机在非数值运算方面的应用远远超过了在数值运算方面的应用。由于数值运算有现成的模型,可以运用数值分析的方法,因此,对数值运算的算法研究比较深入,算法比较成熟,对各种数值运算都有比较成熟的算法可供选用。人们常常将这些算法汇编成册(写成程序形式),或将这些程序存放在磁盘上,供用户调用。而非数值运算的种类繁多,要求各异,难以规范化,因此,只能对一些典型的非数值运算算法(如排序算法)作比较深入的研究。其他的非数值运算问题,往往需要用户参考已有的类似算法,重新设计解决特定问题的专门算法。 3.1.2算法的特点 算法实际上是一种抽象的解题方法,它具有动态性。因此,算法的行为非常重要。作为一个算法,应具有以下特性。
1. 有效性(Effectiveness) 算法的有效性包括两个方面。一是算法中的每一个步骤必须能够实现。例如,在算法中,不允许分母为零的情况;在实数范围内不能求一个负数的平方根等。二是算法执行的结果要能达到预期的结果。通常,针对实际问题设计的算法,人们总是希望能够得到满意的结果。
2. 确定性(Definiteness) 算法的确定性,是指算法中的每一个步骤都必须有明确的定义,不允许有模棱两可的解释,也不允许有多义性。这一特征也反映了算法与数学公式的明显差异。在解决实际问题时,可能会出现这样的情况: 针对某种特殊问题,数学公式是正确的,但按此数学公式设计的计算过程可能会使计算机系统无法认知。这是因为根据数学公式设计的计算过程只考虑了正常使用的情况,而当出现异常情况时,该计算过程就不适应了。例如,某计算公式规定,大于100的数被认为比1大很多,而小于100的数不能认为比1大很多;并且在正常情况下出现的数或是大于100,或是小于100。但指令“输入X,若X比1大很多,则输出数字1,否则输出数字0”是不确定的。这是因为,在正常的输入情况下,这一指令的执行可以得到正确的结果,但在异常情况下(输入的X在10~100),这一指令执行的结果就不确定了。
3. 有穷性(Finiteness) 算法的有穷性是指算法必须在有限的时间内执行完,即算法必须能在执行有限个步骤之后终止。数学中的无穷级数,在实际计算时只能取有限项,即计算无穷级数的过程只能是有穷的。因此,一个数的无穷级数的表示只是一种计算公式,而根据精度要求确定的计算过程才是有穷的算法。 算法的有穷性还包括合理的执行时间。如果一个算法的执行时间是有穷的,但需要执行千万年,显然这就失去了算法的实用价值。例如,克莱姆(Cramer)法则是求解线性代数方程组的一种数学方法,但不能以此为算法,这是因为,虽然总可以根据克莱姆法则设计出一个计算过程用于计算所有可能出现的行列式,但这样的计算过程所需的时间实际上是不能容忍的。再如,从理论上讲,总可以写出一个正确的弈棋程序,而且这也不是一件很困难的工作。由于在一个棋盘上安排棋子的方式总是有限的,而且,根据一定的规则,在有限次移动棋子之后比赛一定结束。因此,弈棋程序可以考虑计算机每一次可能的移动,它的对手每一次可能的应答,以及计算机对这些移动的可能应答等,直到每个可能的移动停止下来为止。此外,由于计算机可以知道每次移动的结果,因此,总可以选择一种最好的移动方式。但是即使如此,这种弈棋程序还是很难执行,因为所有这些可能移动的次数太多,所要花费的时间不能容忍。由上述两个例子可以看出,虽然许多计算过程是有限的,但仍有可能无实用价值。 ……