收藏 分享(赏)

第二章 数据对象与计算.PDF

上传人:精品资料 文档编号:7174008 上传时间:2019-05-08 格式:PDF 页数:17 大小:320.44KB
下载 相关 举报
第二章 数据对象与计算.PDF_第1页
第1页 / 共17页
第二章 数据对象与计算.PDF_第2页
第2页 / 共17页
第二章 数据对象与计算.PDF_第3页
第3页 / 共17页
第二章 数据对象与计算.PDF_第4页
第4页 / 共17页
第二章 数据对象与计算.PDF_第5页
第5页 / 共17页
点击查看更多>>
资源描述

1、裘宗燕 从问题到程序( 2003 年修订) ,第二章 1第二章 数据对象与计算 计算机程序处理数据,写程序就是描述数据的处理过程,其中必然涉及数据的描述和计算问题。例如,在 C 程序里可以写出下面片段,这是一个表示了某种计算过程的“表达式” ,其中包含了一些“数据” ,如整数和实数等: : -(3.24 * 5 + sin(2,3) / 4 * 6.24 要理解这种表达式,写程序时知道如何写出所需表达式,就必须知道 C 语言对各种数据的写法(术语是数据的描述)有什么规定:在表达式里可以写什么?它们表示什么意思?写出的表达式表示了什么计算过程?有关计算的结果是什么?本章首先解决这些问题。 本章将

2、首先讨论 C 语言中各种基本数据的描述,然后介绍如何从基本数据元素出发描述计算,如何写好能求出所需结果的表达式。在这一章里,读者将初步接触到计算机领域的许多重要概念,看到它们在简单程序中的地位和作用。 2.1 基本字符、名字表示、标识符和关键字 一个 C 程序就是 C 语言基本字符的一个符合规定形式的序列。 C 语言基本字符包括: 1. 数字字符,0,1,2,3,4,5,6,7,8,9; 2. 大小写拉丁字母:az,AZ; 3. 其他一些可打印(可以显示)的字符(如各种标点符号、 运算符号、括号等) ,包括: !%“,.?/| 现在不必死记这些,随着学习进展,读者将很容易记住这些字符的意义和作

3、用。 4. 还有一些特殊字符,如空格符、换行符、制表符等。 空格符、换行符、制表符等统称为空白字符。空白字符在程序中主要用于分隔其他成分。 按规定, C 程序中大部分地方增加空白字符都不影响程序意义。因此人们写程序中常利用这种性质,通过加入一些空白字符,把程序排成适当格式,以增强程序的可读性。例如,在适当地方换行,在适当地方加空格或制表符。这样能使程序的表现形式更好反映其结构和所实现的计算过程。举例说,第 1 章的简单 C 程序也可以写成下面样子: #include int main()printf(“Good morning!n“);return 0; 这明显不如前面的写法清晰。对更大的程序

4、情况则会更糟糕。本书后面讨论中还会提出对各种程序成分的较好写法,书中程序示例也反映了这方面的情况。 构成 C 程序的基本成分包括各种名字(如上面出现的 main、 printf 等等) ,各种数值表示(如 125、 3.14 等等) ,各种运算符和其他符号。 名字(标识符)的构成 程序中有许多需要命名的对象。 例如, 程序中常常需要定义一些东西, 以便在各处使用。为了在定义和使用之间建立联系,表示不同位置用的是同一个对象,基本的方式就是为程序对象命名,通过名字建立起定义与使用间、同一对象的不同使用间的联系。为了这种需要,C 语言规定了名字的书写形式。程序中的名字称为标识符。 一个标识符是字母和

5、数字字符的一个连续序列,其中不能有空白字符,而且要求第一个字符必须是字母。为了方便起见, C 语言特别规定将下划线字符“ _”也当作字母看待。这就是说,下划线可以出现在标识符中的任何地方,特别是可以作为标识符的第一个字符。下面是一些标识符的例子: 裘宗燕 从问题到程序( 2003 年修订) ,第二章 2abcd Beijing C_Programming _f2048 sin a3b06 xt386ex A_great_machine Small_talk_80 FORTRAN_90 以下划线开始的标识符保留给系统使用,在我们编写普通程序时不要使用这种标识符,以免与系统内部的名字冲突造成程序问

6、题。 如果一个字符序列中出现了非字母、非数字、也非下划线的字符,那么它就不是一个标识符了(但有可能其中一部分是个标识符,例如 x3+5+y,其中 x3 和 y 都是标识符,中间的 +5+不属于这两个标识符) 。下面是一些非标识符的字符序列: += 3set a32 $ sin(2+5) :ab4= C 语言还规定,标识符中同一字母的大写形式和小写形式将看作不同字符,这样, a 和 A 不同, name、 Name、 NAME、 naMe 和 nMAE 是互不相同的标识符。 关键字 C 语言的合法标识符中有一个特殊的小集合,其中的标识符称为关键字。作为关键字的标识符在程序里具有语言预先定义好的特

7、殊意义,因此不能用于其他目的,不能作为普通的名字使用。 C 语言关键字共 32 个,列在这里: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while 现在不准备对它们做更多解释。随着书中讨论的进展,读者会一个一个地接触并记住它们。目前只需要了解关键字这一概念

8、。 除了不能使用关键字之外, 我们写程序时几乎可以用任何标识符为自己所定义的东西命名,所用的名字可以自由选择。通过长期程序设计实践,人们认识到命名问题并不是一件无关紧要的事情。合理选择程序对象的名字能为人们写程序、读程序提供有益的提示,因此人们倡导采用能说明程序对象内在含义的名字(标识符) 。 注读者注意,命名问题并不是 C 语言中特殊的东西,每种程序语言都必须规定程序中名字的形式,在计算机领域中到处都用到名字。例如,计算机里的文件和目录,各种应用程序和系统,图形界面上的图标和按钮,甚至计算机网络中的每台计算机,都需要命名。采用适当命名形式的原则在计算机领域中具有广泛适用性。 2.2 数据与类

9、型 数据是程序处理的对象。 C 语言把程序能处理的基本数据对象分成一些集合。属于同一集合的数据对象具有同样性质: 采用统一的书写形式, 在具体实现中采用同样的编码方式 (按同样规则对应到内部二进制编码,采用同样二进制编码位数) ,对它们能做同样操作等等。语言中具有这样性质的一个数据集合称为一个类型。 从关于计算机基础知识可知,计算机硬件处理的数据也分成一些类型,通常包括字符、整数、浮点数等, CPU 为不同数据类型提供了不同的操作指令。例如,对整数有一套加减乘除指令, 对浮点数有另一套加减乘除指令等。 程序语言中把数据分成类型与此有密切关系。但类型的意义不仅于此,实际上,类型是计算机科学的核心

10、概念之一。在学习程序设计和程序设计语言的过程中将不断与类型打交道。请读者特别注意这一概念。 裘宗燕 从问题到程序( 2003 年修订) ,第二章 3C 语言的基本类型包括字符类型、整数类型、实数类型等。请读者特别注意: ( 1)程序中书写的、执行中处理的每个基本数据都属于某个确定的基本数据类型; ( 2)类型确定了属于它的数据对象的许多性质,特别是确定了数据的表示范围。在具体 C 语言系统里,基本类型都有确定表示(编码)方式,这就确定了可能表示的数据范围。例如,一个整数类型中的所有整数只是数学中整数的一个子集,其中只包含有限个整数值,存在该类型能表示的最小和最大整数。其他整数在这个类型里没有容

11、身之地,无法在这个类型中表示。 下面会看到这些基本情况的影响。 2.3 基本类型与数据表示 C 语言提供了一组基本基本类型,并规定了“类型名” 。基本类型的名字由一个或几个标识符(关键字)构成,其形式与前面讲的“名字”有所不同。本节将介绍几个最常用的类型。不在这里介绍所有基本类型,是希望能尽快进入讨论的主题程序与程序设计。这几个基本类型对前几章也足够了。后面章节将对所有基本类型做全面的介绍。 首先应提出文字量的概念。文字量就是程序里直接写出的数据。例如,程序里直接写出的整数类型的数据就称为“整型的文字量” 。为简单起见,也常把整型文字量简称为“整数” ,其他情况也采用类似称呼方式,后面常用这种

12、简称,只在特别需要时才用更严格的说法。 C语言规定了各种基本类型的文字量的书写形式,这也是本节的主要内容。 2.3.1 整数类型和整数的表示 C 语言提供了多个整数类型以适应不同需要。 不同整数类型间的差异在于它们可能具有不同的二进制编码位数,因此表示范围可能不同。程序中用的最多是一般整数类型(今后简称为“整数类型”或“整型” )和长整数类型(简称“长整型” ) 。整数类型的类型名是 int;长整型的类型名为 long int,可简写为 long。 int 和 long 都是关键字。 整数表示 整数( int 类型的文字量)有几种书写形式,程序中的整数一般采用十进制写法。用十进制方式写出的一个

13、整数就是普通数字字符组成的一个连续序列,其中不能有空格、换行或其他字符。 C 语言规定十进制表示的数字序列的第一个字符不是 0,除非要写的整数本身就是 0。下面是一些整数的例子: 123 304 25278 1 0 906 由于长整数是另一个不同类型, C 语言为长整数规定了一种专门写法,其特殊之处是在表示数值的数字序列最后附一个字母 l 或 L 作后缀。由于小写字母 l 容易与数字 1 混淆,建议读者总采用大写的 L。下面是一些长整数的例子: 123L 304l 25278L 1l 0L 906L 表示范围 C 语言没有规定各种整数类型的表示范围,也就是说,没有规定各种整数的二进制编码长度。

14、对于 int 和 long,只规定了 long 类型的表示范围不小于 int,但也允许它们表示范围相同。具体 C 语言系统则会对整型和长整型规定明确表示方式和表示范围。例如,早期微型机的一些 C 系统采用 16 位二进制表示的整数(一个 int 占 2 个字节)和 32 位表示的长整数(一个 long 占 4 个字节) 。这样,整型的表示范围就是 -32768 到 32767,即22115 15L。长整型表示范围是 22131 31L。在许多新的微机 C 语言系统里,整数( int)和长整数( long int)都采用 32 位的二进制数表示。 C 语言允许在整数的前面写正负号,加上负号的整数

15、就是表示负整数。 裘宗燕 从问题到程序( 2003 年修订) ,第二章 4整数的八进制书写法和十六进制书写法 整数与长整数都可以采用八进制或十六进制的形式书写。 用八进制形式写出的整数( int 类型的文字量)是由数字 0 开始的连续数字序列,在序列中只允许 0 7 这八个数字。下面是用八进制写法写出的一些整数和长整数: 0236 0527 06254 0531 0765432L 整数的十六进制形式是由 0x 或 0X 开头的数字序列。由于数字只有 10 个,而在十六进制写法中需要 16 个数字, C 语言采用计算机领域通行的方式,用字母 a f 或 A F 表示其余的 6 个十六进制数字,其

16、对应关系是: 字母: a,A b,B c,C d,D E,E f,F表示的数字: 10 11 12 13 14 15下面是用十六进制形式写出的一些整数和长整数: 0x2073 0xA3B5 0XABCD 0XFFFF 0XF0F00000L 请注意:八进制、十进制和十六进制只是整数的不同书写形式,提供多种写法是为了编程方便,使人可以根据需要选择适用的书写方式。无论采用八进制写法还是十六进制写法,写出的仍是某个整数类型的数,并不是新的类型。用八进制、十六进制形式写长整数时,同样需要用后缀 l 或者 L。 日常生活中人们习惯于用十进制的形式书写整数。 C 语言提供八进制和十六进制的整数书写方式,也

17、是为了写程序的需要。在写复杂程序时,有些情况下用八进制和十六进制更方便些,后面会看到这方面例子。 2.3.2 实数类型和实数的表示 实数类型 C 语言提供了三个表示实数的类型:单精度浮点数类型,简称浮点类型,类型名为 float;双精度浮点数类型,简称双精度类型,类型名为 double;长双精度类型,类型名为 long double。这些类型的文字量也分别称作“浮点数” 、 “双精度数”和“长双精度数” 。所有整数类型和实数类型统称为算术类型。 实数的计算机内部表示由具体系统规定,其中不少系统采用通行的国际标准( IEEE 标准, IEEE 是电子电器工程师协会,是一个著名的国际性技术组织)

18、: 1. 浮点类型的数用 4 个字节 32 位二进制表示。 这样表示的数大约有 7 位十进制有效数字,数值的表示范围约为 (. . )34 10 34 1038 38L; 2. 双精度类型的数用 8 个字节 64 位二进制表示,双精度数大约有 16 位十进制有效数字,数值的表示范围约为 (. . )17 10 17 10308 308L; 3. 长双精度类型的数用 10 个字节 80 位二进制表示,大约有 19 位十进制有效数字,其数值的表示范围约为 (. . )12 10 12 104932 4932L。 显然,每个实数类型能表示的数也只是数学中实数的一个小子集合,不仅表示范围有限,表要用某

19、计算机上的某个 C 语言系统编程,要做的一件事就是查清该系统里各种整数类型的表示范围。有关情况可以从系统使用手册中查到,或查看介绍该系统的书籍,或查看系统的联机帮助。此外,还可以查看这个 C 系统中名字为 limit.h 的文件。这是每个 C 语言系统都有的一个标准文件,其中列出了各种情况的具体规定。 对于浮点数也有类似情况。例如,在一些 C 语言系统里, long double 采用与double 同样的表示方式。有关具体 C 语言系统中浮点数表示的情况,也应查阅系统手册,还可以查阅名为 float.h 的标准文件。 裘宗燕 从问题到程序( 2003 年修订) ,第二章 5示的精度(数的有效

20、数字位数)也有限,请读者注意这些情况。 实数的写法 C 语言中最基本的实数类型是双精度类型。 双精度数的书写形式中的基本部分是一个数字序列,在序列中或者包含了一个表示小数点的圆点“ .” (可以是第一个或最后一个字符) ,或者在表示数值的数字序列后面有一个指数部分。指数部分是以 e 或 E 开头的另一(可以包括正负号的)数字序列,指数以 10 为底,这种形式称为科学记数法。也可以既有小数点,又有指数部分。下面是一些双精度数的例子: 3.2 3. 2E-3 2.45e17 0.038 105.4E-10 304.24E8 下面是其中一些双精度类型类型的文字量(双精度数)与它们所表示的实数的对照表

21、: 双精度数 所表示的实数值 2E-3 0.002 105.4E-10 0.00000001054 2.45e17 24,5000,0000,0000,0000.0 304.24E8 304,2400,0000.0 浮点数( float)类型数的写法在与双精度数类似,只是在数最后应附后缀字符 f 或者 F。表示长双精度数的后缀是 l 和 L。下面是一些浮点数类型和长双精度类型数的例子: 13.2F 1.7853E-2F 24.68700f .32F 0.337f 12.869L 3.417E34L .05L 5.E88L 1.L 负实数同样通过在数前加负号表示。 2.3.3 字符类型和字符的表

22、示 字符类型数据主要用于程序的输入输出。此外,文字处理也是计算机的一个重要应用领域,该应用领域的应用程序必须能使用和处理字符形式的数据。由于大部分程序都需要与人打交道,需要接收人的输入信息(例如人给程序发的命令,或者提供的数据) ,还需要给人输出信息,因此字符类型的数据在程序中的使用很广泛。 最常用的字符类型的类型名是 char。字符类型的数据值包括本计算机所用编码字符集中的所有字符。 目前微机和工作站常用 ASCII 字符集, 其中的字符包括所有大小写英文字母、数字、各种标点符号字符,还有一些控制字符,一共 128 个。扩展的 ASCII 字符集包括 256个字符。字符集的所有字符都是字符类

23、型的值。在程序执行时,其中的字符就用对应的编码表示,一个字符通常占用一个字节。 字符文字量的书写形式是用单引号括起的单个字符,例如 1、 a、 D等。一些特殊字符无法用这样写出,例如换行字符等。 C 语言为它们规定了特殊写法。下面是几个最常用的特殊字符的写法: 换行字符 n 双引号字符 “ 单引号字符 反斜线字符 这里的写法都是在单引号里面先写一个反斜线字符( ) ,后面再写一个字符。在这种写法中,反斜线字符的作用就是表明它后面的字符不取原来意义。这样连续的两个字符(或更多几个字符) 称为一个换意序列, 用于表示无法写出的字符。 反斜线字符在其中起着特殊作用,它也被称为换意字符。还有些特殊字符

24、也有特别规定的写法,附录列出了所有特殊字符的写法,还说明了采用八进制和十六进制编码形式写字符的方式。 这里需要强调两点。 1. 字符数据与标识符不同。例如 x 和 x是两种完全不同的东西,后者表示一个数据项,是程序处理的对象;前者则是程序描述中所用的一个名字,它可能代表程序里的某个东裘宗燕 从问题到程序( 2003 年修订) ,第二章 6西。显然它们不在同一个层次上。 2. 数字字符和数不同。例如 1 和 1,前者是一个整型文字量,是一个 int 类型的数据对象,其存储要占据 int 所规定的那么多单元。在常见的微机 C 系统里,它可能占了2 个或 4 个字节,其中存着整数 1 的二进制编码。

25、而 1是个 char 类型的数据,其存储通常占一个字节,其中存着字符 1的编码(在 ASCII 码中 1的编码是 49) 。 C 语言的一个特殊规定是把字符看作一种特别短的整数, 允许程序中直接用字符的值参与算术运算,这方面的情况将在后面讨论。 字符串 字符串是 C 程序里可以直接写出来的另一类数据,其形式是用双引号括起的一系列字符。下面是几个字符串的例子: “CHINA“ “Beijing“ “Daxue“ “Welcomen“ 在字符串里的特殊字符也用换意序列的形式书写, 例如上面第四个字符串的最后是一个换意序列,表示了一个换行字符。 程序中的字符串主要用于输入输出,在第一章的简单 C 程

26、序里有下面一行: printf(“Good morning!n“); 圆括号里就是一个字符串。 C 语言规定程序不能在字符串中间换行,否则编译会出错。 2.3.4 数据的外部表示、内部表示与转换 数据的外部表示指的是人在写出的 C 语言源程序中写数据所用的形式、或者人给正在运行中的程序提供数据时所用的形式、或者人从程序中得到的输出所具有的形式。内部表示指程序运行中,各种数据在计算机内部的二进制编码形式,也就是计算机内部存储和处理数据时所用的形式。显然这是两种不同形式。例如: 外部形式 内部形式 整数 十进制(或其他进制)的数字字符序列 整数的二进制编码 字符 字符本身 相应的二进制编码(常用的

27、 ASCII 编码)举例来说,如果我们在源程序里写整数 123,而在程序运行时实际使用的则是存在内存某(几)个单元里的二进制形式 1111011。如果在程序里写字符 a,程序运行中将会把字符a 的编码的二进制形式保存在计算机里的某个地方。 由于同样数据在外部和内部具有不同表示形式,在源程序编译时,或者在程序运行中执行输入输出时,都需要做两种不同形式间的转换。编译时的转换由编译程序完成, C 语言对程序中各种数据的书写形式都做出了严格规定(参见前面讨论的文字量) ,只要写程序的人按规定形式写数据,编译过程中就能将它们正确转换为内部形式,供程序内部使用。在 C程序的输入输出过程中的数据形式转换,则

28、需要在程序里明确写出来。 现在先讨论输出中的数据转换,介绍如何描述输出动作。由于每个程序都需要输出,写程序时要解决的一个问题就是写输出操作,指定在输出过程中数据的转换方式。 C 语言定义了标准库,每个具体的 C 系统都提供了标准库功能。标准库提供了许多常用函数,供在写程序的人使用。标准函数里有一个名字是 printf 的常用输出函数(函数名也是标识符) ,在第一章的简单程序里就用到它。函数 printf 的功能是把一些信息送到标准输出,一般是送到显示器。 printf 的使用形式是: printf(格式描述串, 其他参数); 具有这种形式的程序片段被称为一个语句。每个语句最后有一个分号,这是语

29、句的一部分,不能缺少。按上面形式写出的语句可看作是一个输出语句,语句中使用了标准库的输出函数裘宗燕 从问题到程序( 2003 年修订) ,第二章 7printf,函数名后面括号里面的描述称为函数的实际参数。 每个函数都明确规定了自己的使用方式,只有符合规定的使用才能得到正确结果。如果不遵循函数的使用规定,写出的程序或者是编译时不能通过,编译程序指出程序有错误,或者编译结果产生的程序不能正确执行。 要使用函数 printf,除了写出函数名外,还要写一对圆括号,其中给出函数所要求的参数。格式描述串是一个字符串(双引号括起来的字符序列) ,其他参数应与格式描述相匹配(下面介绍) ,可以有一个或几个,

30、也可以没有。不同参数间用逗号分隔。 如果格式描述串中没有特殊字符 %,那么该输出语句里就不该有其他参数,也不需要表示分隔的逗号,这是使用 printf 的最简单形式。这样一段函数名、括号及其中的实际参数表示了对函数 printf 的一次使用。这种形式的输出语句的作用就是输出格式描述串本身。第一章例子写了语句“ printf(“Good morningn“);” ,它的执行将输出: Good morning 作为另一个例子,程序在执行下面语句时: printf(“WelcomentonBeijing!n“); 将输出三行字符: Welcome to Beijing! 请注意,上面格式描述串里包含

31、了三个换行字符,它们也都被输出了。 我们常说使用 printf 的语句实施的是对函数 printf 的一次调用。下面简单程序里三次调用函数 printf,它产生的输出与上面一个例子相同: #include int main() printf(“Welcomen“); printf(“ton“); printf(“Beijing!n“); return 0; 在格式描述串中起特殊作用的是以百分号字符( %)开始的,若干字符构成的序列。这种序列称为转换描述,其作用就是指明与之相对应的其他参数的转换和输出方式。函数printf 的一般调用形式是: printf(格式描述串, 其他参数1, ., 其他

32、参数k); 它可以有任意多个其他参数, 但要求格式描述串中转换描述的个数与其他参数的个数互相匹配(简单情况是个数相同,更详细的情况见第八章的有关讨论) 。这样,每个转换描述对应于一个其他参数,说明该参数的输出形式(转换方式) 。下表列出了程序中最常用的几个转换描述,它们所指定的转换,以及与其对应的其他参数应该具有的类型: 转换描述 实现的转换 对应参数的类型 %d 将参数按整数形式转换输出 对应参数应是 int 类型 %ld 将参数按长整数形式转换输出 对应参数应是 long 类型 %f 将参数按带小数点数形式转换输出 对应参数应是 double 类型 %Lf 将参数按带小数点数形式转换输出

