第2节结构和表达式

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第二讲 顺序结构与表达式
【温故知新】
0.1巩固练习
已知:a,b 是整型变量,c是实型变量,对于以下各组输入,执行 readln(a,b,c)后的结果为: A.正常输入 B.出错 C.等待输入
选择答案,并说出理由:
(1)41 37 7 答案: 理由:
(2)41 37 答案: 理由:
(3)41.0 37 7 答案: 理由:
(4)41 37 0.7 答案: 理由:
(5)41 3 0.7 33 答案: 理由:
(6)’41’ 3 0.7 答案: 理由:
0.2温故知新
在上一讲中,我们试着编写了输出两个自然数相除的商和余数、编程计算半径为 R 的圆的面积和周 长等程序。

我们回顾一下当时编程的过程:首先我们在 FP 的编辑区中输入程序,然后按 Alt+F9 编译, 很遗憾我们看到了一些错误信息(这个时候的错误我们称为语法错误),于是我们再重新进行编辑、编译; 编译通过后,我们按Ctrl+F9 运行程序,在“输出两个自然数相除的商和余数”中,如果输出的结果不正 确,那么我们要对程序进行调试(静态调试或动态调试) ,找到问题后再编辑、编译、运行,……,直到 完全正确为止,这时一个程序就完成了。

用图表示如下:
图2.1 程序的编写过程
{
Give two natural number A and B,write the quotient and the remainder of A divided by B. }
program shangyu;
var
a,b,c,d: integer;
begin
readln(a,b);
c:=a div b;
d:=a mod b;
writeln('shang=',c);
writeln('yu=',d);
end. {
R is radius of a circle,write the girth and the area of the circle.
}
program yuan;
var
r,s,c: real;
begin
readln(r); // 输入半径r
s:=pi*r*r; // 计算s=πr^2(π用pi常量表示) c:=2*pi*r; // 计算圆周长c=2πr
Writeln('s=',s);// 输出结果s,c
Writeln('c=',c);
end.
在上面的程序中,已体现出处理问题步骤、思路的顺序关系,这就是顺序结构程序。

在下一节中,我 们将通过几个例题来体会顺序结构的程序设计。

2.1 顺序结构程序设计
2.2.1 顺序结构程序设计
程序共有顺序结构、分支(选择)结构、循环结构三种基本结构以及函数和过程。

本节将通过几个例 题来体会程序的顺序结构和程序设计的过程。

【例 2.1】分钱游戏。

【试题描述】
甲、乙、丙三人共有 24 元钱,先由甲分钱给乙、丙两人,所分给的数与各人已有数相同;接着由乙 分给甲、丙,分法同前;再由丙分钱给甲、乙,分法亦同前。

经上述三次分钱之后,每个人的钱数恰好一 样多。

求原先各人的钱数分别是多少?
【试题分析】
设甲、乙、丙三人的钱数分别为 A,B,C。

用倒推(逆序)算法, 从最后结果入手,按反相顺序,分 步骤推算出每次各人当时的钱数:(在每个步骤中,各人钱数分别存在 A、B、C中) 步骤①: A=8 B=8 C=8 {这是最后结果的钱数,三人都一样多 }
步骤②: A=A/2 (=4)B=B/2 (=4)C=A+B+C(=16) { A,B 未得到丙分给的钱时,只有 结果数的一半;C应包含给A,B 及本身数三者之和 }
步骤③: A=A/2 (=2)C=C/2 (=8) B=A+B+C(=14) {A,C 未得到乙分给的钱时, 只有已有数的一半;B应包含给A,C及本身数三者之和 }
步骤④: B=B/2 (=7)C=C/2 (=4) A=A+B+C(=13) {C 未得到甲分给的钱时,只有 已有数的一半;A 应包含给 B,C 及本身数三者之和 }
注释:
{对应于步骤①} {对应于步骤②} {对应于步骤③} {对应于步骤④} {输出}
步骤⑤: 输出 A (=13)B (=7)C (=4){此时的 A ,B ,C 就是三人原先的钱数 } Pascal 源程序:
program ex2.1;
par a ,b ,c : integer ; begin
a :=8;
b :=8;
c :=8;
a :=a div 2;
b :=b div 2;
c :=a +b +c ; a :=a div 2; c :=c div 2; b :=a +b +c ; b :=b div 2; c :=c div 2; a :=a +b +c ;
writeln ('a=',a ,' ': 4,'b=',b ,' ': 4,'c=',c ) ; end .
细心观察,会发现本程序语句的顺序很关键。

