Chapter 8 高级程序设计语言
8.1 翻译过程
*第二代高级语言可以分为两种,一种是要编译的(FORTRAN、COBOL、ALGOL);
一种是要解释的(Lisp、SNOBOL4、APL);
A. 编译器(Compiler):
把高级语言编写的程序翻译成机器码的程序
翻译高级程序设计语言编写的程序的程序叫做编译器。
早期的编译器输出的是程序的汇编语言版本,再进过汇编器处理才能得到可执行的机器语言程序。
如今,编译器变得更加复杂,汇编语言阶段通常被省略了。
高级语言程序 ----(输入)----> 编译器 ----(输出)----> 机器代码程序
B. 解释器(interpreter):
输入用高级语言编写的程序,指导计算机执行每个语句指定的动作的程序
解释器是一种翻译程序,用于解释和执行语句序列。与汇编器和编译器只输出机器码不同的是,
解释器在翻译过语句后会立刻执行这个语句。可以把解释器看作编写程序所使用的语言的模拟器或虚拟机
JAVA为达到最佳可移植性,它将被编译成一种标准机器语言 -- 字节码(bytecode)
名为JVM(Java虚拟机)的软件解释器将接受字节码程序,然后执行它
/**
字节码通常指的是已经经过编译,但与特定机器码无关,需要直译器转译后才能成为机器码的中间代码。
字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。
字节码主要为了实现特定软件运行和软件环境、硬件环境无关。
字节码的实现方式是通过编译器和虚拟机器。
编译器将源码编译成字节码,特定平台上的虚拟机器将字节码转译为可以直接执行的指令。
**/
8.2 程序设计语言的范型
四种程序设计语言范型:
A. 命令(流程)范型
允许程序员把算法表示为(第6章介绍的)任务分层体系。即程序描述了解决问题的主要处理。
特征是顺序执行指令,使用表示内存地址的变量,以及使用赋值语句改变这些变量的值。
-- 受冯·诺依曼模型影响: 对存储在内存中的数值进行操作的顺序指令的模型
有 FORTRAN、COBOL、BASIC、C、Pascal、Ada和C++
B. 函数范型
它以数学概念函数为基础,计算被表示为函数求值。
问题求解被表示为函数调用。基本结构是函数求值,不存在变量和赋值语句。
没有循环结构,重复操作被表示为递归的函数调用。
有 LISP、Schenme(LISP派生语言)和ML
C. 逻辑程序设计范型
它的基础是数理逻辑的原理。该模型由一组关于对象的事实和一组关于对象之间的关系的规则构成。
采用这种模型的程序,由关于对象和它们之间的关系(可以由事实和规则推出)的问题构成。
采用这种模型,底层问题求解算法使用逻辑规则由事实和规则推导出答案。
有PROLOG,它有三种类型的语句构成:
1. 一种语句用于声明有关对象的事实和对象之间的关系
2. 一种语句用于定义有关对象和它们之间的关系的规则
3. 一种语句用于对对象和它们的关系发问
人工智能应用程序即使用LISP,又使用PROLOG
D. 面向对象范型
面向对象的观点是将时间看作由交互的对象构成,每个对象负责自己的动作。
在命令范型中,数据对象是被动的,由程序进行操作。
而在面向对象范型中,对象则是主动的,对象和操作对象的代码绑定在一起,这使得每个对象都负责自己的操作。
它允许程序员用(第6章介绍的)对象分层体系
有SIMULA、Smalltalk
而C++具有某些面向对象特性的命令式语言,JAVA是具有某些命令式特性的面向对象语言。
8.3 命令式语言的功能性
A. 布尔表达式
(Boolean expression): 一个标识符序列,标识符之间由相容的运算符分隔,求得的值为true或false.
这些语句是程序设计提问的方式,称为断言或条件
一个布尔表达式可以是:
· 一个布尔变量
· 一个算术表达式加一个关系运算符,再加一个算术表达式
· 一个布尔表达式加一个布尔运算符,再加一个布尔表达式
*不等于的表示符号 /= , != , <>
布尔运算符是特殊的运算符 AND、OR和NOT
B. 强类型化
汇编中,标识符被赋予内存单元,标识符与这些内存单元存储的内容无关。
大多数高级语言中,关联内存单元和标识符则要求说明这些内存单元存储的数据类型。
强类型化(strong typing): 每个变量都有一个类型,只有这种类型的值才能存储到该变量中。
数据类型(data type): 一组值以及能够应用于这种类型的值的基本操作集合的说明。
1. 数据类型
数据是表示信息的物理符号。在计算机内部,数据和指令都是二进制位的组合。计算机能够执行
一条指令,是因为这条指令的地址被载入了程序计数器,指令被载入指令寄存器,被执行的位组合
同样可以表示 整数、实数、字符或布尔值,关键看计算机如何解释位组合。
a. 整数
整数数据类型表示是一个整数范围,这个范围由表示整数的字节数决定。
b. 实数
实数数据类型表示的是特定精度的数的范围,这个范围由表示实数值的字节数决定。
在对实数应用关系运算时要注意精度问题
c. 字符
表示ASCII字符集的字符需要一个字节,表示Unicode字符集中的字符则需要两个字节
d. 布尔型
布尔数据类型只有两个值 -- true 和 false
并非所有的高级语言都支持布尔数据类型,如果一种数据类型不支持布尔类型,可以模拟它。
整数、实数、字符和布尔称为简单数据类型或原子数据类型,因为每个值都是独立的,不能再分割的。
e. 字符串
是具有复合数据类型的特征的数据类型,但通常被看作简单数据类型
不同语言定义的字符串的操作不同,包括连接操作和根据词典顺序进行的比较操作。
2. 声明
声明(declaration): 把变量、动作或语言中的其他实体与标识符关联起来的语句,使程序员
可以通过名字引用这些项目
保留字(reserved word): 一种语言中具有特殊意义的字,不能用它作为标识符
区分大小写(case sensitive): 大写字母和小写字母被看作是不同的;两个拼写方法相同,但
大小写形式不同的标识符被看作两个不同的标识符
赋值语句(assignment statement): 把一个表达式的值存入一个变量的语句
C. 输入/输出结构
高级语言把输入的数据看作一个分为多行的字符流。字符的含义则由存放值的内存单元的数据类型决定。
所由输入语句都由三部分组成,即要存放数据的变量的声明,输入语句和要读入的变量名、以及数据流本身
* 输入的变量的类型决定了如何解释输入流中的字符(只是一系列ASCII或Unicode字符)
输出语句将创建一个字符流,输出语句中列出的项目可以是直接量,也可以是变量名。
直接量是输出语句中明确写出的数字或字符串。根据标识符或直接量的类型,输出的值将被依次处理。
类型决定了如何解释这种位组合。
无论输入/输出语句的语法是什么,也无论输入/输出流在哪里,这个过程关键是数据类型。
它决定了如何把字符转化成位组合(输入)以及如何把位组合转化为字符(输出)
D. 控制结构
由两种方式来改变算法的控制流,即循环和选择 //循环结构,选择结构与顺序结构组成三种基本控制结构
控制结构(control structure): 确定程序中的其他指令的执行顺序的指令
1. 顺序语句
一条指令按照物理顺序排在另一条指令之后执行。
2. 选择语句
如第6章说述,if由两种版本
if-then : 执行一组语句或跳过它们
if-then-else: 执行两组语句中的一组
被看作一组的指令称为复合语句,C++和JAVA用花括号对语句分组,它们称这些分组为块
3. 循环语句
用于重复一组动作
a. 计数控制的循环
计数控制循环将重复执行指定的次数
这种机制,每当过程重复一次,就累计一次重复次数,然后再次开始重复操作之前
测试循环次数,看是否循环结束。
有三部分构成: 循环控制变量初始化、测试循环变量是否达到预定值和增量(循环变量+1)
b. 事件控制的循环
循环次数由循环主体中发送的事件控制的循环
有三部分构成: 初始化事件、测试事件和更新事件
4. 子程序语句
利用分层思想,给某块代码一个名字,在程序的另一部分用这个名字作为语句。
当遇到这个名字后,程序这部分的处理进程将暂停,转而执行名字对应的代码。
执行完代码后,处理将继续执行名字之后的语句。 -- 代码名出现位置叫做 调用部件
有两种基本形式 : 一种是执行特定任务的有名代码,在调用部件中用作语句。
另一种不仅执行任务,还返回给调用部件一个值,用来评估表达式
子程序有多种叫法:
FORTRAN :子程序和函数
Ada :过程和函数
C++ :空函数和返值函数
JAVA :两种形式都叫做方法
*参数传递
有时,调用部件需要给子程序提供处理过程中需要的信息。
高级语言使用的通信方法叫做形参列表.
形参列表(parameter list): 程序中两部分之间的通信机制
形参(paramenters): 列在子程序名后的括号中的标识符
实参(arguments): 子程序调用中列在括号中的标识符
*值参和引用参数
传递参数的基本方式有两种,即通过值传递或通过引用(地址)传递
值参(value parmeter): 由调用部件传入实参的副本的形参 -- 原始变量不会变
引用参数(reference parameter): 由调用部件传入实参的地址的形参 -- 会修改原始变量
5. 递归
当子程序调用自身时,这种调用称为递归调用,是另一种循环控制结构。
递归(recursion): 子程序调用自身的能力
每个递归有两种情况: 基本情况: 答案已知的情况
一般情况: 调用自身来解决问题更小版本的解决方案
由于一般情况是原始问题越来越小的版本,所以程序最终到达基本情况,这情况答案已知,递归结束。
6. 异步处理
关于输入,在传统的流处理中,只有当遇到指令序列中的输入语句时才执行它。
但鼠标点击不在程序序列中,用户可以在程序执行中的任何时刻点击鼠标。当鼠标点击方式的时候,
程序需要识别它,然后处理点击,再继续执行下面的操作。这种处理类型叫做异步,意思为"不在同一时间"
任何时刻都可以点击鼠标,这不与任何指令同步。
异步(asynchronous): 不与计算机中的其他操作同时发生;换言之,即与计算机的动作不同步
7. 嵌套逻辑
在任何控制结构中,要执行或跳过的语句既可以是简单语句,也可以是块(复合语句);
控制结构可以嵌套在控制结构 ... 对于嵌套多少层没有限制,但如变得难以理解,则
建议给嵌套任务一个名字,让它成为子程序,然后再实现它。
E. 复合数据类型
1. 记录
记录是异构项目的有名集合,可以通过名字单独访问其中内容。
所谓异构,表示集合中的元素可以是各种类型的,每个项目都有一个标识符和一种类型。
2. 数组
数组是同构项目的有名集合,可以通过项目在集合中的位置访问它们。
项目在集合中的位置叫做索引。
记录中的变量和数组中的变量的处理方式与其他变量完全一样,只是访问方式不同而已。
在记录中,变量通过名字访问;在数组中,变量通过索引访问。
8.4 面向对象语言的功能性
面向对象的语言具有三个要素: 封装、继承和多态性。
这三要素赋予了面向对象语言可重用性,从而减少创建和维护软件的工作。
A. 封装
抽象是目标,信息隐蔽是实现这一目标的方法
封装(encapuslation): 实施信息隐蔽的语言特性
对象类或类(问题求解阶段)(object class or class(problem-solving phase)):
属性和行为相似的一组对象的说明。
对象(问题求解阶段)(object(problem-solving phase)): 与问题背景相关的事物或实体。
对象(实现阶段)(object(implementation phase)): 类的一个实例
类(实现阶段)(class (implementation phase)): 对象的模式
实例化(instantiate): 创建类的对象
B. 继承
继承是面向对象语言的一种属性,即一个类可以继承另一个类的数据和方法
超类是被继承的类,派生类是继承的类。
继承(inheritance): 类获取其他类的属性(数据域和方法)的机制
C. 多态性
是一种处理明显二义性的能力。
多态性(polymorphism):
一种语言的继承体系结构中具有两个同名方法,且能够根据对象应用合适的方法的能力。