33、对应参数应是 long double 类型 %c 输出一个字符 对应参数应表示字符的编码 %s 输出一个字符串 对应参数应该是一个字符串 一个格式描述串通常由一些普通字符和几个转换描述按某种所需顺序构成, 所有普通字符形成了实际输出的框架, 这些字符都将被正常输出, 只是在那些原来写着转换描述的地方,实际输出时将用其他参数经过转换得到的结果替代,形成最终输出。前面例子里的裘宗燕 从问题到程序( 2003 年修订) ,第二章 8“ printf(“Welcomen“);”不含转换描述,因此将输出 Welcome 和一个换行。 语句: printf(“%d + %d = %dn“, 2, 3, 5

34、); 的格式描述中包含转换描述,执行它时将形成一行输出: 2 + 3 = 5 这一输出的框架由 “%d + %d = %dn“提供,它说明输出的形式:首先输出对后面的第一个参数按整数的形式转换而得到的东西(这里就是 2) ,然后是一个空格、一个加号、另一个空格,然后是第二个参数按整数形式转换而得到的东西、。这样,当程序执行到这个语句时,就产生了上述输出。 下面是另一个例子: printf(“len:%f, width:%f, area:%fn“, 2.2, 3.5, 7.7); 这个语句的执行将输出: len:2.200000, width:3.500000, area:7.700000 注意