此例用反推顺序(逆序),按步骤正确推算出各变量的值。

当然,有的问题可按正序步骤编程,这类程序都称为顺序程序。

本程序Writeln 语句的输出项含有(' ' : 4 ),是输出 4 个空格(即空格项占 4 格)。

【例 2.2】鸡兔同笼问题 【问题描述】
有鸡兔同笼,头 30,脚 90,究竟笼中的鸡和兔各有多少只? 【试题分析】
设鸡为 J 只,兔为 T 只,头为 H ,脚为 F ,则:
J+T=30
① 2*J+4*T=90

解此题暂不必采用数学上直接解方程的办法,可采用“假设条件与逻辑推理”的办法:
假设笼中 30 个头全都是兔,那么都按每头4只脚计算,总脚数为(4*H),与实际脚数 ( F )之差为 (4*H­F),如果这个差=0,则笼中全是兔(即鸡为0 只);如果这个差值 >0,说明多计算了脚数,凡是 鸡都多给算了两只脚,用它除以 2 就能得到鸡的只数,处理步骤为:
① J=(4*H­F)/2 {先用脚数差值除以2算出鸡的只数} ② T=H­J {再用总头数减鸡数算出免的只数} 按此方法,这两步运算必须注意先后顺序才会符合运算逻辑。

Pascal 源程序:
program Ex2.2;
const H =30;{常量说明 }
F =90;
var J ,T : byte ; begin
J :=(4*H ­F ) div 2; {整除运算 } T :=H ­J
writeln ('J=',J ,' ': 6,'T=',T ) ; end .
本程序中 H ,F 为常量,变量 J ,T 为 byte 类型,属于整数类型。

【例 2.3】交换两个变量的值:由键盘输入两个正整数 A 和 B ,编程交换这两个变量的值。

【试题分析】
方法一:使用中间变量 C 。

我们把变量 A 和 B 想象成交换两盒录音带的 内容,按以下步骤处理:
步骤①:拿一盒空白录音带 C 为过渡,先将
A 翻录至 C ;
步骤②:再将 B 翻录至 A ; 步骤③:最后将 C 翻录至 B 。

Pascal 源程序:
program e x2.3_1; var A ,B ,C : integer ; begin
write (‘A ,B =’); readln (A ,B ); C := A ; {等价于步骤1} A := B ; {等价于步骤2} B := C ; {等价于步骤3} writeln (‘A ,B=’,A ,’,’,B ); end .
优点:易于理解;
缺点:增加了一个变量的空间。

体育的奥林匹克追求的是——“更快、更高、更强” ,信息学的奥林匹克追求的是——“更快、更少、 更强” :时间上越快越好,空间上越少越好,程序健壮性越强越好。

【试题拓展】不使用中间变量,交换两个变量的值
下面我们来思考:这个程序能不能不使用中间变量 C 实现交换变量 A 和 B 的值。

方法二:不使用中间变量C
Pascal 源程序:
具体数据分析: program ex2.1_2;
var a ,b ,c :integer ; begin
write (‘A ,B =’); readln (a ,b ); a :=a +b ; b :=a ­b ; a :=a ­b ;
writeln (‘A ,B=’,A ,’,’,B ); end .
设a=2,b=3;则:
1、执行语句a :=a +b ;后a=a+b=2+3=5;
此时a=5,b=3;
2、执行语句b :=a ­b ;后b=a­b=5­3=2;
此时a=5,b=2;
3、执行语句a :=a ­b ;后a=a­b=5­2=3;
此时a=3,b=2;
其他方法:
对于交换两个整数 A,B 值的问题,方法二的优化减少了一个中间变量,实现了“更少”的要求;一 般而言,计算机在执行位运算的速度比执行整数运算速度要快,尤其对整数乘以 2 和除以 2 取商(div) 运算时,位运算的优势显得更为明显。

