C语言程序设计(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-19 09:14:01

点击下载

作者:呼克佑

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

C语言程序设计

C语言程序设计试读:

前言

近年来,学习计算机程序设计的人几乎都选择C语言作为首选语言。《C语言程序设计》不仅是计算机类专业的一门专业基础课,也是大多数理工类专业的必修课。

为什么要学习C语言?大致有以下几个理由:

● C语言可以作为学习计算机程序设计语言的入门语言。

● C语言是编写操作系统的首选语言,与计算机硬件打交道时灵巧且高效。

● C语言具有现代高级程序设计语言的基本语法特征。

● 常用的面向对象程序设计语言如C++和Java,其基本语法来源于C语言。

● 许多用C语言编写的系统需要维护。

● 用于要求程序高速运行领域的编程,如嵌入式系统、通信程序。

● 游戏设计者和黑客少不了C语言。

● C语言使用者和爱好者众多。

学习C语言,需要理解和掌握C语言中诸如关键字、标识符、数据类型、常量、变量、运算符和表达式等基本概念,也需要掌握语句、数组、函数、指针、结构体、文件的使用。同时需要了解和掌握计算机的解题过程、算法的设计和表示、结构化程序设计方法等内容。

本书全面、系统地介绍了C语言的语法、语义和程序设计技术,内容丰富,结构完整,力求精练实用。对抽象概念的叙述通俗易懂,内容安排突出重点、分散难点,实例充实全书。全书共分10章。第1章介绍了C语言的简史、特点,计算机解题过程和算法的概念。第2章介绍了C语言的基本数据类型、常量、变量、运算符和表达式。第3章介绍了结构化程序设计的三种基本结构及其控制语句。第4章介绍了数组的使用及其程序设计方法。第5章介绍了指针的使用及其程序设计方法。第6章介绍了用户自定义函数的定义、调用和声明方法,以及变量的作用域规则。第7章介绍了C语言的复杂数据类型结构体和动态数据结构。第8章介绍了文件的基本概念和操作方法。第9章介绍了宏、文件包含、条件编译等预处理命令的使用。第10章是上机指导。每章均给出了覆盖几乎所有知识点的习题供学生练习。最后提供了非常实用的附录,如常用库函数介绍、编译连接常见错误信息表等。

本书作为教材使用时,建议讲授学时不少于40课时,实验学时不少于16课时。

本书配有电子课件、源代码等教学资源,可登录电子工业出版社华信教育资源网(www.hxedu.com.cn),免费注册、下载。

参加本书编写的人员都是长期工作在教学第一线的教师,从事计算机专业课程教学多年,有丰富的教学经验。本书由呼克佑老师主编并编写第4、8、9章,第1、2章由林福平老师编写,第3章由邓红霞老师编写,第5、10章由段利国老师编写,第6章由曹棣老师编写,第7章由阎志中老师编写,全书由呼克佑老师统稿,由冯秀芳老师主审。

在本书的编写过程中得到了太原理工大学相关领导的大力支持和帮助,在此表示衷心的感谢。由于作者水平有限,书中疏漏在所难免,殷切盼望读者批评指正。

编 者

第1章 C语言与程序设计

本章主要内容

C语言发展简史与特点

计算机解题过程

算法及其表示

常用算法介绍

结构化程序设计方法

众所周知,计算机系统是由硬件和软件组成的,程序是软件系统中不可或缺的重要组成部分,而程序是用计算机语言编写的。学习计算机语言和程序设计技术,就是要学会用计算机语言编写解决实际问题的程序,这对于软件开发人员来说是重要的一步。

指示计算机完成特定操作的命令称为指令,计算机硬件所有指令的集合称为该计算机的指令系统或机器语言。使用机器语言编写程序效率低且不方便,没有人直接使用机器语言编写程序。C语言是一种既低级又高级的计算机程序设计语言,用C语言代替机器语言编写程序,可以达到机器语言程序的效果——程序执行速度快且使用存储空间小,同时C语言又是一种高级程序语言,编写程序的效率与其他高级程序语言并无差异。

学习“C语言程序设计”主要包括两个方面:一是学习C语言的语法规则;二是学习程序设计方法。在掌握C语言的语法规则的基础上,运用程序设计方法设计解决问题的算法,从而设计出解决问题的C语言程序。

学习计算机语言,当然也包括C语言,主要是学习语法和语义两个方面。计算机语言的语法是严格定义的,不允许有语法错误。语法是一些规定,如各种语句及各种语法成分都有各自的规定。同时计算机语言的语义是唯一的,没有二义性的,各种语句及语法成分有各自的语义。只有掌握计算机语言的语法,理解语义,才能正确使用计算机语言编写没有语法错误和逻辑错误的程序。

程序设计是给出解决特定问题程序的过程,包括问题分析、算法设计、程序源代码设计、测试、调试和维护。源代码可以用C语言编写,也可以用其他计算机语言编写。程序设计的目的是得到一个指令序列,提供给计算机来执行,使得问题得到解决。在程序设计过程中,往往需要不同方面、不同领域的专业知识,包括应用领域知识、特定算法知识和形式逻辑知识等。

学习程序设计时,需要了解和掌握计算机的解题过程、算法的设计和表示、结构化程序设计等内容。同时需要用具体的计算机语言编写程序。在这个过程中,需要学习和掌握程序的编辑、编译、调试和运行等有关操作。

C语言程序设计是一门实践性很强的课程。在学习过程中,不仅要掌握基本概念、语法和语义等内容,还需要注重实验环节,通过自己动手编写程序,在完成C语言程序的编辑、编译、调试和运行的过程中,加深对C语言的理解,体会编写程序过程及有关的关键技术。与此同时,培养编程兴趣,提高编程能力。

通过学习C语言,可以为进一步学习其他计算机语言,包括目前常用的面向对象的语言如C++、Java等各种计算机语言奠定基础。

1.1 C语言发展简史

C语言是一种广泛使用的面向过程的计算机程序设计语言,既适合于系统程序设计,又适合于应用程序设计。C语言在操作系统、软件工程、图形学、数值分析等诸多领域得到了广泛的应用。

早期的计算机语言,除了汇编语言之外,高级程序设计语言有FORTRAN语言、ALGOL语言和COBOL语言等。后来出现了大量的各种各样的高级语言,较有影响的有BASIC语言、PASCAL语言、C语言、C++语言和Java语言等。C语言的发展历程大致如图1-1所示。图1-1 C语言的发展历程

1960年出现的ALGOL60很受程序设计人员欢迎,用ALGOL60描述算法很方便,但硬件操作能力较弱,不宜用来编写系统程序。1963年英国剑桥大学在ALGOL语言的基础上推出了CPL(复合程序设计语言),增加了直接对硬件的处理能力,但由于规模大,因此实现困难。1967年剑桥大学的马丁·理查德(Matin Richards)对CPL语言进行了简化,推出了BCPL(基本复合程序设计语言)。1970年美国贝尔实验室的肯·汤普逊(Ken Thompson)对BCPL语言进一步简化,突出了硬件处理能力,取名B语言(BCPL的第一个字母),并用B语言写了第一个UNIX操作系统程序,但B语言过于简单,功能有限。1972年贝尔实验室的丹尼斯.M.里奇(Dennis.M.Ritchie)对B语言进行了完善和扩充,保留了B语言的硬件处理能力,扩充了数据类型,强调了通用性,这就是C语言(BCPL的第二个字母)。1973年肯·汤普逊和丹尼斯.M.里奇两人合作,用C语言重写了UNIX操作系统,并在PDP-11计算机上加以实现。C语言伴随着UNIX操作系统成为一种最受欢迎的计算机程序设计语言。

UNIX操作系统因简洁、实用和高效率而受到人们欢迎,C语言功不可没。1977年出现了不依赖于具体机器的C语言编译版本“可移植C语言编译程序”,使C语言移植到各种不同的机器变得非常简单。1978年,贝尔实验室的布朗.W.卡尼汉(Brian.W.Kernighan)和丹尼斯.M.里奇(Dennis.M.Ritchie)合著了“The C Programming Language”一书,对C语言的语法进行了规范化的描述,成为以后广泛使用的C语言的基础。随着微型计算机的普及,产生了各种不同的C语言版本,为了统一标准,美国国家标准学会(ANSI)于1983年制定了C语言标准,这就是ANSI C标准。1990年,C语言成为国际标准化组织(ISO)通过的标准语言,这一C语言版本称为C89或C90。1999年通过的ISO/IEC9899:1999新标准称为C99。

目前已经有一些C语言的编译器支持C99。在实际编写程序过程中,应该了解和使用C语言的标准,使得编写的程序具有可移植性,可以运行于不同的计算机系统。

1.2 C语言的特点

C语言是一种通用的程序设计语言,语言本身简洁、灵活、表达能力强,被广泛用于系统软件和应用软件的开发,并且具有良好的可移植性。

C语言的特点可概括如下:(1)C语言简洁、紧凑、灵活。C语言的核心内容很少,只有32个关键字,9种控制语句;程序书写格式自由,压缩了一切不必要的成分。(2)表达方式简练、实用。C语言有一套强有力的运算符,达44种,可以构造出多种形式的表达式,用一个表达式就可以实现其他语言可能需要多条语句才能实现的功能。(3)具有丰富的数据类型。数据类型越多,数据的表达能力就越强。C语言具有现代语言的各种数据类型,如字符型、整型、实型、数组、指针、结构体和共用体等,可以实现诸如链表、栈、队列、树等各种复杂的数据结构。其中的指针类型使得参数的传递简单并且迅速,同时节省内存空间。(4)具有低级语言的特点。C语言具有与汇编语言相近的功能和描述方法,如地址运算和二进制数位运算等,还可以对硬件端口等资源进行直接操作,充分使用计算机的资源。C语言既具有高级语言便于学习和掌握的特点,又具有机器语言或汇编语言对硬件的操作能力。因此,C语言既可以作为系统描述语言,又可以作为通用的程序设计语言。(5)C 语言是一种结构化语言,适合于大型程序的模块化设计。C 语言提供了编写结构化程序的基本控制语句,如if-else语句、switch语句、while语句和do-while语句等。C语言程序是函数的集合,函数是构成C语言程序的基本单位,每个函数具有独立的功能,函数之间通过参数传递数据。程序员可以编写自己的函数。同时,不同操作系统的编译器都为程序员提供了大量的标准库函数,如输入/输出函数、数学函数和字符串处理函数等。灵活地使用标准库函数可以简化程序设计,提高编写程序效率。(6)各种版本的编译器都提供了预处理命令和预处理程序。预处理扩展了C语言的功能,提高了程序的可移植性,为大型程序的调试提供了方便。(7)可移植性好。程序从一个环境不经改动或稍加改动就可以移植到另一个完全不同的环境中运行。这是因为标准库函数和预处理程序将可能出现的与机器有关的因素与源程序分隔开来,使得针对不同的计算机硬件环境,可以重新定义有关的内容。(8)生成的目标代码质量高。由C源程序编译和链接得到的目标代码的运行效率比用汇编语言编写的也不过只低10%~20%,可充分发挥机器的效率。(9)C语言语法限制不严,程序设计自由度大。C语言程序在运行时不做诸如数组下标越界和变量类型兼容性等检查,而是由编程者自己保证程序的正确性。C语言几乎允许所有的数据类型的转换,字符型和整型可以自由混合使用,所有类型均可作逻辑型,可自己定义新的类型,还可以把某类型强制转换为指定的类型。实际上,这使编程者有了更大的自主性,能编写出灵活、优质的程序,同时也给初学者增加了一定的难度。所以,只有在熟练掌握C语言程序设计后,才能体会到其灵活性。

可以先简单了解以上特点,等掌握C语言之后,再次阅读就会有更为深刻的领会。

C语言有许多优点,是一种优秀的计算机语言,但也存在以下的缺点。了解这些缺点,有助于实际使用C语言编写程序时做到扬长避短。(1)C语言程序的错误更隐蔽。C语言的灵活性使得用它编写程序时更容易出错,而且C语言的编译器不检查这样的错误。与汇编语言类似,需要程序运行时才能发现这些逻辑错误。C语言还会有一些隐患,需要引起程序员的重视,如将比较的“==”写成赋值“=”,虽然语法上没有错误,但是这样的逻辑错误往往不易发现,想要找出错误往往十分费时。(2)C语言程序有时会难以理解。C语言语法成分相对简单,是一种小型语言。但是,其数据类型多,运算符丰富且结合性多样,使得对其理解有一定的难度。有关运算符和结合性,人们最常说的一句话是“先乘除,后加减,同级运算从左到右”,但是相比较而言C语言的运算符及表达式更加复杂。发明C语言时,为了减少字符输入,C语言比较简明,同时也使得C语言可以写出常人几乎难以理解的程序。(3)C语言程序有时会难以修改。考虑到程序规模的大型化或者巨型化,现代编程语言通常会提供“类”和“包”之类的语言特性,这样的特性可以将程序分解成更加易于管理的模块。然而C语言缺少这样的特性,维护大型程序则显得比较困难。

1.3 计算机解题过程

使用计算机解决现实世界的问题是一种必然的选择。如何使用计算机解题?也就是如何编写解决问题的程序或软件?这是一个比较复杂的问题,需要使用软件工程的方法来解决,超出本书的范围。这里从学习C语言的角度简要认识计算机解题的过程。图1-2 计算机解题过程

计算机的解题过程如图1-2所示,大致分为4个阶段,分别是分析问题、设计算法、编写程序和运行验证。

1.分析问题

详细分析需要解决的问题,清楚地了解问题的需求。已知的原始数据有哪些,使用什么方法或数学模型,要得到什么结果。分析问题就是明确做什么(What to do)。

2.设计算法

明确了做什么之后,就需要考虑怎么做(How to do it)。通常将解决问题的方法或数学模型转换为解决问题的步骤,即设计算法。设计算法是计算机解题过程中的一个具有创造性的重要环节,所设计的算法是否合理、正确直接关系到问题能否解决。同时,解决问题的方法往往不是唯一的,可能有多种解决方法,需要设计出多种算法,通过分析比较,从中找出合适的或最优的算法。

3.编写程序

确定了解决问题的算法之后,需要使用一种计算机程序设计语言编写程序。编写程序就是将设计的算法等价映射(转换)为计算机语言的程序,所编写的程序从逻辑上看是算法的一种表现形式。

4.运行验证

编写的程序有时不能正确地满足解决实际问题的需求,还需要调试,即在计算机上运行并且排除潜在错误。必要时,还要使用测试数据对程序进行测试,验证程序的正确性。如果程序测试不充分,则有可能使得潜在的错误存在。除此之外,问题需求也可能随着时间的推移而变化,使得程序使用一段时间后还需要进行修改完善,这个过程称为维护。

1.4 算法及其表示

大型软件的开发一般采用软件工程的方法,经过分析、设计、编码、调试和运行等阶段。每个阶段都有明确的任务,后一阶段的工作是在前一阶段结果的基础上进行的。对于初学者而言,需要解决的问题和编写的程序一般比较简单,只要将问题分析清楚,找到解决问题的方法,编写程序不是一件困难的事情。

C语言解题时,在程序中有两方面的描述,即数据描述和处理步骤(算法)描述,后者处理前者的数据。因此,编写C语言程序之前,应该将问题所涉及的数据、已知条件和问题的解决步骤分析清楚。以下通过两个简单的实例来说明这一点。【例1-1】 求任意两个数的和与平均值。(1)数据描述

问题中有4个数据,即两个任意数、任意数之和与它们的平均值。在程序中定义4个浮点型变量存储这些数据,如float a,b,sum,average;。(2)处理步骤描述

第1步:输入两个任意数,存储在变量a和b中。

第2步:计算两个数之和与平均值,存储在变量sum和average中。

第3步:输出变量sum和average的值,即得到问题所要求的结果。

根据上述分析,编写程序如下:【例1-2】 某体育比赛中,有10个裁判为参赛选手打分,参赛选手最后得分的计算方法是:去掉一个最高分和一个最低分后其他分数的平均值。求参赛选手的最后得分。(1)数据描述

问题中的原始数据有10个,解题过程中需要计算最高分、最低分和最后得分。在程序中可定义一个数组s存储10个分数、三个浮点类型变量max、min、score分别用来存储最高分、最低分和最后得分,另外还需要若干辅助变量。(2)处理步骤描述

第1步:输入10个任意数,存储在数组s中。

第2步:计算10个数的最高分、最低分与它们的和,并存储在变量max、min和sum中。

第3步:从sum中减去max和min并且除以(10-2)(值为8)求得最后得分,并将其存储在变量score中。

第4步:输出变量score的值,则得到问题所要求的结果。

对于第1步和第2步还需给出更详细的步骤,以便程序实现。根据上述分析,编写程序如下:

使用计算机解题时,解题步骤归纳如下:(1)了解题目要做什么。(2)明确处理的数据及数据特征,确定处理方案。程序处理的对象是数据,程序中如何存储数据?输入的数据有哪些?输出的结果有哪些?这些都应该明确并且做到心中有数;而选择适当的处理方案(数学模型),对于设计处理步骤是至关重要的。(3)清楚地描述对数据的处理步骤——算法设计,以便得到预期的结果。算法设计是解决问题的核心,是程序的灵魂,是程序设计过程中的一个重要环节。(4)对处理步骤进一步细化——逐步求精算法,直到能够使用程序设计语言编写程序实现。算法设计和逐步求精算法是使用计算机解题过程中最为困难的一步,是唯一的有创造性的工作。(5)将算法转换为程序。将算法转换为程序是一项包含众多技巧的工作,需要完整的计算机程序设计语言与程序设计的知识。(6)运行程序,分析结果。通过对源程序进行编辑、编译和连接,得到可执行的程序,并且运行所得到的可执行程序。如果出现编译错误或运行结果不正确,则要修改源程序,重新进行编译、连接和运行,直到得到满意的结果。

对于一个复杂的问题,可以将其分解成若干个容易处理、可单独解决的子问题,然后分别加以解决。1.4.1 算法的概念

算法是精确定义的一系列规则的集合,这些规则规定了解决特定问题的一系列操作,以便在有限的步骤内产生出问题的答案。【例1-1】和【例1-2】中的处理步骤就是一种用自然语言描述的算法。【例1-3】 求两个正整数m和n的最大公约数(即同时能够整除m和n的最大正整数)。

欧几里得阐述了求两个数的最大公约数的过程——欧几里得算法。

第1步:以n除m,并令r为所得余数(显然n>r≥0)。

第2步:若r=0,算法结束,n即为m和n的最大公约数。

第3步:置m←n,n←r,返回第1步。

算法中的符号←表示将该符号右边变量或表达式的值送到左边的变量中。

算法中不仅各步骤间的顺序是重要的,在每步内的动作次序也同样重要。例如,上述算法的第3步中,“置m←n,n←r”绝对不能写成“置n←r,m←n”,因为这样做的结果是在变量m、n和r中存储了同一个值,即都变成了第1步除法运算的余数。

对于同一个问题,可以有不同的解题方法,即可以有不同的算法。如【例1-2】求参赛选手的最后得分问题,可以先将10个数排序,求中间8个数的平均值,还可以有其他方法。为了有效地解题,不但要求算法正确,还要考虑算法的质量,通常选择简单明了、结构清晰和计算高效的算法。

求解问题时,算法可以千变万化、简繁各异,但是算法必须具有以下特性。

● 有穷性:算法在执行了有限步骤之后结束,并且每一步都可以在有穷的时间内完成。

● 确定性:算法中每种操作必须有确切的含义,即无二义性。同时,无论如何算法都只有唯一的一条执行路径,即相同的输入只能得出相同的输出。

● 可行性:算法中描述的操作都可以通过已经实现的基本操作执行有限次数来实现。

● 输入:有零个或多个输入,即算法需要的必要信息。

● 输出:有一个或多个输出,输出的是与输入有某些特定关系的信息。没有输出的算法是无意义的。1.4.2 算法的表示

算法的基本组成结构有三种,即顺序结构、分支结构和循环结构。或者说,任何一个算法,无论其多么简单或多么复杂,都可由这三种基本结构组合而成。

算法有多种表示方法,常用的表示方法有:(1)自然语言描述;(2)传统流程图;(3)N-S流程图;(4)伪代码。

1.自然语言描述【例1-2】和【例1-3】介绍的算法是用自然语言描述的。自然语言可以是中文、英文、其他民族语言或数学表达式等。用自然语言描述算法通俗易懂,其缺点是文字有可能冗长,不太严格,容易产生歧义,表达分支和循环结构不方便等。

2.传统流程图

流程图是用约定的图框和流程线表示运算或操作流程的图示形式。其优点是直观形象、易于理解。美国国家标准学会ANSI规定的一些常用流程图符号如图1-3所示。图1-3 常用流程图符号

可以画出【例1-3】求最大公约数算法的传统流程如图1-4所示。图1-4 求最大公约数的传统流程图

3.N-S流程图

N-S流程图是一种结构化流程图,适合于表示结构化算法。N-S流程图完全取消了带箭头的流程线,全部算法写在一个矩形框内,框内还可以包含从属于它的框。

N-S流程图使用的流程图符号如图1-5所示,图中A和B为某种操作或功能模块,P为判断条件。(1)顺序结构:A操作和B操作按顺序进行,先进行A操作,再进行B操作。(2)选择结构:根据判断条件P是否成立,在A和B两种操作中选择一种。若判断条件P成立,选择A操作执行;否则,选择B操作执行。(3)循环结构:根据判断条件P是否成立,决定A操作是否被重复执行。C语言中的循环结构分为 while 循环(也称为当型循环)和 do-while 循环(也称为直到型循环)。while循环是先判断条件P,若成立,则重复A操作;do-while循环是先执行A操作,再判断条件P,若成立,则重复A操作。图1-5 N-S流程图基本结构

可以画出【例1-3】求最大公约数算法的N-S流程如图1-6所示。图1-6 求最大公约数的N-S流程图

4.伪代码

伪代码是一种用以表示算法的代码。伪代码采用了类似程序设计语言的语句表示算法,但是伪代码不是一种程序设计语言,不涉及程序设计的细节。伪代码表示算法不用图形符号,比使用传统流程图和N-S流程图表示算法更方便、紧凑并且易懂,便于将算法转换为各种计算机语言的程序。求最大公约数算法的伪代码(伪C语言)表示如下:

可以看出,用伪代码表示的算法与计算机程序设计语言已经很接近,很容易将其改写成计算机程序。对计算机程序设计语言比较熟悉时,使用伪代码(如伪C语言)表示算法易于转换为实际的计算机语言程序。

1.5 常用算法介绍

算法是解决问题的方法,不同的领域有不同的方法。根据问题领域的不同,算法可分为数值问题和非数值问题的算法。数值问题的算法解决传统的数学问题,如求方程解的算法和求定积分算法等。与数值问题的算法相比,计算机科学对非数值问题的算法给予了更多的重视。计算机在非数值应用领域应用十分广泛,不同的应用领域有不同的非数值问题算法,已远远超过了在数值问题方面的应用。

算法思想种类繁多,常用的算法有枚举法、递推法、递归法等。本节简要介绍这几种方法,程序设计中常常用到这些方法。1.5.1 枚举法

枚举法又称为穷举法。该方法通过逐一考察问题的所有可能解,找出问题真正的解。枚举法要求问题的可能解必须是有限的,而且这些可能解是已知的。【例1-4】 给定一个正整数,确定它的整数立方根是否存在,若存在则找出这个立方根。

问题分析:一个正整数的整数立方根如果存在,一定在0和这个数之间,而这之间正整数的个数是有限的,所以可以设计一个基于枚举法的算法。1.5.2 递推法

递推法是从已知的初始条件出发,逐次推出中间结果。在理想状态下,每递推一次,结果逐渐接近问题的最后解。

递推法在数值算法中又称为迭代法。迭代法常用于求近似解的问题,根据对前一步结果的误差的不同处理方法,迭代法又有逼近迭代和试探迭代等不同方法。数值计算要注意解的稳定性问题,即在迭代中每一步的解越来越接近真正的解,否则迭代不会成功。【例1-5】 计算一个正整数n的阶乘。

根据数学知识n!=1×2×3×…×n,为了求得n!,可以从1开始,求得1的阶乘后再求2的阶乘,再和3相乘得3的阶乘,以此类推,最后求得n的阶乘。1.5.3 递归法

一个直接或间接调用过程(或函数)自身的算法称为递归算法,一个函数如果调用自身进行计算则称该函数为递归函数。一些问题的算法描述中,递归法往往比非递归法更加简洁易懂。【例1-6】 计算一个正整数N的阶乘。

阶乘函数f的递归定义为:

f(1)=1(1!=1,N=1时)

f(N)=N×f(N-1)(N!=N×(N-1)!,如果N>1)

前一式子给出函数的初始值,初始值是非递归定义的。每个递归函数都应该给出非递归定义的初始值,否则这个函数无法计算出来。后一式子用较小自变量的函数值来表达较大自变量的函数值,在定义式的两边都引用了阶乘函数f,所以是一个递归定义。

除上面介绍的枚举法、递推法和递归法外,还有回溯法、贪婪法、分治法、动态规划法等算法,其详细内容可查阅相关参考资料。

1.6 结构化程序设计方法

编写程序如果没有一整套规范,就会造成程序可读性差、无法维护等问题。结构化程序设计方法有助于解决这个问题。对于过程性的计算机语言的程序来说,使用结构化程序方法可以提高程序的可阅读性和可修改性,提高编写程序的效率,缩短修改程序的时间。1.6.1 结构化程序设计基本思想

结构化程序设计是由E.W.Dijikstra在1965年提出的,对程序设计及软件开发产生了深远的影响。结构化程序设计以功能模块和过程设计为主,其要点如下:(1)采用自顶向下,逐步求精的程序设计方法。(2)任何程序只使用顺序、选择和循环这三种基本控制结构。

结构化程序设计要求程序中的每个功能模块是单入口和单出口的;没有死循环;没有死语句,即没有绝对不会被执行的语句。图1-7 顺序结构的程序流程

C语言提供了与三种基本控制结构相对应的语句,可以方便地编写结构化的程序。有关结构化程序设计的详细内容请参考有关的书籍和资料。1.6.2 三种基本程序结构

编写C语言程序时,应该按照结构化程序设计的基本思想设计程序,在程序中尽量使用顺序、选择和循环这三种基本结构,避免使用goto语句,避免编写的程序是多入口或多出口的。

顺序结构的程序流程如图1-7所示,选择结构的程序流程如图1-8所示,循环结构的程序流程如图1-9所示。图1-8 选择结构的程序流程图1-9 循环结构的程序流程

本章小结

本章主要介绍了以下内容:(1)C语言发展简史

简要介绍了C语言的发展历程,C语言与UNIX操作系统的关系,C语言的标准化。(2)C语言的特点

C语言的特点主要包括:简洁性,表达式简练实用,丰富的数据类型,具有低级语言的特点,结构化的语言,可移植性强,代码效率高,等等。(3)计算机解题过程

简要介绍了计算机的解题过程,包括分析问题、设计算法、编写程序和运行验证。(4)算法及其表示

介绍了算法的基本概念及4种算法的表示方法。这些算法的表示方法包括自然语言描述、传统流程图、N-S流程图和伪代码。(5)常用算法介绍

介绍了最为常用的算法,包括枚举法、递推法和递归法。(6)结构化程序设计方法

简要介绍了结构程序设计的基本思想,以及结构程序设计中的三种基本结构。

习题一

一、单项选择题

1.C语言程序是由()构成的。

A.一个main函数 B.一个main函数和一个其他函数

C.一个main函数和若干个其他函数 D.多个main函数和若干个其他函数

2.C语言程序的执行总是从()开始的。

A.main函数 B.程序的第一个函数

C.程序的第一行 D.程序的第一个语句

3.以下不是算法特性的是()。

A.有穷性 B.确定性 C.可行性 D.可读性

二、填空题

1.算法的基本结构有________、________和________三种。

2.C语言程序实际上也是一种________的表示方法。

3.C语言的特点有________、________和________等。

4.C语言的优点有________、________和________等。

5.C语言的缺点有________、________和________等。

6.常用的算法有________、________和________等。

7.用计算机语言编写程序解决实际问题的过程,通常分为若干步骤来完成。其中,分析问题的目的是明确________;设计算法的目的是考虑________。

三、应用题

1.参考【例1-1】,编写一个C语言程序,输出以下内容:

2.参考【例1-2】,编写一个C语言程序,输入三个整数,输出它们的最大值。

3.用传统流程图或N-S流程图表示下列各题的算法:(1)交换两个存储单元a和b的内容。(2)判断一个数n能否同时被3和7整除。(3)鸡兔同笼,已知鸡兔共有头50个,有脚80只,问鸡兔各有多少只。(用枚举法)

4.斐波那契数列的前两项是1,从第3项开始,每项的值是前两项的和,即该数列为1,1,2,3,5,…,求该数列的第20项。(用递推法)

第2章 C语言基本概念

本章主要内容

简单的C语言程序实例

字符集、关键字和标识符

数据类型

常量和变量

运算符、表达式、运算符的优先级和结合性

数据类型转换

本章介绍C语言的基本概念,包括数据类型、常量、变量、运算符和表达式等。基本类型数据的表示形式、变量的定义、运算符和表达式是本章的主要内容。

2.1 简单的C语言程序

学习计算机程序设计语言的目的是用这种语言编写程序,解决实际问题。掌握一种语言的最好方法除了大量阅读该语言的程序之外,就是使用它编写程序,通过编写程序熟悉语言的语法规则和语句含义,了解程序的结构,掌握编写程序的方法。首先认识若干简单的C语言程序。【例2-1】 编写一个C语言程序,输出“Hello,World”。这是一个经典C语言入门程序。

使用编辑器,将上述程序输入计算机并存储在一个文件中,再对C语言源程序文件进行编译和链接生成可执行程序,最后运行生成的可执行程序,结果如图2-1所示。图2-1【例2-1】运行结果

程序中的main是一个特殊的函数名,称为主函数。花括号及其中的内容是main()的函数体,可以由若干条语句组成,每个语句的最后有一个分号,表示一个语句结束。一个C语言程序由若干个函数组成,其中必须有唯一的main()函数。C语言程序从main()函数开始运行,main()函数中的最后一个语句执行完毕后,C语言程序的运行也就结束了。

printf()函数是C语言的标准库函数,该函数原型在标准库函数的头文件中定义,所以需要使用#includ命令加以包含。该函数将字符串“hello,world\n”输出到标准输出设备(屏幕)上。字符串中的“\n”代表换行符,即输出字符串“hello,world”后换行。【例2-2】编写程序,计算两个整数之和并且输出结果。

上述程序编译并且运行,结果如图2-2所示。图2-2【例2-2】运行结果

程序中的/*……*/称为注释,其内容用于帮助阅读理解程序,其作用是提高程序的可读性,但是没有实际的逻辑意义,不生成目标指令。该程序中的注释用来注明程序或语句的功能。程序注释也可以用来注释函数的功能、变量的用途及程序段的功能等。

main()函数体中的语句:int value1,value2,sum;,用来声明变量value1、value2和sum,变量的类型为整型(int)。C语言程序中的所有变量使用前必须预先声明。程序设计语言变量的本质是存储单元,这里声明了三个能够存储整型数据的存储单元。

函数体中还有三个含有“=”的语句。C语言中的“=”从语义上来说是赋值,即将“=”右边表达式(常量或变量是最简单的表达式)的值赋给左边的变量。

最后用函数printf()输出变量sum的值(两个整数之和)。【例2-3】 编写程序,输出两个整数中的最大值。

上述程序编译并且运行,输入“15,35 ↙”(↙是键盘上的Enter键),运行结果如图2-3所示。图2-3【例2-3】运行结果【例2-3】程序中,有两个函数:max()函数和main()函数。一个C语言程序由若干个函数组成。

程序中定义的函数max()的功能是求两个整数的最大值,其中x和y是函数max的形式参数(简称形参)。函数体中,使用if语句选择x,y中的最大值赋值给变量z,用return语句返回结果值。

函数scanf()是C语言标准库函数,用于从标准输入设备(键盘)输入数据给指定的变量。语句scanf("%d,%d",&a,&b);用来输入两个整数给变量a和b,变量前面的运算符&是取地址运算符,&a和&b分别是变量a和b的地址,要想输入数据给变量a和b,必须将a和b的地址传递给scanf()函数。需要注意的是,函数scanf()的输入格式实参"%d,%d"中含有逗号(,),输入数据时也需要输入逗号。

主函数main()中,语句c=max(a,b);的含义是,用a和b作为实际参数(简称实参),调用函数max(),得到函数max()的返回值赋值给c,即a和b的最大值赋值给c。【例2-4】 最小的C语言程序(只有一个空的main()函数)。

main(){}

虽然这是一个没有任何逻辑功能的程序,却是合法的C语言程序,它什么也不做。其他空函数的一般形式为:

func(){}

其中,func是空函数名,该函数没有任何逻辑内容,也就是什么也不做。程序中某个地方调用这样的函数时,仅仅是一种形式上的调用。这里的函数名也可以根据程序的实际需要由程序员任意命名。

编写程序过程中,定义空函数是为了形式上临时使用这个函数,以检查所编写的程序是否存在语法错误。同时使得编写的程序可以运行,这样就可以先验证空函数以外的程序逻辑是否正确,暂时不用等待那个函数的完成,可以提高编写程序的效率。等该函数实际编程完成之后再取而代之。

2.2 关键字和标识符

从语法角度来看,计算机语言程序的最小单位是字符,即程序是由字符组成的。程序是符合语法规定的字符的有序序列。这些字符除了字母、数字和标点符号之外,还可以是制表符、回车符和换行符等。

计算机语言有若干语法元素,像标识符、常量、运算符和关键字等,C语言也不例外。由语法元素构成语句,由语句构成程序。因此,C语言程序包含三个层次,它们是语法元素(也称为单词)、语句和程序。2.2.1 字符集

C语言字符集包括以下的内容:(1)字母:大写字母A~Z、小写字母a~z。(2)数字:0~9。(3)下画线:_。(4)标点符号:,(逗号)、;(分号)、"(双引号)、'(单引号)等。(5)特殊字符:+(加号)、-(减号)、*(乘号)、/(除号)、%(百分号)、=(等于号)、()(圆括号)、[](方括号)、{}(花括号)、>(大于号)、<(小于号)、!(感叹号)、\(反斜杠)、|(竖线)、Tab(制表符)、(空格符)等。

制表符、空格符、回车符和换行符等是单词的分隔符。标点符号和特殊字符也是单词的分隔符,同时自身也可能是运算符。C语言的关键字是由字母组成的,标识符是由字母、数字和下画线组成的。2.2.2 关键字

关键字又称保留字,是语言中被赋予特定含义的单词符号。ANSI C定义的关键字共32个,如表2-1所示。表2-2给出了ANSI C定义的关键字分类,其中选择语句、循环语句和控制转移关键字合起来又称为控制流关键字。

需要注意的是,不同版本或标准的C语言还会扩充相应的关键字。表2-1 ANSI C定义的关键字表2-2 ANSI C定义的关键字分类

早期的计算机语言没有规定关键字,给编译器带来了麻烦,编译器不得不采用多遍扫描源程序的方法进行编译。如果没有关键字也会给阅读理解程序带来不便和困惑,如看到单词符号“if”时,如果不阅读分析其上下文,就无法确定“if”是if语句的开始,还是一个变量。2.2.3 标识符

C语言程序中,通常需要对函数、变量、符号常量、数据类型和数组等进行命名,这些名称统称为标识符。标识符是一个具有特定规则的字符序列,用来作为这些对象的名称。需要注意,C语言中大小写字符是有区别的。

例如,2.1节中的变量名value1、value2、sum和函数名printf、max都是标识符。而max和Max不是同一个标识符。

标识符是符合以下语法规则的字符序列:(1)首字符必须是字母或下画线。(2)只能包含字符A~Z、a~z、0~9及_(下画线)。(3)标识符不能是关键字。(4)标识符不能跨行书写。

例如,以下这些字符序列是合法的C语言标识符:

abc ABC Abc buffer data1_abc filename

而以下这些字符序列则不是合法的C语言标识符:

+abc $xyz 2apple%cat

使用标识符命名程序中各种对象时,要尽量做到“见名知意”,这样的程序具有良好的可阅读性并且易于理解其程序逻辑。通常遵循以下原则来使用标识符:(1)选择具有一定意义的英文单词做标识符。例如,用day表示日期、sum表示和等。(2)适当地使用下画线。例如,用load_num表示调入数据等。(3)使用约定俗成的标识符。例如,temp表示中间变量,x、y和z表示需要计算的变量等。(4)标识符的长度不要过长。(5)用大小写区别命名。例如,loadnum和loadNum是两个不同的标识符,后者则相对易于阅读。C语言程序中,通常变量使用小写字符开头的标识符,而符号常量往往使用大写字符的标识符。

2.3 数据类型

与其他程序设计语言一样,C语言的数据类型定义了该类型数据的存储空间大小,即字节数、数据的表示形式及取值范围。C语言有丰富的数据类型,这有助于针对特定的问题需求,选用最适当的数据类型,达到节省存储和加快计算速度的目的。2.3.1 C语言的数据类型

C语言主要的数据类型有4类,分别是基本类型、构造类型、指针类型、空类型(void)。有关C语言数据类型的分类与组成,如表2-3所示。

基本类型包括:整数类型;浮点类型;字符类型;枚举类型。数值类型是整数类型和浮点类型的总称。C语言的字符类型比较特殊,也可以作为数值类型,成为算术运算的对象。

计算机程序处理的对象是数据,每一个数据有各自的数据类型。例如,123是整数类型,3.14是浮点类型,'A'是字符类型。

数据类型决定此类数据的存储空间、表示形式及取值范围。例如,有符号整数类型的数据带有一个二进制的正负符号位,通常在最左边;负整数采用补码表示;浮点类型根据精度的不同使用不同的字节数表示,其尾数部分和指数部分有各自的编码方式。数据类型决定了存储数据所需存储空间的大小、表示形式、表示范围和可参与的运算。需要注意的是,数据类型本身只是一种抽象形式,只有用它定义的变量才分配存储空间。表2-3 C语言的数据类型2.3.2 整数类型

C语言的整数类型包括有符号和无符号两类。从使用的空间字节数来看,又分为整型、短整型和长整型。C语言本身并没有规定整数类型的字节数。根据计算机系统或编译器的不同,这些整数类型使用的存储字节数是不一样的。一般情况下,计算机的字长不同,整数类型使用的字节数也不一样。表2-4给出了16位机整数类型的存储字节数和表示范围。表2-5给出了32位机整数类型的存储字节数和表示范围。不过目前16位机已经几乎没有人使用。将来随着64位机的逐渐流行,与64位机相对应的整数类型也会逐步普及使用。表2-4 16位机整数类型表2-5 32位机整数类型

C语言标准要求每一种整数类型必须有确定的数值表示范围,并且二进制位数上int类型不能比short int类型短,long int类型不能比int类型短。

声明整数变量时,signed int和int表示同样的类型,即整型;signed short int、short int和short表示同样的类型,即短整型;signed long int、long int和long表示同样的类型,即长整型。

C语言标准库头文件中定义了若干符号常量,它们的值包括各种整数类型的最大值和最小值,像SHRT_MAX、INT_MAX和LONG_MAX分别是短整数、整数和长整数的最大值。编写程序时可以使用这些符号常量。

整数类型数据之间进行算术运算,结果还是整数,仍旧应存储在整数类型数据存储单元中。例如,程序段:

运行后,变量c的值为12,小数被舍去。

整数类型的数据进行算术运算还有可能发生整数溢出的情况,运算结果如果超出了数值表示范围则产生溢出。不仅乘法运算会导致整数溢出,加法和减法运算也有可能导致整数溢出。例如,程序段:

运行后,变量c产生溢出,值为-15536,不是正确的结果。(32位机上的计算结果)

这里以16位机上C语言为例,简单介绍一下整数类型的存储形式,带符号整数类型数据在存储单元中是以补码形式存储的。整数类型的存储形式如下:

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载