35、,参数和转换描述间按位置一一对应,分别转换。这里需要特别强调在格式描述串中的转换描述和它所对应的参数在类型上的一致性。如果这两者在类型上不一致,就无法保证得到正确的输出结果,甚至还可能引起更严重的程序运行错误。另一个问题是要保证格式描述串里转换描述个数和其他参数个数之间的一致性,否则也是一种错误。这种错误引起的后果是无法预料的(这一说法意味着可能产生很严重的后果) 。 初学者常常遇到这种情况:写好了一个程序,但程序的输出结果却不正确。仔细检查程序中的计算过程,怎么也找不出错误。经过许多努力,最后发现是有关输出的语句中格式转换描述与对应参数不匹配。这种情况值得读者特别注意。 如果在程序里使用 p

36、rintf,程序在最前面就应当包括行: #include 这个行的作用是告诉编译程序,在本程序中使用了 C 标准库里的输入输出函数,要求编译程序正确处理输出函数的使用。这种行的细节意义将在后面章节里讨论。 2.4 运算符、表达式与计算 了解了基本数据的描述后,现在就可以讨论计算过程的描述问题了。在 C 语言程序里,描述计算的最基本结构是表达式,表达式由被计算的对象(例如文字量,后面将会介绍更多的基本计算对象)和表示运算的特殊符号按照一定的规则构造而成。 描述数据运算的特殊符号称为运算符, C 语言里的运算符大都由一个或两个特殊字符表示(有个别例外) 。本节将讨论各种算术运算符的形式和意义,介绍