下面我们用位运算的方法来实现方法二的程序:
Pascal 源程序 具体数据分析:
program ex2.1_3;
var a,b,c : integer;
begin
write(‘A,B=’);
readln(a,b);
a:=a xor b;
b:=a xor b;
a:=a xor b;
writeln(‘A,B=’,a,’,’,b); end.设a=2,b=3;对应二进制为:a=0000 0000 0000 0010,b=0000 0011则:
1、执行语句a:=a xor b;后a=0000 0000 0000 0001;此时a=1,b=3;
2、执行语句b:=a xor b;后b=0000 0000 0000 0010;此时a=1,b=2;
3、执行语句a:=a xor b;后a=0000 0000 0000 0011;此时a=3,b=2;
integer 是有符号整数,在计算机中用 16 个二进制位表示,最高位即最左边的 1 位表示符号:0 表 示正数,1表示负数。

xor 为对两个二进制数进行异或运算。

异或运算遵循如下的规则:
XOR 0 1
0 0 1
1 1 0 即:0 xor 0=1;0 xor 1=1。

1 xor 0=1;1 xor 1=0。

异或可形象的理解为:将两个二进制位相加模 2的值。

例如 1 xor 1 可以理解为:
(1+1)mod 2=2 mod 2=0
二进制运算:与(and)、或(or)、非(not)、异或(xor)、移位(右移:shr,左移:shl)运算等, 有兴趣的同学可以查看相关计算机基础理论相关的内容。

2.1.2 课堂练习
1.甲、乙、丙三人分别有磁带 36,48,64 盒。

先由甲把自己的磁带平均分为三份,分给乙、丙各一 份,自己留下一份;接着是乙,最后是丙,都按甲的方法处理。

编程输出甲、乙、丙在上述过程中各人的 磁带数分别是多少? (输出所有的中间结果)
2.五位好朋友相聚。

第一位朋友带来了很多糖块赠送给各位朋友,使每人的糖块在各自原有的基础上 翻了一倍;接着第二位好友也同样向每人赠送糖块,他同样使每人的糖块在各人已有的数量上翻了一倍; 第三、第四、第五位好友都照此办理。

经过这样的赠送之后,每人的糖块恰好都为 32 块。

问各位好友原 先的糖块数分别是多少?
2.2 表达式
程序在进行处理时要用到各种各样的式子——表达式。

所谓表达式,就是通过括号() 、运算符将一些量连在一起形成的式子。

这些量可以是各种类型的, 可以是常量、变量、函数、集合等。

表达式有好几种类型,不同类型的表达式有自己的运算符。

2.2.1 算术表达式
(如下表所示) 算术表达式通过算术运算符+、­、*、/、div、mod进行运算。

【例 2.4】判断下列表达式是否正确,正确的写出运算结果,错误的说出错误原因。

2*3 ; 2*4.1 ; 4/2 ; 6.0/4.0 ; 15 div 3 ; 16 div 3
­21 div 2 ; 21.0 div 3 ;15 mod 3 ;16 mod 3 ; ­21 mod 2
【分析解答】
2*3 (操作数 2 和 3 都是整型,结果为整型数:6)
2*4.1 (操作数有一个为实型数,所以结果为实型数:8.2000000000000000E+0000) 4/2 (运算符“/”为实数除,结果为实型数,即使能够整除结果仍为实型数:2.0)
6.0/4.0 (结果为实型数 1.5000000000000000E+0000)
15 div 3 (div 为整型操作符,整除结果为整数 5)
16 div 3 (整除结果为整数 5)
­21 div 2 (整除结果为整数­10)
21.0 div 3 (错误的表达式,因为 div 为整型操作符,而 21.0 是实型数,不能进行整除运算)
15 mod 3 (mod 为整型操作符,取余结果为整数 0)
16 mod 3 (取余结果为整数 1)
­21 mod 2 (取余结果为整数­1)
算术运算符的运算次序(优先级):
括号 > 函数 > * / div mod > + ­
【例 2.5】求表达式 6*(15*2 div 3 mod 2+10)/5 的运算结果 【分析解答】
表达式的运算先后次序如下图所示:
运算的结果为:1.2000000000000000E+0001。

是一个实型数。

2.2.2 字符(串)表达式
有关字符(串)操作的表达式,运算符有“+” (相连运算)等。