37、如何用它们构造算术表达式。讨论中还要介绍一些与运算符、表达式和表达式所描述的计算有关的重要问题,理解这些问题,对于正确描述所需计算的表达式都非常重要。 2.4.1 算术运算符 算术运算符一共有 5 个,它们是: 上面讨论中提到标准输出,请读者回忆一下计算机基础知识中关于操作系统标准 输入和标准输出的概念,在 DOS、 UNIX 等各种操作系统中都有这些概念,送到标准输出的信息通常将被自动送到计算机的显示屏幕,使我们可以在屏幕上看到这些输出。在Windows 等图形用户界面的系统里, 程序送到标准输出的信息可能被显示在一个窗口中。此外,许多操作系统都允许将送到标准输出的信息重新进行定向( DOS

38、、 UNIX 系统都支持用户这样做) 。因此可以通过这种机制把送到标准输出的信息转送到任何其他地方,例如送到某个文件里,直接送到打印机等等。 裘宗燕 从问题到程序( 2003 年修订) ,第二章 9运算符 使用形式 意义 + 一元和二元运算符 一元表示正号,二元表示加法运算 - 一元和二元运算符 一元表示负号,二元表示减法运算 * 二元运算符 乘法运算 / 二元运算符 除法运算 % 二元运算符 取模运算(求余数) 一元运算符就是只有一个运算对象的运算符,运算对象写在运算符后面。二元运算符有两个运算对象,分别写在运算符两边。在上面的算术运算符中, + 和 - 同时作为一元和二元运算符使用,其他都

39、是二元运算符。对表达式里的某个 + 或 运算符,根据其出现位置的上下文总可以确定它是作为哪种运算符使用的。取模就是求余数,例如 17 对 5 求余数的结果是 2。取模运算符只能用于各种整数类型,其余运算符可用于所有算术类型。 2.4.2 算术表达式 算术表达式由计算对象(例如数值的文字量等) 、算术运算符及圆括号构成,其基本形式与数学上的算术表达式类似。下面是两个表达式的例子: -(28 + 32) + (16 * 7 - 4) 25 * (3 - 6) + 234 对属于同一类型( int、 long、 float、 double 或 long double)的一个或两个数据使用算术运算符,

40、计算结果仍然是该类型的值。例如: 3 + 5 算出整数类型的 8, 3L + 5L 计算出长整数值 8,而 3.2 + 2.88 计算出一个双精度值。在写表达式时,为清晰起见,可以在运算对象和运算符之间适当地加一个空格。这种空格并不影响程序的意义。 例 :写程序计算半径为 6.5 厘米的圆球的体积。 根据前面有关简单 C 程序的说明,表达式的写法,以及 printf 的使用形式,我们很容易写出下面的简单程序: #include int main() printf(“V = %fcm3n“, (3.1416 * 6.5 * 6.5 * 6.5) * 4.0 / 3.0 ); return 0;