例如:表达式 (1)’nan’+’tong’
(2)’yue’+’king’
的结果为:(1)’nantong’
(2)’yueking’
2.2.3 数据类型之——布尔型
在前面, 我们学习了整型(integer)与实型 (real )。

其中 integer 型数据取值范围为­32768 到 32767
之间所有整数。

而 real 型数据取值范围为其绝对值在 10 ­38 到 10 38
之间的所有实数。

它们都是数值型的
(即值都为数)。

布尔型(Boolean )是一种数据的类型,这种类型只有两种值,即“真 . ”与“假 .
” 。

1、 布尔常量
在 Pascal 语言中“真 . ”用 ture 表示, “假 . ”用 false 表示。

所以布尔类型只有 TRUE 与 FALSE 两个常量。

2、 布尔变量(BOOLEAN )
如果我们将某些变量说明成布尔型,那么这些变量就是布尔变量,它们只能用于存放布尔值(ture 或 false )。

例如:var a ,b :boolean ; 3、 布尔类型是顺序类型
由于这种类型只有两个常量,Pascal 语言中规定 ture 的序号为 1,false 的序号为 0。

若某种类型的 常量是有限的,那么这种类型的常量通常都有一个序号,我们称这种类型为顺序类型。

如前面我们学过的 整型(integer ),以及后面将要学到的字符型(char )都是顺序类型。

4、 布尔类型的输入与输出
a)输出
var a,b:boolean;
begin
a:=true;b:=false;
writeln(a,b);
end.
输出为:TRUEFALSE
b)布尔类型变量不能直接用读语句输入
布尔类型变量不能通过读语句给它们提供值。

事实上,我们可以通过间接方式对布尔变量进行值的输 入。

例如,以下程序是错误的:
var a,b,c:Boolean;
begin
readln(a,b,c); {错误语句}
writeln(a,b,c);
end.
2.2.4 关系表达式与逻辑表达式
描述大小、相等或不等关系的表达式称为关系表达式,对关系表达式再进行与、或、非运算的称为逻 辑表达式。

运算符主要有:=,>,<,>=,<=,<>,and,or,not 等。

例如:
(1)a+b>=c {等同于 not (a+b<c)}
(2)(a>b)and(b>c)
(3)not f {f 为布尔型变量}
(4)not (a>b) {等同于 a<=b}
(5)3=2 {结果恒为 false,因为它不可能成立}
逻辑运算常用的有三个运算符:and(与)、or(或)、not(非) 。

他们的运算对象为布尔量,其中 not 为单目运算,只有一个运算对象,and 与or为双目运算,有两个运算对象。

它们的运算真值表如下:
将各运算合并后的真值表如下:
a b Not a a and b a or b a xor b
false false true false false false
false true true false ture true
true false false false ture ture
ture ture false ture ture false
运算符的运算次序(优先级):
括号 > 函数> ­ not > * / div mod and > + ­ or > =,>,<,>=,<=,<> 注:
1、同级运算由左到右;
2、括号优先级最高,先算内层,再算外层。

2.3 二进制
在计算机中所有的信息都是以二进制的方式存储的,因此,我们在学习程序设计时有必要掌握一些有 关二进制的知识。

2.3.1 二进制的相关概念
位(bit) :二进制数系统中,每个0 或 1就是一个位(bit),位是内存的最小单位。

字节(Byte) :由于常用的英文字符用8 位二进制就可以表示,所以通常就将 8 位称为一个字节。

1Byte=8bit
1KB=2^10B=1024B
1MB=2^10KB=1024KB
1GB=2^10MB=1024MB
1TB=2^10GB=1024GB
字长: CPU 在单位时间内(同一时间)能一次处理的二进制数的位数叫字长。

一般计算机的字长都是字节(8 位)的整数倍。

能处理字长为 8 位数据的CPU通常就叫8 位的CPU; 同理 32 位的 CPU 就能在单位时间内处理字长为 32位的二进制数据。

字长的长度是不固定的,对于不同的 CPU、字长的长度也不一样。

8 位的 CPU 一次只能处理一个字 节,而 32位的 CPU 一次就能处理 4 个字节,同理字长为 64位的 CPU 一次可以处理 8 个字节。

操作系统常常与 CPU 的字长密切相关。

如:Windows XP 有32 位和64 位两种,对应32 位计算机 CPU(如奔腾 4系列)和64 位计算机 CPU(如酷睿系列) 。