41、这个程序经过加工之后,运行时将输出计算结果: V = 1150.349200cm3 从这个例子里也可以可以看到格式描述串的作用,它给出了输出的框架。程序最前面写了 #include,表示程序里使用了标准输入输出函数 printf。 这一程序示例也表示了一种最简单的计算程序的模式,将其中的表达式换成其他表达式, 就可以完成各种算术表达式的计算了。 还可以根据需要写格式描述串, 描述输出的形式。写这种程序时,请特别注意表达式计算出的结果的类型(例如,是 int 还是 double) ,相应格式串中的转换描述必须与之对应, 否则就是程序错误。 例如, 下面程序里就有一个错误,我们无法保证这一程序能给

42、出什么结果,甚至不知道它是否会导致系统崩溃。请设法找出这个程序里的错误,但不要去试验这个错误程序: #include int main() printf(“Factorial of %d is %fn“, 7, 1*2*3*4*5*6*7); return 0; 裘宗燕 从问题到程序( 2003 年修订) ,第二章 102.4.3 表达式的求值 表达式的计算过程又称表达式求值。表达式的意义就是它所求出的值。一个表达式可能很复杂,其中可能有多个运算符,这时该表达式将确定什么样的计算过程?或者说,其中的运算符将按照怎样的顺序计算?程序语言必须对此做出明确规定。 C 语言对表达式求值的规定包括几个方

43、面:运算符优先级的规定,运算符的结合方式的规定,运算对象求值顺序的规定,以及括号的意义。下面分别介绍这几个问题。 优先级 小学生学算术就知道先乘除后加减,也就是说,乘除运算符具有更高优先级,在计算中应先做。 C 语言里有很多运算符,它为每个运算符规定了一个优先级。当不同的运算符在表达式里相邻出现时,具有较高优先级的运算符应比具有较低优先级的运算符先行计算。算术运算符被放在三个不同的优先级上: 运算符: 一元 + 和 - * / % 二元 + 和 -优先级: 高 中 低 这样,在下面表达式里加法将会最后做: 5 / 3 + 4 * 6 / 2 这与数学中的规定相符。 结合方式 仅靠优先级,上面例

44、子里子表达式 4 * 6 / 2 的计算方式仍没有确定,因为其中相邻的乘除运算符具有相同优先级。结合方式解决这类问题,它确定具有相同优先级的运算符相邻出现时表达式的计算方式。 C 语言规定一元算术运算符自右向左结合;二元算术运算符自左向右结合,优先级相同时左边的运算符先计算。这样,在上面的例子里就将先计算 4 * 6,而后再用它们的计算结果去除另一个运算对象 2。此外, -+-8 还是计算出 8。这一规定也符合数学习惯。 括号 括号供人明确地描述表达式中的计算顺序。如果用括号括起表达式中的某个部分,括号里面的表达式将先行计算,得到的结果再参与括号外面的其他计算。例如,下面表达式里各步骤的计算顺