2.3.2 数制转换——二进制转换为十进制
在日常生活中,我们接触的都是十进制,那么我们怎样才能把二进制转换为我们熟悉的十进制呢? 方法:
“按权展开求和”
把二进制数首先写成加权系数展开式,然后按十进制加法规则求和。

【例 2.6】将(1011.01)2 转换为十进制
【解】
(1011.01)2
=(1*2 3 +0*2 2 +1*2 1 +1*2 0 +0*2 ­1 +1*2 ­2 )10
=(8+0+2+1+0+0.25)10
=(11.25)10
数的进制与权——认清转换的本质
同进制的数,基数不同,每位上代表的值的大小(权)也不相同。

例如:

十进制数(逢十进一,由 0~9 组成)
(219)10=2*10 2 +1*10 1 +9*10 0

二进制数(逢二进一,由 0、1 组成)
(11010)2=1*2 4 +1*2 3 +0*2 2 +1*2 1 +0*2 0

八进制数(逢八进一,由 0~7 组成)
(273)8=2*8 2 +7*8 1 +3*8 0
十六进制数(逢十六进一,由0~9、A、B、C、D、E、F 组成) :
(27AF)16=2*16 3 +7*16 2 +10*16 1 +15*16 0
【例 2.7】将下面的数转换为十进制数:
(1)(3FF)16 (2)(23)8 (3)(1010)2
解:
(1) (3FF)16=3*16 2 +15*16 1 +15*16 0
=3*256+15*16+15*1
=1023
(2) (23)8=2*8 1 +3*8 0
=2*8+3*1
=27
(3) (1010)2=1*2 3 +0*2 2 +1*2 1 +0*2 0
=1*8+0*4+1*2+0*1
=10
由此,我们根据“按‘权’展开”的方法将任意进制的数转换为十进制数。

2.3.3 数制转换——十进制转换二进制
给你一个十进制,比如:89和 0.625,如果将它转换成二进制数呢?
十进制整数转二进制数:——“除以 2取余数,逆序输出”
十进制小数转二进制数:——“乘以 2取整数,顺序输出”
下面我们通过例题来看看如何进行转换?
【例 2.8】将下面的十进制数转换为二进制数:
(1)(89)10 (2)(0.625)10
解:
(1)因为 89 是整数,所以采用“除以 2取余数,逆序输出”的方法进行转换
所以(89)10=(1011001)2
(2)因为 0.625 是小数,所以采用“乘以 2取整数,顺序输出”的方法进行转换
所以(0.625)10=(0.101)2(蓝色部分为整数)
【想一想】
我们知道(39)10=(100111)2、 (0.35)10=(0.01011)2,那么
(1) (12.125)10=(?)2 ?
(2) (245)10=(?)8=(?)2
(3)二进制、八进制、十六进制之间的关系
下面给出 0~15 对应的二进制、十六进制数。

(0)16=(0000)2 (1)16=(0001)2
(2)16=(0010)2 (3)16=(0011)2
(4)16=(0100)2 (5)16=(0101)2
(6)16=(0110)2 (7)16=(0111)2
(8)16=(1000)2 (9)16=(1001)2
(A)16=(1010)2 (B)16=(1011)2
(C)16=(1100)2 (D)16=(1101)2
(E)16=(1110)2 (F)16=(1111)2
2.3.4 课堂练习
(在各选项中选出符合题意的选项,并将答案写在括号内)
不定项选择。

1、 (0.5)10=( C )16
A)0.1 B)0.75 C)0.8 D)0.25
2、算式(2047)10 ­(3FF)16+(2000)8 的结果是( A )
A) (2048)10 B) (2049)10 C) (3746)8 D) (1AF7)16
3、十进制数(2003)10 等值于二进制数( A )
A)11111010011 B)10000011 C)110000111 D)010000011 E)1111010011
4、算式(2008)10 ­(3723)8 的结果是( BCD )
A) (­1715)10 B) (5)10 C) (5)16 D) (101)2 E) (3263)8
2.4 课后练习、上机编程
1、 《FreePascal同步练习》第 2 章 Free Pascal 语言基础
2、第 3 章程序设计入门 B 级试题(P22)。

相关文档
最新文档