45、序都已经完全确定了: -(2 + 6) * 4) / (3 + 5) 括号使人用于控制计算过程的一种手段。 如果直接写出的表达式所产生的计算顺序不符合需要,就可以通过加括号的方式,强制程序去执行所需要的特定计算顺序。 运算对象的求值顺序 虽然有了上述规定,计算过程中仍有些事情没有完全确定。请看下面表达式: (5 + 8) * (6 + 4) 显然,子表达式 (5 + 8)和 (6 + 4)的计算应先完成,然后才能去做乘法。但两个运算对象 (5 + 8)和 (6 + 4)中哪个先算呢?这也就是问乘法运算符的两个运算对象(更一般性的问题是各种二元运算符的两个运算对象)的计算顺序问题。 C 语言对算

46、术运算符的这一问题没有明确规定。这样,有的 C 系统可能先算左边对象,另一 C 系统可能先算右边对象,甚至可以有这样的 C 系统,其中有时先算左边的对象,有时先算右边的对象。 应当这样理解 C 语言的规定:在写程序时,不应写那种依赖于特殊计算顺序的表达式,因为我们无法保证它在各种系统里都能算出所希望的结果。显然,在上面例子中,运算对象的求值顺序不会影响结果。但是读者不久就会看到一些对求值顺序敏感的表达式。根据上面的讨论,程序里不应该写对求值顺序敏感的表达式。 裘宗燕 从问题到程序( 2003 年修订) ,第二章 11运算对象的求值顺序问题是程序语言中的特殊问题,在数学里不存在这种问题。从这里读

47、者也应该看到计算机与数学的不同。 了解了上面这些规定,在需要描述计算过程时,我们就可以写出正确的表达式了。还应提出一点:如果表达式很复杂,有时加入一些括号对读表达式的人有利,即使这些括号并不必要。此外,如果一个表达式很长,一行无法写完时也可以换行。多行书写的表达式也应采取某种对齐方式,以利于人的理解,出现错误也容易发现和改正。 2.4.4 计算和类型 由于参与计算的数据都有类型,计算过程中自然会出现许多与类型有关的问题。下面介绍其中的一些重要问题。 类型对计算的限制 两个 int 类型的数据经过计算,得到的还是 int 类型的结果。对长整数类型、各种实数类型,情况也一样。这个事实将带来许多后果。 首先, int 类型(以及 long 类型)数据的除法是整除,计算得到的商仍为整数,余数将被丢掉。这种情况有时会带来一些容易迷惑人的结果,例如下面两个表达式: 1 / 3 * 3 和 1 * 3 / 3 计算得到的结果不同,前一个表达式算出的值是 0。对所有整数类型都有这个问题,在写程序时必须注意。下面程序也不能正确算出平均值: #incl

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报