精华内容
下载资源
问答
  • 程序设计语言的基本概念

    千次阅读 2019-01-20 16:56:37
    程序设计语言是为了书写计算机程序而人为设计的符号语言,用于对计算过程进行描述、组织和推导。 程序设计语言的广泛使用始于1957年出现的FORTRAN,程序设计语言的发展是一个不断演化的过程,其根本推动力是更高的...

    在这里插入图片描述

    程序设计语言是为了书写计算机程序而人为设计的符号语言,用于对计算过程进行描述、组织和推导。

    程序设计语言的广泛使用始于1957年出现的FORTRAN,程序设计语言的发展是一个不断演化的过程,其根本推动力是更高的抽象机制以及对程序设计思想的更好支持。

    低级语言与高级语言

    计算机硬件只能识别由0、1组成的机器指令序列,即机器指令程序,因此机器指令是最基本的计算机语言。

    由于机器指令是特定的计算机系统所固有的、面向机器的语言,所以用机器语言进行程序设计时效率很低,程序的可读性很差,也难以修改和维护。

    因此,人们就用易记忆的符号代替0、1序列来表示机器指令,例如,用ADD表示加法,用SUB表示减法等。用符号表示的指令称为汇编指令,汇编指令的集合被称为汇编语言。

    汇编语言的源程序由若干条语句组成,其中可以有三类语句:指令语句、伪指令语句和宏指令语句

    指令语句又称为机器指令语句,将其汇编后能产生相应的机器代码,这些代码能被CPU直接识别并执行相应的操作。基本的指令有ADD、SUB和AND等,书写指令语句时必须遵守指令的格式要求。

    伪指令语句指示汇编程序在汇编源程序时完成某些工作,例如为变量分配存储单元地址,给某个符号赋一个值等。伪指令语句经编译后不产生机器代码。

    在汇编语言中,还允许将多次重复使用的程序段定义为宏。宏指令语句就是宏的引用。

    汇编语言的书写格式在很大程度上取决于特定计算机的机器指令,因此它仍然是一种面向机器的语言,人们称机器语言和汇编语言为低级语言

    在此基础上,人们开发了功能更强、抽象级别更高的语言以支持程序设计,于是就产生了面向各类应用的程序设计语言,称为高级语言。常见的有Java、C、C++、PHP、Python等。

    程序设计语言的定义

    一般地,程序设计语言的定义都涉及语法、语义和语用等方面。

    语法是指由程序设计语言的基本符号组成程序中的各个语法成分(包括程序)的一组规则。其中由基本字符构成的符号(单词)书写规则称为词法规则,由符号构成语法成分的规则称为语法规则。

    语义是程序设计语言中按语法规则构成的各个语法成分的含义,分为静态语义和动态语义。静态语义是指编译时可以确定的语法成分的含义,而运行时刻才能确定的含义是动态语义。

    一个程序的执行效果说明了该程序的语义,它取决于构成程序的各个组成部分的语义。

    语用表示了构成语言的各个记号和使用者的关系,设计符合的来源、使用和影响。

    程序设计语言的分类

    (1) 命令式和结构化程序设计语言

    命令式语言是基于动作的语言,在这种语言中,计算被看成是动作的序列。命令式语言族开始于Fortran,Pascal和C语言都可以体现命令式程序设计的关键思想。

    在这种语言中,计算机被看作是动作的序列,程序就是用语言提供的操作命令书写的一个操作序列。用命令式程序设计语言编写程序,就是描述解题过程中每一步的过程,程序的运行过程就是问题的求解过程,因此也称为过程式语言。

    机器语言及汇编语言是最早的命令式语言。

    通常所称的结构化程序设计语言属于命令式语言类,其结构特性主要体现在以下几个方面:

    一是用自顶向下的逐步精化的方法编程,二是按模块组织的方法编程,三是程序只包含顺序、判定及循环构造,而且每种构造只允许单入口和单出口。

    结构化程序的结构简单清晰、模块化强,描述方式接近人们习惯的推理式思维方式,因此可读性强。C、PASCAL等都是典型的结构化程序设计语言。

    (2) 面向对象的程序设计语言

    程序设计语言的演化从机器语言开始到汇编语言到各种结构化高级语言,最后到支持面向对象技术的面向对象语言,反映的就是一条抽象机制不断提高的演化道路。

    C++、Java和Smalltalk是面向对象程序设计语言的代表,它们都支持封装、继承、多态等面向对象技术。

    (3) 函数式程序设计语言

    函数式设计语言是一类以λ演算为基础的语言,其基本概念来自于LISP,这是一个在1958年为了人工智能应用而设计的语言。函数是一种对应规则(映射),使定义域的每个元素和值域中的唯一的元素相对应。

    常见的函数式程序设计语言有Haskell、Scala、Scheme、APL等。

    (4) 逻辑型程序设计语言

    逻辑型程序设计语言是一类以形式逻辑为基础的语言,其代表是建立在关系理论和一阶谓词理论基础上的PROLOG。PROLOG有很强的推理功能,适用于编写自动定理证明、专家系统和自然语言理解等问题的程序。

    展开全文
  • 逻辑程序设计语言Prolog

    万次阅读 多人点赞 2017-06-23 10:16:23
    Prolog(PROgramming in LOGic的缩写)语言是一种基于 Horn 子句的逻辑型程序设计语言,也是一种陈述性语言。 Prolog 与人工智能的知识表示、自动推理、图搜索、产生式系统和专家(知识)系统有着天然的联系,很适合...

    Prolog 概念

    Prolog(PROgramming in LOGic的缩写)语言是一种基于 [Horn 子句](http://www.baidu.com)的逻辑型程序设计语言,也是一种陈述性语言。 Prolog 与人工智能的知识表示、自动推理、图搜索、产生式系统和专家(知识)系统有着天然的联系,很适合智能程序设计。 若想详细了解可自行百科:http://baike.baidu.com/item/Prolog

    今天我们先搞明白 Prolog 语言的基本原理,然后再详细学习一下 Turbo Prolog 语言程序设计。选择 Turbo Prolog 是因为它是一个功能较齐全的逻辑程序语言,其程序的可读性强而且简单易学,是一个很好的教学语言。另外, Turbo Prolog 程序既可以在 Trubo Prolog 和 PDC Prolog 环境下运行或编译,又可以在当前流行的可视化语言 Visual Prolog 的环境下运行或编译。


    Prolog 基础

    一、Prolog 的语句

    Prolog 语言仅有三种语句:事实(Fact)、规则(Rule)和问题(Question)。

    1、事实

    格式:

    <谓词名>(<项表>).
    
    • 谓词名是以大小写字母开头,字母、数字、下划线等组成的字符串;
    • 项表是以逗号隔开的项序列。

    Prolog 中的项包括由常量或变量表示的简单对象以及函数、结构和表等,即事实的形式是一个原子谓词公式

    功能:

    一般表示对象的性质或关系。

    举个例子:

    student(john).
    like(mary, music).
    

    这就是 Prolog 中两个合法的事实。分别表示“约翰是学生”和“玛丽喜欢音乐”。

    当然了,作为特殊情形,一个事实也可以只有谓词名而无参量。
    举个例子:

    abc.
    repeat.
    

    等也是允许的。

    2、规则

    格式:

    <谓词名>(<项表>):-<谓词名>(<项表>){,<谓词名>(<项表>)}.
    
    • “:-”号表示“if”(也可以直接写为 if ),其左部的谓词是规则的结论(亦称为头),右部的谓词是规则的前提(亦称为体);
    • “{}”表示零次或多次重复,逗号表示 and(逻辑与)。

    即规则的形式是一个逻辑蕴涵式

    功能:

    一般表示对象间的因果关系、蕴含关系或对应关系。

    举个例子:

    bird(X) :- animal(X), has(X, feather).
    grandfather(X, Y) :- father(X, Z), father(Z, Y).
    

    分别表示“如果 X 是动物,并且 X 有羽毛,则 X 是鸟”和“ X 是Y 的祖父,前提是如果存在 Z,X 是 Z 的父亲并且 Z 又是 Y 的父亲”。

    作为特殊情形,规则中的谓词也可以只有谓词而无参量。
    举个例子:

    run :- start, step1(X), step2(X), end.
    

    也是一个合法规则。

    3、问题

    格式:

    ?-<谓词名>(<项表>){,<谓词名>(<项表>)}.
    

    功能:

    问题表示用户的询问,它就是程序运行的目标。

    举个例子:

    ?-student(john).
    ?-like(mary, X).
    

    分别表示“约翰是学生吗?”和“玛丽喜欢谁?”。

    问题可以与规则及事实同时一起给出,也可以在程序运行时临时给出。

    二、Prolog 的程序

    Prolog 程序一般由一组事实、规则和问题组成。问题是程序执行的起点,称为程序的目标。


    我们首先写出一个 Prolog 的程序,如下:(为引用方便起见,我们把这个程序称为“程序0”

    likes(bell, sports).
    likes(mary, music).
    likes(mary, sports).
    likes(jane, smith).
    friend(john, X) :- likes(X, reading), likes(X, music).
    friend(john, X) :- likes(X, sports), likes(X, music).
    ?- friend(john, Y).
    

    接下来我们分析一下这个程序:
    可以看出,这个程序中有四个事实、两条规则和一个问题。其中事实、规则和问题都分行书写;规则和事实可连续排列在一起,其顺序可随意安排,但同一谓词名的事实或规则必须集中排列在一起;问题不能与规则及事实排在一起,它作为程序的目标要么单独列出,要么在程序运行时临时给出。
    这个程序的事实描述了一些对象(包括人和事物)间的关系;而规则则描述了 John 交朋友的条件,即如果一个人喜欢读书并且喜欢音乐(或者喜欢运动和喜欢音乐),那么这个人就是 John 的朋友(当然,这个规则也可看做 John 朋友的定义);程序中的问题是“约翰的朋友是谁?"

    Prolog 程序中的目标还可以变化,也可以含有多个语句(上例中只有一个)。如果有多个语句,则这些语句称为子目标。例如对上面的程序,其问题也可以是:

    	?-likes(mary, X).
    或
    	?-likes(mary, music).
    或
    	?-friend(X, Y).
    或
    	?-likes(bell, sports),
    	  likes(mary, music),
    	  friend(john, X).
    

    等。但对于不同的问题,程序运行的结果一般是不一样的。

    还需说明的是,Prolog程序中的事实或规则一般称为它们对应谓词的子句。例如,上面程序中的前4句都是谓词 likes 的子句。 Prolog 规定,同一谓词的子句应排在一起。从语句形式和程序组成来看, Prolog 就是一种基于 Horn 子句的逻辑程序。这种程序要求用事实和规则来求证询问,即证明所给出的条件子句和无条件子句与目标子句是矛盾的,或者说程序中的子句集是不可满足的。这就是所谓的 Prolog 的说明性语义。

    从 Prolog 的语句来看, Prolog 语言的文法结构相当简单。但由于它的语句是 Horn 子句,而 Horn 子句的描述能力是很强的,所以 Prolog 的描述能力也是很强的。例如,当它的事实和规则描述的是某一学科的公理,那么问题就是待证的命题;当事实和规则描述的是某些数据和关系,那么问题就是数据查询语句;当事实和规则描述的是某领域的知识,那么问题就是利用这些知识求解的问题;当事实和规则描述的是某初始状态和状态变化规律,那么问题就是目标状态。所以, Prolog 语言实际是一种应用相当广泛的智能程序设计语言。从上面最后一个目标可以看出,同过程性语言相比,对于一个 Prolog 程序,其问题就相当于主程序,其规则就相当于子程序,而其事实就相当于数据。

    三、Prolog 程序的运行机理

    要想了解 Prolog 的运行机理,首先需要了解几个基本概念。

    1、自由变量与约束变量

    Prolog中把无值的变量称为自由变量,有值的变量称为约束变量。一个变量取了某值就说该变量约束于某值,或者说该变量被某值所约束,或者说该变量被某值实例化了。在程序运行期间,一个自由变量可以被实例化而成为约束变量,反之,一个约束变量也可被解除其值而成为自由变量。

    2、匹配合一

    两个谓词可匹配合一,是指两个谓词的名相同,参量项的个数相同,参量类型对应相同,并且对应参量项还满足下列条件之一。

    1. 如果两个都是常量,则必须完全相同。
    2. 如果两个都是约束变量,则两个约束值必须相同。
    3. 如果其中一个是常量,一个是约束变量,则约東值与常量必须相同。
    4. 至少有一个是自由变量。

    例如下面的两个谓词:

    prel("ob1", "ob2", Z)
    prel("ob1", X, Y)
    

    只有当变量 X 被约束为"ob2",且 Y、Z 的约束值相同或者至少有一个是自由变量时,它们才是匹配合一的。
    Prolog 的匹配合一,与归结原理中的合一的意思基本一样,但这里的合一同时也是一种操作。这种操作可使两个能匹配的谓词合一起来,即为参加匹配的自由变量和常量,或者两个自由变量建立一种对应关系,使得常量作为对应变量的约束值,使得两个对应的自由变量始终保持一致,即若其中一个被某值约束,则另一个也被同一值约束;反之,若其中一个的值被解除,则另一个的值也被解除。

    3、回溯

    所谓回溯,就是在程序运行期间,当某一个子目标不能满足(即谓词匹配失败)时,控制就返回到前一个已经满足的子目标(如果存在的话),并撤销其有关变量的约束值,然后再使其重新满足。成功后,再继续满足原来的子目标。如果失败的子目标前再无子目标,则控制就返回到该子目标的上一级目标(即该子目标谓词所在规则的头部)使它重新匹配。回溯也是 Prolog 的一个重要机制。

    不懂没关系,下面有例子,看完这个 Prolog 程序的运行过程就懂了。

    有了上面的基本概念,下面就介绍所 Prolog 程序的运行过程。我们仍以上面给出的 Prolog 程序“程序0”为例。

    设所给的询问是:

    ?-friend(john, Y).			(john和谁是朋友?)
    

    则求解目标为:

    friend(john, Y).
    

    这时,系统对程序进行扫描,寻找能与目标谓词匹配合一的事实或规则头部。显然,程序中前面的 4 个事实均不能与目标匹配,而第 5 个语句的左端即规则为:

    friend(john, Y) :- likes(X, reading), likes(X, music).
    

    的头部可与目标谓词匹配合一。但由于这个语句又是一个规则,所以其结论要成立则必须其前提全部成立。于是,对原目标的求解就转化为对新目标:

    likes(X, reading), likes(X, music).
    

    的求解。这实际是经过归结,规则头部被消去,而目标子句变为:

    ?- likes(X, reading), likes(X, music).
    

    现在依次对子目标:

    likes(X, reading)和 likes(X, music)
    

    求解。
    子目标的求解过程与主目标完全一样,也是从头对程序进行扫描,不断进行测试和匹配合一等,直到匹配成功或扫描完整个程序为止。
    可以看出,对第一个子目标 like(X, reading)的求解因无可匹配的事实和规则而立即失败,进而导致规则:

    friend(john, X) :- likes(X, reading), likes(X, music).
    

    的整体失败。于是,刚才的子目标:

    likes(X, reading)和 likes(X, music)
    

    被撤销,系统又回溯到原目标 friend(john, X)。这时,系统从该目标刚才的匹配语句处(即第 5 句)向下继续扫描程序中的子句,试图重新使原目标匹配,结果发现第 6 条语句的左部,即规则

    friend(john, X) :- likes(X, sports), likes(X, music).
    

    的头部可与目标谓词匹配。但由于这个语句又是一个规则,于是,这时对原目标的求解就又转化为依次对子目标:

    likes(X, sports)和 likes(X, music)
    

    的求解。这次子目标 likes(X, sports)与程序中的事实立即匹配成功,且变量 X 被约束为 bell。于是,系统便接着求解第 2 个子目标。由于变量 X 已被约束,所以这时第 2 个子目标实际上已变成:

    likes(bell, music).
    

    由于程序中不存在事实 likes(bell, music),所以该目标的求解失败。于是,系统就放弃这个子目标,并使变量 X 恢复为自由变量,然后回溯到第一个子目标,重新对它进行求解。由于系统已经记住了刚才已同第一子目标谓词匹配过的事实的位置,所以重新求解时,便从下一个事实开始测试。易见,当测试到程序中的第 3 个事实时,第一个子目标便求解成功,且变量 X 被约束为 mary 。这样,第 2 个子目标也就变成:

    likes(mary, music).
    

    再对它进行求解。这次很快成功。
    由于两个子目标都求解成功,所以,原目标 friend(john, Y)也成功,且变量 Y 被约束为 mary(由 Y 与 X 的合一关系)。于是,系统回答:

    Y = mary
    

    程序运行结束。上述程序的执行过程如图下所示。
    Prolog 程序运行机理图解示例

    上述程序的运行是一个通过推理实现的求值过程。我们也可以使它变为证明过程。例如,把上述程序中的询问改为:

    friend(john, mary).
    

    则系统会回答“yes”。
    若将询问改为:

    friend(john, smith).
    

    则系统会回答“no”。

    从上述程序的运行过程来看, Prolog 程序的执行过程是一个(归结)演绎推理过程。其推理方式为反向推理,控制策略是深度优先且有回溯机制,具体实现方法是:自上而下匹配子句;从左向右选择子目标;(归结后)产生的新子目标总是插入被消去的目标处(即目标队列的左部)。Prolog 的这种归结演绎方法被称为 SLD(Linear resolution with Selection function for Definite clause)归结, 或 SLD 反驳 - 消解法。这样,SLD 归结就是 Prolog 程序的运行机理,也就是所谓的 Prolog 语言的过程性语义


    Turbo Prolog 程序设计

    Turbo Prolog 是一个编译型语言,1986 年由美国的 BORLAND 公司推出,运行在 IBM PC 系列机及其兼容机上。Turbo prolog 除了具有基本 prolog 的逻辑程序特点外还具有速度快、功能强,具有集成化开发环境,可同其他语言接口,能实现动态数据库和大型外部数据库,可直接访问机器系统硬软件和具有图形、窗口功能等一系列特点。

    本次我们以 Turbo prolog(2.0版)为例,介绍 prolog程序设计。

    一、程序结构

    一个完整的 Turbo prolog 程序一般包括常量段领域段数据库段谓词段目标段子句段 6 个部分。各段以其相应的关键字 constantsdomainsdatabasepredicatesgoalclauses 开头加以标识。另外,在程序的首部还可以设置指示编译程序执行特定任务的编译指令;在程序的任何位置都可设置注解。总之,一个完整的 Turbo prolog(2.0版)程序的结构如下:

    /*  < 注	释 >  */
        <编译指令>
    constants
        <常量说明>
    domains
        <域说明>
    database
        <数据库说明>
    predicates
        <谓词说明>
    goal
        <目标语句>
    clauses
        <子句集>
    

    当然,一个程序不一定要包括上述所有段,但一个程序至少要有一个 predicates 段clauses 段goal 段。在大多数情形中,还需要一个 domains段,以说明表、复合结构及用户自定义的域名。如若省略 goal 段,则可在程序运行时临时给出,但这仅当在开发环境中运行程序时方可给出。若要生成一个独立的可执行文件,则在程序中必须包含 goal 段。另外,一个程序也只能有个 goal 段。
    在模块化程序设计中,可以在关键字 domains, predicates 及 database前加上 global,以表明相应的说明是全局的,以便作用于几个程序模块。

    举个例子,如果要将上面的 Prolog 程序“程序0”作为 Turbo prolog程序,则应改写为

    DOMAINS
    	name = symbol
    PREDICATES
    	likes(name, name)
    	friend(name, name)
    GOAL
    			friend(john,Y), write("Y = ", Y).
    CLAUSES
    			likes(bell, sports).
    			likes(mary, music).
    			likes(mary, sports).
    			likes(jane, smith).
    			friend(john, X) :- likes(X, sports), likes(X, music).
    			friend(john, X) :- likes(X, reading), likes(X, music).
    

    下面对程序结构中的几个段作以说明。

    领域段 该段说明程序谓词中所有参量项所属的领域。领域的说明可能会出现多层说明,直到说明到 Turbo prolog 的标准领域为止(如上例所示)。Turbo prolog 的标准领域即标准数据类型,包括整数、实数、字符、串和符号等,其具体说明如下表所示。

    领域名称 标识符 取值范围 例子
    整数 integer -32 767 ~ +32 767
    实数 real ±IE-307 ~ ±IE+308
    字符 char 用单引号括住的所有可能的字符 ‘a’, ‘5’
    string 用一对双引号括住的任意字符序列。程序中的串最长可达 255 个字符,文件中的可为 64k ‘abc’, ‘123’
    符号 symbol 以小写字母打头的字母、数字和下划线序列;串 ‘abc’, abc
    Turbo Prolog 的标准领域表

    谓词段 该段说明程序中用到的谓词的名和参量项的名(但 Turbo prolog的内部谓词无须说明)。

    子句段 该段是 Turbo prolog 程序的核心,程序中的所有事实和规则就放在这里,系统在试图满足程序的目标时就对它们进行操作。

    目标段 该段是放置程序目标的地方。目标段可以只有一个目标谓词,例如上面的例子中就只有一个目标谓词;也可以含有多个目标谓词,如:

    goal
      readint(X), Y = X+3, write("Y ='%Y).
    

    就有3个目标谓词。这种目标称为复合目标。

    二、数据与表达式

    1、领域

    (1)标准领域。
    Turbo prolog中不定义变量的类型,只说明谓词中各个项的取值域。由上面我们知道, Turbo prolog 有整数实数字符符号这5种标准域。另外,它还有结构文件这3种复合域

    (2)结构。
    结构也称复合对象,它是 Turbo prolog 谓词中的一种特殊的参量项(类似于谓词逻辑中的函数)。结构的一般形式为:

    <函子>(<参量表>)
    

    其中函子及参量的标识符与谓词相同。注意,这意味着结构中还可包含结构。所以,复合对象可表达树形数据结构。例如下面的谓词:

    likes("Tom", sports(football, basketball, table_tennis)).
    

    中的

    sports(football, basketball, table_tennis)
    

    就是一个结构,即复合对象。又如:

    person("张华", student("清华大学"), address("中国", "北京")).
    reading("王宏", book("人工智能技术导论", "西安电子科技大学出版社")).
    friend(father("Li"), father("Zhao")).
    

    这几个谓词中都有复合对象。
    复合对象在程序中的说明,需分层进行。例如,对于上面的谓词:

    likes("Tom", sports(football, basketball, table_tennis)).
    

    在程序中可说明如下:

    domains
      name = symbol
      sy = symbol
      sp = sports(sy, sy, sy)
    predicates
      likes(name, sp)
    

    (3)表。
    表的一般形式是:

    [x1, x2, ..., xn]
    

    其中xi(i=1,2,...,n)为 Prolog 的项,一般要求同一个表的元素必须属于同一领域。不含任何元素的表称为空表,记为[]。例如下面就是一些合法的表。

    [1,2,3]
    [ apple, orange, banana, grape, cane]
    ["Prolog", "MAENS", "PROGRAMMING", "in logic"]
    [[a, b], [c, d], [e]]
    []
    

    表的最大特点是其元素个数可在程序运行期间动态变化。表的元素也可以是结构或表,且这时其元素可以属于不同领域。例如:

    [name("LiMing"), age(20), sex(male), address(xian)]
    [[1, 2], [3, 4, 5], [6, 7]]
    

    都是合法的表。后一个例子说明,表也可以嵌套。
    实际上,表是一种特殊的结构,它是递归结构的另一种表达形式。这个结构的函数名取决于具体的 Prolog 版本,这里我们就用一个圆点来表示。下面就是一些这样的结构及它们的表的表示形式:

    结构形式 表形式
    ·(a, []) [a]
    ·(a, ·(b, [])) [a, b]
    ·(a, ·(b, ·(c, []))) [a, b, c]

    表的说明方法是在其组成元素的说明符后加一个星号*。如:

    domains
        lists = string*
    predicates
    	pl(lists)
    

    就说明谓词 pl 中的项 lists 是一个由串 string 组成的表。
    对于由结构组成的表,至少分3步说明。例如对于下面谓 p 中的表

    p([name("Liming"), age(20)])
    

    则需这样说明:

    domains
      rec=seg*
      seg=name(string); age(integer)
    predicates
      p(rec)
    

    2、常量与变量

    由上面的领域可知, Turbo Prolog的常量有整数实数字符符号结构文件 这8种数据类型。同理, Turbo Prolog 的变量也就有这8种取值。另外,变量名要求必须是以大写字母或下划线开头字母、数字和下划线 序列,或者只有一个下划线(这种变量称为无名变量)

    3、算术表达式

    Turbo Prolog 提供了 5 种最基本的算术运算:加、减、乘、除 和 取模,相应运算符号为“+”、“-”、“*”、“/”、“mod”。这 5 种运算的顺序为:“*”、“/”、“mod”优先于“+”、“-”。同级从左到右按顺序运算,括号优先。
    算术表达式的形式与数学中的形式基本一样。例如:

    数学中的算术表达式 Turbo Prolog 中的算术表达式
    x + yz X + Y * Z
    ab - c / d A * B - C / D
    u mod v U mod V(表示求U除以V所得的余数)

    即, Turbo Prolog 中算术表达式采用通常数学中使用的中缀形式。这种算术表达式为 Prolog 的一种异体结构,若以 Prolog 的结构形式来表示,则它们应为:

    +(X, *(Y, Z))
    -(*(A, B), /(C, D))
    mod(U, V)
    

    所以,运算符“+”、“-”、“*”、“/”和“mod”实际也就是 Prolog 内部定义好了的函数符。
    在 Turbo Prolog 程序中,如果一个算术表达式中的变元全部被实例化(即被约束),则这个算术表达式的值就会被求出。求出的值可用来实例化某变量,也可用来同其他数量进行比较,用一个算术表达式的值实例化一个变量的方法是用谓词“is”或“=”来实现的。例如:

    Y is X + 5
    或
    Y = X + 5		(*)
    

    就使变量 Y 实例化为 X+5 的值(当然 X 也必须经已被某值实例化),可以看出,这里对变量 Y 的实例化方法类似于其他高级程序语言中的“赋值”,但又不同于赋值。例如,在 Prolog 中下面的式子是错误的:

    X = X + 1
    

    需要说明的是,虽然 Prolog 是一种逻辑程序设计语言,但在目前的硬件条件下却非突破逻辑框架不可。这是因为有些实用操作是无法用逻辑描述的(如输入与输出),有些算术运算在原则上可用逻辑描述,但这样做效率太低。为此, Prolog 提供了若干内部谓词(亦称 预定义谓词),来实现算术运算、输入与输出等操作。所谓内部谓词,就是 Prolog 的解释程序中,预先用实现语言定义好的用户可直接作为子目标调用的谓词。一般的 Prolog 实用系统都配有 100 个以上的内部谓词,这些内部谓词涉及输入输出、算术运算、搜索控制、文件操作和图形声音等方面,它们是实用 Prolog 程序设计所必不可少的。这样,上面的(*)式以及下面的关系表达式称为异体谓词

    4、关系表达式

    Turbo Prolog 提供了 6 种常用的关系运算,即 小于小于或等于等于大于大于或等于不等于,其运算符依次为:

    <, <=, =, >, >=, <>
    

    Turbo Prolog 的关系表达式的形式和数学中的也基本一样,例如:

    数学中的关系式 Turbo Prolog 中的关系式
    X + 1 ≥ Y X + 1 >= Y
    X ≠ Y X <> Y

    即, Turbo Prolog 中的关系式也用中缀形式。当然,这种关系式为 Turbo Prolog 中的异体原子。若按 Turbo Prolog 中的原子形式来表示,则上面的两个例子为:

    >=(X +1, Y) 和 <>(X, Y)
    

    所以上述 6 种关系运算符,实际上也就是 Turbo Prolog 内部定义好了的 6 个谓词。这 6 个关系运算符可用来比较两个算术表达式的大小。例如:

    brother(Name1, Name2) :- person(Name1, man, Age1),
    				   person(Name2, man, Age2),
    				   mother(Z, Name1), mother(Z, Name2), Age1 > Age2.
    

    需要说明的是,“=”的用法比较特殊,它既可以表示比较,也可以表示约束值,即使在同一个规则中的同一个“=”也是如此。例如:

    p(X, Y, Z) :- Z = X + Y.
    

    当变量 X、Y、Z全部被实例化时,“=”就是比较符。如对于问题:

    Goal: p(3, 5, 8).
    

    机器回答“yes”,而对于:

    Goal: p(3, 5, 7).
    

    机器回答“no”。即这时机器把 X+Y 的值与Z的值进行比较。但当 X,Y 被实例化,而 Z 未被实例化时, “=”号就是约束符,如:

    Goal: P(3, 5, Z).
    

    机器回答“Z = 8”。这时,机器使 Z 实例化为 X+Y 的结果。

    三、输入与输出

    虽然 Prolog 能自动输出目标子句中的变量的值,但这种输出功能必定有限,往往不能满足实际需要;另外,对通常大多数的程序来说,运行时从键盘上输人有关数据或信息也是必不可少的。为此每种具体 Prolog 一般都提供专门的输人和输出谓词,供用户直接调用。例如,下面就是 Turbo Prolog 的几种输入输出谓词:

    1. readin(X)。这个谓词的功能是从键盘上读取一个字符串,然后约束给变量 X 。
    2. readint(X)。这个谓词的功能是从键盘上读取一个整数,然后约束给变量 X,如果键盘上打入的不是整数,则该谓词失败。
    3. readreal(X)。这个谓词的功能是从键盘上读取一个实数,然后约束给变量 X,如果键盘上打入的不是实数,则该谓词失败。
    4. readchar(X)。这个谓词的功能是从键盘上读取一个字符,然后约束给变量 X,如果键盘上打入的不是单个字符,则该谓词失败。
    5. write(X1, X2, …, Xn)。这个谓词的功能是把项 Xi(i=1,2,…,n) 的值显示在屏幕上或者打印在纸上,当有某个 Xi 未实例化时,该谓词失败。其中的 Xi 可以是变量,也可以是字符串或数字。例如:
      write("computer", "Prolog", Y, 1992)
    6. nl(换行谓词)。它使后面的输出(如果有的话)另起一行。另外,利用 write的输出项“\n”也同样可起到换行作用。例如:
      write("name"), nl, write("age")

      write("name", "\n", "age")
      的效果完全一样。

    举个例子:
    用上面的输入输出谓词编写一个简单的学生成绩数据库查询程序。

    PREDICATES
       student(integer, string, real)
       grade
    GOAL
       grade.
    CLAUSES
       student(1, "张三", 90.2).
       student(2, "李四", 95.5).
       student(3, "王五", 96.4).
       grade :- write("请输人姓名:"), readln(Name), 
    		    student(_, Name, Score),
    		    nl, write(Name, "的成绩是", Score).
       grade :- write("对不起,找不到这个学生!").
    

    下面是程序运行时的屏幕显示

    请输入姓名:王五
    王五的成绩是96.4
    

    四、分支与循环

    Prolog 本来没有分支和循环语句,但可以利用其逻辑机制实现分支和循环效果。

    1、分支

    对于通常的 IF-THEN-ELSE 分支结构,Prolog可用两条同头的(同头即指结论相同)并列规则实现。例如,将:

    IF X>0 THEN X:=1
    ELSE X:=0
    

    用 Prolog实现则是:

    br :- X > 0, X = 1.
    br :- X = 0.
    

    类似地,对于多分支,可以用多条规则实现。例如:

    br :- X > 0, X = 1.
    br :- X = 0, X = 0.
    br :- X < 0, X = -1.
    

    2、循环

    Prolog 可以实现计循环次数的 FOR 循环,也可以实现不计循环次数的 DO 循环。

    举个例子:
    下面的程序段就实现了循环,它使得 write 语句重复执行了3次,而打印输出了3个学生的记录:

    student(1, "张三", 90.2).
    student(2, "李四", 95.5).
    student(3, "王五", 96.4).
    print :- student(Number, Name, Score),
    		write(Number, Name, Score), nl,
    		Number = 3.
    

    可以看出,程序第一次执行,student 谓词与第一个事实匹配,write 语句便输出了张三同学的记录。但当程序执行到最后一句时,由于 Number 不等于 3,则该语句失败,于是,引起回溯。而 write 语句和 nl 语句均只能执行一次,所以继续向上回溯到 student 语句。这样,student 谓词则因失败而重新匹配。这一次与第二个事实匹配,结果输出了李四的记录。同理,当执行到最后一句时又引起了回溯。write 语句第三次执行后,由于 Number 已等于3,所以最后一个语句成功,程序段便运行结束。
    这个例子可以看做是计数循环。当然,也可以通过设置计数器而实现真正的计数循环。下面的程序段实现的则是不计数的 DO 循环:

    student(1, "张三", 90.2).
    student(2, "李四", 95.5).
    student(3, "王五", 96.4).
    print :- student(Number, Name, Score),
    		write(Number, Name, Score), nl,
    		fail.
    print :-.
    

    这个程序段中的 fail 是一个内部谓词,它的语义是恒失败。这个程序段与上面的程序段的差别仅在于把原来用计数器(或标记数)进行循环控制的语句变成了恒失败谓词 fail,另外又增加了一个 print 语句,增加这个语句的目的是为程序设置一个出口。因为 fail 是恒失败,下面若无出口的话,将引起 print 本身的失败,进而又会导致程序的连锁失败。
    还需说明的是,用 Prolog的递归机制也可以实现循环,不过用递归实现循环通常需与表相配合。另外,递归的缺点是容易引起内存溢出,故通常的循环多是用上述方法实现的。

    五、动态数据库

    动态数据库就是在内存中实现的动态数据结构。它由事实组成,程序可以对它操作,所以在程序运行期间它可以动态变化。Turbo Prolog 提供了 3 个动态数据库操作谓词,即:

    asserta(< fact >)
    assertz(< fact >)
    retract(< fact >)
    

    其中 fact 表示事实。这 3 个谓词的功能如下:

    • asserta(< fact >) 把 fact 插入当前动态数据库中的同名谓词的事实之前。
    • assertz(< fact >) 把 fact 插入当前动态数据库中的同名谓词的事实之后。
    • retract(< fact >) 把 fact 从当前动态数据库中删除。

    例如语句:

    asserta(student(20, "李明", 90.5)).
    

    将在内存的谓词名为 student 的事实前插入一个新事实:

    student(20, ''李明", 90.5)
    

    如果内存中还没有这样的事实,则它就是第一个。又如语句:

    retract(student(20, _, _)).
    

    将从内存的动态数据库中的删除事实:

    student(20, _, _)
    

    它可解释为学号为 20 的一个学生的记录。注意,这里用了无名变量 “_”
    可以看出,Turbo Prolog 提供的动态数据库机制,可非常方便地实现堆栈、队列等动态数据结构,提供的数据库操作谓词大大简化了编程。
    另外,Turbo Prolog 还提供了两个文件操作谓词:

    save(< filename >).
    consult(< filename >).
    

    其中 save 可将当前内存中的事实存入文件“filename”中,consult 则将文件“filename”中的事实调入内存。

    六、表处理与递归

    1、表头与表尾

    表是 Prolog 中一种非常有用的数据结构。表的表述能力很强,数字中的序列、集合,通常语言中的数组、记录等均可用表来表示。表的最大特点是其长度不固定,在程序的运行过程中可动态地变化。具体来讲,就是在程序运行时,可对表施行一些操作,如给表中添加一个元素,或从中删除一个元素,或者将两个表合并为一个表等。用表还可以方便地构造堆栈、队列、链表、树等动态数据结构。
    表还有一个重要特点,就是它可分为两部分。表头是表中第一个元素,而表尾是表中除第一个元素外的其余元素按原来顺序组成的。例如下面的表所示就是一个例子。

    表 头 表 尾
    [1, 2, 3, 4, 5] 1 [2, 3, 4, 5]
    [apple, orange, banana] apple [orange, banana]
    [[a, b], [c], [d, e]] [a, b] [[c], [d, e]]
    [“Prolog”] “Prolog” []
    [] 无定义 无定义
    **表头与表尾示例** 表

    2、表的匹配合一

    在程序中是用“|”来区分表头和表尾的,而且还可以使用变量。例如一般地用[H|T]来表示一个表,其中 H、T 都是变量,H 为表头,T为表尾。注意,此处 H 是一个元素(表中第一个元素),而 T 则是一个表(除第一个元素外表中的其余元素按原来顺序组成的表)。表的这种表示法很有用,它为表的操作提供了极大的方便。如下面的表所示即为用这种表示法通过匹配合一提取表头和表尾的例子。

    表1 表2 合一后的变量值
    [X | Y] [a, b, c] X = a, Y = [b, c]
    [X | Y] [a] X = a, Y = []
    [a | Y] [X, b] X = a, Y = [b]
    [X, Y, Z] [a, b, c] X = a, Y = b, Z = c
    [[a, Y] | Z] [[X, b], [c]] X = a, Y = b, Z = [[c]]
    **表的匹配合一示例** 表

    还需说明的是,表中的“|”后面只能有一个变量。例如写法 [X | Y, Z] 就是错误的。但竖杠前面的变量可以多于一个。例如写法 [ X, Y | Z] 是允许的。这样,这个表同 [a, b, c] 匹配合一后,有:

    X = a, Y = b, Z = [c]
    

    另外,竖杠的前面和后面也可以是常量,例如 [a | Y] 和 [X | b] 都是允许的,但需要注意,后一个表称为无尾表,如果它同表 [a | Y] 匹配,则有:

    X = a, Y = b	(而不是 Y = [b])
    

    如果无“|”,则不能分离出表尾。例如,表 [X, Y, Z] 与 [a, b, c] 合一后得 X = a,Y = b,Z = c,其中变量 Z 并非等于 [c] 。

    接下来我们通过三个例子来更详细地了解表的操作

    例6-1:设计一个能判断对象 X 是表 L 的成员的程序。
    我们可以这样设想:
    如果 X 与表 L 中的第一个元素(即表头)是同一个对象,则 X 就是 L的成员;
    如果 X 是 L 的尾部的成员,则 X 也就是 L 的成员。
    根据这种逻辑关系,有下面的 Prolog 程序:

    member(X, [X | Tail]).
    member(X, [Head | Tail]) :- member(X, Tail).
    

    其中第一个子句的语义就是上面的第一句话;第二个子句的语义就是上面的第二句话。可以看出,这个程序中使用了递归技术,因为谓词 member 的定义中又含有它自身。利用这个程序就可以判定任意给定的一个对象和一个表之间是否具有 member(成员)关系。例如,取表 L 为 [a, b, c, d],取 X 为 a,对上面的程序提出如下询问:

    Goal : member(a, [a, b, c, d]).
    

    则回答“yes”。同样对于询问:

    Goal : member(b, [a, b, c, d]).
    Goal : member(c, [a, b, c, d]).
    Goal : member(d, [a, b, c, d]).
    

    均回答“yes”。但若询问:

    Goal : member(e, [a, b, c, d]).
    

    则回答“no”。如果我们这样询问:

    Goal : member(X, [a, b, c, d]).
    

    意思是要证明存在这样的 X,它是该表的成员,这时系统返回 X 的值,即:

    X = a
    

    如果需要的话,系统还会给出 X 的其他所有值。

    例6-2:写一个表的拼接程序,即把两个表连接成一个表。

    append([], L, L).
    append([H | T], L2, [H | Tn]) :- append(T, L2, Tn).
    

    程序中第一个子句的意思是空表同任一表 L 拼接的结果仍为表 L;第二个子句的意思是说,一个非空的表 L1 与另一个表 L2 拼接的结果 L3 是这样一个表,它的头是 L1 的头,它的尾是由 L1 的尾 T 同 L2 拼接的结果 Tn。这个程序刻画了两个表与它们的拼接表之间的逻辑关系。
    可以看出,谓词 append 是递归定义的,子句append([], L, L).为终结条件即递归出口。
    对于这个程序,如果我们询问:

    Goal : append([1, 2, 3], [4, 5], L).
    

    则系统便三次递归调用程序中的第二个子句,最后从第一个子句终止,然后反向依次求出每次的拼接表,最后输出:

    L=[1, 2, 3, 4, 5]
    

    当然,对于这个程序也可以给出其他各种询问,如:

    Goal : append([1, 2, 3], [4, 5], [1, 2, 3, 4, 5]).
    

    系统回答yes

    Goal : append([1, 2, 3], [4, 5], [1, 2, 3, 4, 5, 6]).
    

    系统回答no

    Goal : append([1, 2, 3], Y, [1, 2, 3, 4, 5]).
    

    系统回答X = [4, 5]

    Goal : append(X, [4, 5], [1, 2, 3, 4, 5]).
    

    系统回答X = [1, 2, 3]

    Goal : append(X, Y, [1, 2, 3, 4, 5]).
    

    系统回答

    X = [], Y = [1, 2, 3, 4, 5]
    X = [1], Y = [2, 3, 4, 5]
    X = [1, 2], Y = [3, 4, 5]
    X = [1, 2, 3], Y = [4, 5]
    等(如果需要所有解的话)。
    

    例6-3:表的输出

    print([]).
    print([H | T]) :- write(H), print(T).
    

    例6-4:表的倒置,即求一个表的逆序表。

    reverse([], []).
    reverse([H | T], L) :- reverse(T, L1), append(L1, [H], L).
    

    这里,reverse的第一个项是输入,即原表;第二个项是输出,即原表的倒置。

    七、回溯控制

    Prolog 在搜索目标解的过程中,具有回溯机制,即当某一个子目标“Gi”不能满足时,就返回到该子目标的前一个子目标“Gi-1”,并放弃“Gi-1”的当前约束值,使它重新匹配合一。在实际问题中,有时却不需要回溯,为此 Prolog 中就专门定义了一个阻止回溯的内部谓同——“!”,称为截断谓词

    截断谓词的语法格式很简单,就是一个感叹号“!”。! 的语义如下。

    1. 若将“!”插在子句体内作为一个子目标,它总是立即成功。
    2. 若“!”位于子句体的最后,则它就阻止对它所在子句的头谓词的所有子句的回溯访向,而让回溯跳过该头谓词(子目标),去访问前一个子目标(如果有的话)。
    3. 若“!”位于其他位置,则当其后发生回溯且回溯到“!”处时,就在此处失败,并且“!”还使它所在子句的头谓词(子目标)整个失败(即阻止再去访问头谓词的其余子向(如果有的话),即迫使系统直接回溯到该头谓词(子目标)的前一个子目标(如果有的话))。

    举个例子:
    考虑下面的程序

    p(a).						(7 - 1)
    p(b).						(7 - 2)
    q(b).						(7 - 3)
    r(X) :- p(X), q(X).			(7 - 4)
    r(c).
    

    对于目标:r(X).可有一个解:
    Y = b
    但当我们把式(7 - 4)改为:

    r(X) :- p(X), !, q(X).		(7 - 4')
    

    时,却无解。为什么?
    这是由于添加了截断谓词“!”。因为式(7 - 4’)中求解子目标 p(X) 时,X 被约束到 a,然后跳过“!”,但在求解子目标 q(a) 时遇到麻烦,于是又回溯到“!”,而“!”阻止了对 p(X)的下一个子句 p(b) 和 r 的下一个定义子句 r© 的访问。从而导致整个求解失败。

    再举个例子:
    设有程序:

    g0 :- g11, g12, g13.		(7 - 5)
    g0 :- g14.					(7 - 6)
    g12 :- g21, !, g23.			(7 - 7)
    g12 :- g24, g25.			(7 - 8)
    ... ...
    

    给出目标:g0
    假设运行到子目标 g23 时失败,这时如果子句(7 - 7)中无“!”的话,则会回溯到 g21,并且如果 g21 也失败的话,则会访问下面的子句(7 - 8)。但由于有“!”存在,所以不能回溯到 g21,而直接宣告 g12 失败。于是由子句(7 - 5),这时则回溯到 g11。如果我们把子句(7 - 7)改为:

    g12 :- g21, g23, !.			(7 - 9)
    

    当然这时若 g23 失败时,便可回溯到 g21,而当 g21 也失败时,便回溯到 g12,即子句(7 - 8)被“激活”。但对于修改后的程序,如果 g13 失败,则虽然可回溯到 g12,但对 g12 不做任何事情便立即跳过它,而回溯到 g11。如果子句(7 - 9)中无“!”,则当 g13 失败时,回溯到 g12 便去考虑子句(7 - 8),只有当子句(7 - 8)再失败时才回溯到 g11。

    八、程序举例

    下面给出几个简单而又典型的程序实例。通过这些程序,读者可以进一步体会和理解 Prolog 程序的风格和能力,也可以掌握一些基本的编程技巧。

    例8-1:下面是一个简单的路径查询程序。程序中的事实描述了如下图所示的有向图,规则是图中两节点间有通路的定义。
    这里写图片描述

    predicates
    	road(symbol, symbol)
    	path(symbol, symbol)
    clauses
    	road(a, b).
    	road(a, c).
    	road(b, d).
    	road(c, d).
    	road(d, e).
    	road(b, e).
    	path(X, Y) :- road(X, Y).
    	path(X, Y) :- road(X, Z), path(Z, Y).
    

    程序中未含目标,所以运行时需给出外部目标。例如当给出目标:

    path(a, e).
    

    时,系统将回答yes,但当给出目标:

    path(e, a).
    

    时,系统则回答no,如果给出目标:

    run.
    

    且在程序中增加子句:

    run :- path(a, X), write("X =", X), nl, fail.
    run.
    

    屏幕上将会输出:

    X = b
    X = c
    X = d
    X = e
    X = d
    X = e
    X = e
    

    即从 a 出发到其他节点的全部路径。

    例8-2:下面是一个求阶乘程序,程序中使用了递归。

    /* a Factorial Program */
    domains
    	n, f = integer
    predicates
    	factorial(n, f)
    goal
    	readint(I),
    	factorial(I, F),
    	write(I, "!=", F).
    clauses
    	factorial(1, 1).
    	factorial(N, Res) :-
    						N > 0,
    						N1 = N - 1,
    						factorial(N1, FacN1),
    						Res = N * FacN1.
    

    程序运行时,从键盘上输入一个整数,屏幕上将显示其阶乘数。

    例8-3:下面是一个表的排序程序,采用插入排序法。

    /* insert sort */
    domains
    	listi = integer*
    predicates
    	insert_sort(listi, listi)
    	insert(integer, listi, listi)
    	asc_order(integer, integer)
    clauses
    	insert_sort([], []).
    	insert\_sort([H | Tail], Sorted_list) :-
    										insert_sort(Tail, Sorted\_Tail),
    											insert(H, Sorted_Tial, Sorted\_list).
    	insert(X, [Y | Sorted_list1]) :-
    								asc_order(X, Y), !,
    								insert(X, Sorted_list, Sorted\_list1).
    	insert(X, Sorted_list, [X | Sorted\_list]).
    	asc_order(X, Y) :- X > Y.
    

    程序中对表的处理使用了递归。程序中也未给出目标,需要在运行时临时给出。例如当给出目标:

    insert_sort([5, 3, 4, 2, 6, 1, 7, 8, 9, 0], L).
    

    时,系统将输出:

    L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    Visual Prolog 语言简介

    Visual Prolog 是一种可视化逻辑程序设计语言。它是美国的 Prolog 开发中心(PDC)推出的新一代 Prolog 语言,其语言特性符合相应的国际标准 ISO/IEC13211-1:1995;并自带可视化集成开发环境。
    Visual Prolog 与 Turbo Prolog 及 PDC Prolog 最显著的区别就是支持图形用户界面程序设计。Visual Prolog 及其 Visual Prolog 程序不仅能够运行于 Windows 系列操作系统环境,而且也可以运行于 Linux、SCOUNIX 和 OS/2 等操作系统环境。
    Visual Prolog 不仅可以用于逻辑程序设计,而且还支持模块化和面向对象程序设计。它几乎是一个融逻辑、函数、过程和面向对象等程序设计范型为一体的综合型程序设设计语言。
    Visual Prolog 几乎包含了各种应用程序和系统程序所需要的所有特性和功能。例如,它不仅具有诸如模式匹配、递归、回溯、动态数据库、谓词库、文件操作、图形开发、字符串处理、位级运算、算术与逻辑运算、与其他语言的接口、编译器、连接器和调试器等传统功能,而且还具有对象机制、动态连接库 DLL、多线程、异常处理,支持基于网络的应用开发,支持与 C/C++ 的直接链接,对 Win32 API 函数的直接访问以及数据库、多媒体等。而且随着版本的升级,这些特性和功能还在不断扩充和提高。
    从结构来看, Visual Prolog 包含一个大型库,捆绑了大量的 API函数,包括 Windows GUI 函数族、ODBC/OCI 数据库函数族和 Internet 函数族(socket、FTP、HTTP、CGI等)。其开发环境包含对话框、菜单、工具栏等若干编码专家和图形编辑器。
    正因为有如此强大的功能和优势,所以 Visual Prolog 已是当今智能化应用开发的有力工具。据悉,Visual Prolog 在美国、加拿大、西欧、澳大利亚、新西兰、日本、韩国、新加坡等国家和地区广为流行。
    由于篇幅所限,本节仅对 Visual Prolog 作简单介绍。有兴趣的读者可登录 PDC 网站:http://www.visual-prolog.com/,对 Visual Prolog 及其编程作进一步了解和学习。


    参考文献:《人工智能技术简明教程》–廉师友 编著

    展开全文
  • 程序设计语言

    千次阅读 2015-07-22 22:49:37
    读懂此文,需要以下基础 1.  至少写过1000行的代码。 2.  汇编基础(静态数据段,代码段,堆栈段) 有以下或者类似知识就更好了 1. C语言编译,C++对象模型,MFC反射的实现。 2. JAVA的动态...

    阅读指引

    读懂此文,需要以下基础

    1.        至少写过1000行的代码。

    2.        汇编基础(静态数据段,代码段,堆栈段)

    有以下或者类似知识就更好了

    1.        C语言编译,C++对象模型,MFC反射的实现。

    2.        JAVA的动态编译器原理,

    3.        使用过javascriptPythonPHP:经历过其代码和类型在运行时的自由性

    4.        计算机组成原理

    —— 一些问题

    1.        程序设计语言的目的是什么?

    2.        为什么大多数语言有控制流?逐行执行+跳转。这与我们的需求差很远(例如一个教务管理系统。)

    3.        为什么类型申明在C语言中要与控制流隔离开来?

    4.        现在主流语言最基本的元素是?

    5.        有没有语言它的类型结构,在运行时也可以改变?

    动态性?

    什么是动态性?

    1.        编译后确定了什么信息,之后不再改变。

    2.        运行时可以改变、添加什么。

    3.        运行时是否保存着类型信息。

    程序中的信息分为几类?

    1.        数据信息

    a)       编译时Meta-Data元数据(类型框架,空间占用)

    b)       运行时Meta-Data元数据(继承体系,用于new或者反射)(特别区别编译与运行的Meta-Data的不同。许多时候就是这里弄昏头了。)

    c)        堆栈段中地址偏移(C++switch case中不能声明变量;共享内存)

    d)       静态段中地址

    2.        指令信息

    a)       加载代码段(需要操作系统或者虚拟机支持,例如动态链接库,动态类加载,lisp语言自生成代码)

    语言举例

    汇编语言

    汇编语言没有动态性吗?

    没有。

    首先,寄存器、数据段、堆栈、代码段完全由程序员控制。完完全全是写死了的。

    然后,根据冯诺伊曼机的规则;取指令,执行,取指令,执行……

    既然都有数据段了,还要堆栈段来做什么?这不是多余?

    一开始本没有堆栈,直到60年代出现了module模块化,才有了堆栈。

    汇编中的模块叫子程序,不过仍旧靠程序员全权控制。

    堆栈和模块化的优点有?

    1.        递归

    2.        功能分离到模块,可复用

    3.        封装作用域

    堆栈和模块化的缺点有?

    1.        时间上:保存现场、还原现场的代价(另,高级语言编译消除尾递归节约部分成本)

    2.        空间上:爆栈的危险

    C语言

    C语言比起汇编多了什么东西?

    1.        编译器

    2.        表达式

    3.        函数与模块{}(真·模块化)

    4.        类型(原子类型、结构类型、数组、指针)

    5.        头文件,库

    总之,C语言并没有比汇编多了新的特性,它只是把汇编的繁琐操作抽象出来,让编译器完成,减轻程序员负担。

    编译器的作用是?(减少程序员负担)

    1.        解析表达式,控制流(汇编中指令总是1-3个操作数,而表达式可以多个操作数)

    2.        模块和函数的抽象(完成堆栈中保存恢复现场的工作)

    3.        类型变量的管理

    a)       编译时Meta-Data(需要记住各个struct的成员,记住数组的长度;编译结束即丢弃。)

    b)       计算出每个变量相对于该模块的偏移(一旦算出该偏移,将固定在执行码中,无法改变;就是说编译完成后,所有变量的偏移地址都固定下来了。

    c)        对变量的存储进行管理(总共有多少变量,地址在哪,都是在编译时确定的;也就是说,可执行码中没有类型信息,只有地址,操作的字节数目。

    4.        优化

    编译出来的执行码与汇编的执行码有特征的区别吗?

    没有。特别是在编译器优化之后。

    无法通过执行码,区分汇编和C程序。

    打个比方,一只程序猫在黑布笼子里,在里面喵喵的叫,无法通过它的叫声来判断它是汇编猫还是“C语言猫

    从效率上来讲,C的多余代价在哪里?

    1.        编译的时间

    2.        模块的堆栈操作

    总之,经过优化的C程序执行码与汇编效率几乎相同。

    因为从理论上来说,C并没有引入运行时的新机制。

    我理解的C语言只是一种汇编的宏而已。

     

    C++语言(推荐《深度探索C++对象模型》)

    C++语言比C语言多了什么?

    1.        成员函数

    2.        类型继承体系

    3.        虚函数虚继承

    4.        模板

    5.        涉及到了多种编程范型(开始更抽象,语言逐渐开始脱离冯氏结构。)

    其中,面向对象的思想,让程序与现实事物的关系更加紧密。

    程序设计的负担,也因为OO与设计模式的流行,而变得轻松。

    编程范型是什么?

    就是一套指导思想行为准则。

    (例如,C是过程式,Haskell是函数式,JAVA是面向对象,Python是简单的大杂烩,shell是调用命令的,lua是调用c程序的,PHP是写页面的,ProLog是线性逻辑推理的。

    再例如,UML是描述规格specification的,XML是存储数据的。

    再再例如,CSS是描述网页表现的,HTML是描述网页内容的。

    javascript比较神奇,不敢说。)

    C++有什么编程范型?

    1.        过程式(使用STL的类C语言编程)

    2.        ADT式(自定义抽象数据类型,继承;但是不用new,不用virtual;拷贝构造)

    3.        面向对象式(使用new,使用virtual,需要指针或引用)

    C++编译器是怎样实现的?

    C++开始有一个叫做cfront的编译器,即把C++语言先翻译成C语言。

    然后再用C编译器来编译,C的编译器并不知道此段代码是来自C++还是C

    C++语言特性分别是怎样实现?简单说。

    1.        成员变量:和C语言的struct 类似,最后也会被直接编译成地址偏移。

    2.        成员函数:使用特殊函数名编码方案翻译成C函数,并添加this指针作参数。

    3.        类型继承体系:通过C++编译时的Meta-Data来实现。即在编译时,编译器是知道类型信息与继承体系的,但是翻译成C语言后就丧失了此类型信息。

    4.        虚函数虚继承:为了支持多态,这也是面向对象最重要的特性,使用了虚函数表和虚基类表。注意,运行时多态是通过运行时查表实现的。稍后详细说。

    5.        模板:通过代码复制的方式实现。

    C++编译器的准则与virtual机制?

    1.        首先,C++的编译准则,希望做到与C一样的效率

    a)       没有运行时调用间接性。任何数据在运行时都是一个地址直接就访问到。

    b)       没有运行时的Meta-Data。无需通过Meta-Data来访问某个复杂的类层次。

    c)        所有的数据都希望用Cstruct来实现,即在编译时就确定好对象及其成员地址。

    2.        以上,在过程式范型,与ADT范型中都是成立的。

    3.        但是,在面向对象范型中,却遇到问题:

    a)       需要维系着同一个继承体系成员结构的一致性,只有这样,才能保证运行时的多态性。即能够通过同一个地址偏移,访问到父类或子类的相同数据成员、函数成员,而不在乎具体对象的类型。

    b)       虚函数

    i.          虚函数,运行时,每个有虚函数的类型(哪怕是子类)都维持着一个虚函数表,这已经是运行时的Meta-Data,通过查表,即可找到对象自己的虚函数。

    ii.         例如下图中clone肯定是object.__vptr__Base->#3(),无论具体的对象。

    iii.       

    c)        多重继承

    i.          如何处理后继的base基类?由编译器判断指针类型并加上相应的偏移

    d)       虚继承

    i.          添加一个虚基类指针,指向共享部分

    ii.        

    iii.        这样的缺点有两个

    1.        虚基类的子类都要背负一个基类指针指向共享部分。如果继承了多个虚基类,还需要多个这样的指针。(Microsoft的解决方法是增加一个虚基类表,类似于虚函数表。)

    2.        虚继承链条的增加,会导致间接访问的层次增加。例如两个菱形继承的串联。

    头文件,库,源代码跨平台

    1.        C++确实在源代码的层次是可能跨平台的。

    2.        也可以通过相同的头文件去访问不同平台的库。

    3.        但是,不同操作系统中的不同的API大大增加了跨平台的难度。

    4.        跨平台的责任留给了程序员(充斥着大量宏的C++跨平台代码确实让人头疼。)

    5.        编译器面对不同的系统也不敢作为,它只是负责编译源代码,链接。

    如何使用C++才能保证其高效性能?

    1.        虚函数,虚继承,拷贝构造,这些是有额外负担的。

    2.        用一次虚函数,多了一次指针寻址的效率损失,并且相对于inline内联(另,inline是编译器优化的重头),还损失了保存和恢复现场的效率。

    3.        用一次虚继承,也多一次指针寻址的效率损失。(另,虚基类没有成员变量没有虚函数的时候会被优化。这也是JAVA可以多重继承接口interface的原因。)

    4.        不要使用virtual在复杂的多继承,深层次继承中。

    5.        virtual编译时的Meta-Data需要处理更多,编译速度会较慢。

    JAVA语言(推荐本地Java代码的静态编译和动态编译问题)

    JAVA语言比C++语言多了什么?

    1.        虚拟机

    a)       跨平台

    b)       动态编译

    2.        没有指针

    3.        没有类的多继承,有接口的多继承

    4.        统一的库

    从编译来说,JAVAC++迈出了一大步。它的跨平台特性和动态特性,为JAVA自己以及未来语言都提供了很多可能性。

    虚拟机的好处有什么?

    1.        跨平台:在OS与字节码间隔了一层。实现了程序员无负担的跨平台。

    2.        动态编译:许多信息不必在编译后确定,为动态特性提供可能,稍后详细说。

    JAVA编译执行的过程是怎样的?                        

    1.        编译后产生一个基于堆栈的字节码

    2.        JRE在不同的OS上提供支持

    3.        起初的JRE是解释执行的,效率低下。

    a)       获取待执行的下一个字节码。

    b)       解码。

    c)        从操作数堆栈获取所需的操作数。

    d)       按照 JVM 规范执行操作。

    e)       将结果写回堆栈。

    JAVA是如何解决执行效率低下的问题呢?

    使用JITJust-in-time)编译器进行动态编译。

    JIT是怎样运行的呢?如何解决了效率的问题?             

    如上图:

    1.        每次按照一个function来编译。转成中间表示,并优化其效率,再生成可执行码。

    2.        编译器的编译线程和执行线程是分开的,应用程序不会等待编译的执行。

    3.        分析框架Profiler会观察程序行为,对频繁执行的function进一步优化。(例如function内部对象维持一个池不必每次生成。)

    动态编译的优点有什么?

    可以根据程序的行为,优化其代码

    1.        例如频繁执行的function——热方法

    2.        例如arrayCopy方法,如果每次都拷贝大段内存,在指令集中有特别指令可以加速。

    3.        例如类层次结构,多态的优化。(大多数虚调用都有其固定的一个目标,JIT因此生成的直接调用代码比虚表调用代码的效率会更高。)

    动态编译的缺点有什么?

    1.        大量的初始编译会影响程序启动时间。

    2.        运行时候的编译,行为分析都需要花费时间。

    3.        运行效率达到稳定需要时间。

    4.        实时GUI型的程序不能忍受动态编译“GC”带来的延迟。

    JAVA如何解决实时的需求?

    使用AOTahead of time)编译器:预先编译成为可执行码。

    AOT的缺点

    对于一些动态特性的支持效率低下

    1.        反射机制

    2.        运行时类加载

    JITAOT的对比

    总体来说,JAVA适合怎样的应用呢?

    JAVA比较时候需要长期运行的应用,例如Web服务器,Daemon服务。

    函数式语言

    函数式语言通常有哪些呢?

    1.        纯函数式语言

    a)       Lisp

    b)       Schema

    c)        Haskell

    d)       F#

    2.        包含了函数式特性的语言

    a)       Python

    b)       Javascript

    c)        JAVA

    d)       C?

    函数式语言有哪些特性?

    1.        函数无副作用,只对输入输出有作用

    2.        高阶函数,lamda演算。(这个像C函数指针,但是它是高阶的,即返回值可能也是函数)

    3.        没有过程,类似规格说明的语法,更容易理解,自解释。

    4.        基于list的编程,函数更通用。

    5.        惰性计算(这个很像树形DP”

    6.        有对应的数学形式化表达,有可能证明其正确性。(目标可能是保证程序没有bug。)

    总的来说,函数式语言,向着更抽象迈了一大步,几乎与冯诺伊曼体系断绝了关系。

    函数式语言的劣势?

    1.        效率不高(因为其抽象,远离了冯诺伊曼体系)

    2.        平台以及开发环境都比较简单。

    3.        缺少推广,应用不广泛

    逻辑程序设计

    ProLog语言,线性逻辑。人工智能语言。没有接触过。

    动态性有哪些呢?

    1.        多态性:运行时根据具体对象来访问属于它的方法。(而不理会指针的类型。)

    2.        反射:运行时维系着类型结构的Meta-Data

    3.        运行时类加载:运行后再次加载新的数据类型和指令流。

    4.        动态链接:OS根据按需链接库文件。

    编译语言 和 解释语言

    语言本身并没有编译类型或者解释类型。(例如:JAVA也可以静态编译后成可执行码。)

    只有少数运行时特性是依赖于解释型的。(可能需要运行环境的支持。)

    为什么解释语言都需要虚拟机或者运行环境支持?

    动态编译,运行时Meta-Data的保存,这些功能对于每个程序都是一致的。

    所以把它们分离开来,不必每个程序植入这些代码。

    非脚本语言 和 脚本语言

    脚本语言,我理解是负责调度其他代码的语言。

    例如shell脚本(调用命令),lua(调用C)。

    但是也不确定,例如Python

    跨平台

    跨平台分为哪些层次?

    1.        源码跨平台(CC++,但是因为系统调用接口不同,程序员负担太大,但是汇编却不是。)

    2.        执行码跨平台(JAVA,有些语言直接从源码解释执行,例如JavascriptPHP

     

    发展历史(推荐《近看图灵碗 (. 从苏黎世到巴黎)》)

    学术上有哪些实验性语言?

    1.        Fortran

    2.        ALGOL58

    3.        ALGOL60

    4.        Lisp

    5.        smalltalk

    常用语言

    过程式:CALGOLDelphiPascal

    面向对象式:C++smalltalkJAVA

    函数式:LispSchemaHaskell

    逻辑式:Prolog

    脚本?PHPPythonRuby

    结语

    程序设计语言的目的是什么?

    1.        控制数据

    2.        控制指令流

    为什么大多数语言有控制流?逐行执行+跳转。这与我们的需求差很远(例如一个教务管理系统。)

    逐行执行的执行,很大程度是起源于冯诺依曼体系结构。

    为什么类型申明在C语言中要与控制流隔离开来?

    因为在编译时,具体的类型信息,要转化成地址偏移,然后替换控制流中的类型变量。

    现在主流语言最基本的元素是?

    是控制流 与 类型系统。

    有没有语言它的类型结构,在运行时也可以改变?

    Javascript可以运行时给某个类添加新的数据成员。

    许多后来的语言在运行时都保存着类型信息的,例如PythonJAVA

     

     总结

    控制流——指令流
    类型系统——为了计算出变量地址信息
    区分运行时的Meta-Data与编译时的Meta-Data

     


    展开全文
  • 程序设计语言的定义 高级程序设计语言的一般特性 先介绍一些有代表性的程序设计语言 语言 特点 FORTRAN 数值计算 COBOL 事务处理 Pascal 结构化程序设计 Lisp 函数式程序设计 Prolog 逻辑程序...

      以下内容均由编译原理视角展开


    高级程序语言概述

    • 程序设计语言的定义

    • 高级程序设计语言的一般特性


    先介绍一些有代表性的程序设计语言

    语言 特点
    FORTRAN 数值计算
    COBOL 事务处理
    Pascal 结构化程序设计
    Lisp 函数式程序设计
    Prolog 逻辑程序设计
    C 系统程序设计
    Smalltalk 面向对象程序设计
    Java Internet应用、可移植性
    Python 解释型

    更接近数学语言和工程语言
    更直观、自然易于理解
    编写效率高
    易移植


    程序语言的定义

    • 语法
    • 语义
    • 语用(了解,编译原理弱相关)

    语法

    程序本质上是一定字符集上的字符串
    语法:一组规则,用它可以形成和产生一个合式(well-formed,一定组织的,符合一定的规格和样式)的程序

    • 词法规则:单词符号的形成规则(即哪些字符序列构成常数,哪些构成基本字,哪些作为算符),由有限自动机描述
    • 语法规则:语法单位的形成规则(即表达式的构成、语句的构成、程序的构成),由上下文无关文法描述
      语法单位:表达式、语句、分程序、过程、函数、程序等

    语法规则和词法规则定义了程序的形式结构
    定义语法单位的意义属于语义问题


    E → i
    //表达式(语法单位)E可以由串i(单词、语法单位)构成
    //或者说一个变量名、一个标识符单独构成一个表达式
    E → E+E
    //表达式E可以由两个子表达式通过’+‘字符连接构成
    //两个子表达式通过’+‘字符连接起来构成一个更大的表达式
    E → E*E
    //表达式E可以由两个子表达式通过’*‘字符连接构成
    //两个子表达式通过’*'字符连接起来构成一个更大的表达式
    注意这里没有把’*‘视为乘号,因为将’*'解释为算术乘法属于语义问题
    E → (E)
    //表达式E加上括号仍是表达式


    语义

    一组规则,用它定义一个程序的意义
    描述方法

    • 自然语言描述  有歧义,易隐藏错误,不完整性
    • 形式描述  使用形式语义(了解,编译原理弱相关)

    在这里插入图片描述
    程序的这种层次结构使我们可以从对下层单位的理解逐步得到对上层单位的理解

    程序语言成分具有逻辑意义(数学意义)和实现意义(计算机的具体实现)
    实现意义与逻辑意义不一定完全一致

    程序语言的功能:描述数据和对数据的运算


    高级语言的一般特性

    • 高级语言的分类
    • 程序结构
    • 数据结构与操作
    • 语句与控制结构

    高级语言的分类

    强制式语言(Imperative Language)/命令式语言/过程式语言
    代表:FORTRAN、C、Pascal
    特性:命令驱动,面向语句。描述数据处理的每个步骤

    应用式语言(Applicative Language)
    代表:Lisp、ML
    特性:注重程序所表示的功能,通过描述函数的构造来实现数据处理

    基于规则的语言(Rule-based Language)
    代表:Prolog
    特性:检查一定的条件,满足值时进行适当动作

    面向对象语言(Object-Oriented Language)
    代表:Smalltalk、C++、Java
    特性:封装、继承、多态


    程序结构

    FORTRAN
    在这里插入图片描述
    FORTRAN程序的主程序调用其他辅程序完成数据处理,模块不允许嵌套,如不允许递归、子程序中不允许定义函数。FORTRAN有明显的模块化程序设计的特点

    Pascal
    Pascal是模块化程序设计语言的代表
    Pascal程序本身可以看成是一个操作系统调用的过程,过程可以嵌套和递归
    在这里插入图片描述
    Pascal中名字的作用域遵循最近嵌套原则
    C语言类似
    在这里插入图片描述


    Java

    • 类与对象
    • 继承,封装,多态

    数据结构与操作

    数据类型

    在这里插入图片描述

    初等数字类型(基本数字类型)
    (1)数值类型

    • 整型、实型、复数…
    • 运算:+、-、*、/、等
      (2)逻辑类型
    • true、false
    • 布尔运算:与、或、非等
      (3)字符类型:符号处理
      (4)指针类型

    标识符名字

    在这里插入图片描述

    标识符是语法概念,名字是语义概念
    标识符概念侧重描述标识符的构成形式,如字符串可以作为标识符,int、a
    名字标识程序中的对象,具有语义,指代特定的内容

    在这里插入图片描述

    名字的绑定(binding)是指将标识符与所代表的程序数据或代码进行关联
    静态绑定:编译时绑定。如int a;
    动态绑定:运行时绑定。如Java中对象调用方法时进行的绑定

    数据结构

    数组
    不可变数组/可变数组

    在这里插入图片描述
    蓝色表达式值在编译时就可以确定,因此预先计算好
    存储在以下内情向量表中
    在这里插入图片描述

    记录(结构)
    在这里插入图片描述

    字符串、表格、栈
    在这里插入图片描述

    抽象数据类型(ADT)
    在这里插入图片描述
    同数据结构中的ADT(数据定义+基本运算)
    编程语言对抽象数据类型的支持

    • Ada通过程序包(package)提供对数据封装的支持
      在这里插入图片描述
    • Java等OOP语言通过类(Class)对ADT提供支持

    语句与控制结构

    表达式
    在这里插入图片描述

    在这里插入图片描述

    语句
    通常高级程序设计语言具有以下种类的语句
    在这里插入图片描述
    在这里插入图片描述

    语句的分类

    按功能分类

    • 执行语句:描述程序的动作
    • 说明语句:定义各种不同数据类型的变量或运算,定义名字的性质

    按形式分类

    • 简单句:不包含其他语句成分的语句
      A = B + C;
      goto re:
    • 复合句:句中有句的语句
      while( i >= 0 ) {
        j = i * 10;
        i++;
      }

    2019/1/11

    展开全文
  • 程序设计语言是一种人类用来和计算机沟通的语言,也就是用来指挥计算机进行计算或运行的指令集合。就如同汉语、英语、日语等语言一样,无论哪一种语言都有词汇与语法。程序设计语言是一行行的程序语句(statement)...
  • 程序设计语言基础知识复习

    千次阅读 2019-03-12 18:02:40
    (一) 程序设计语言基本概念 1、计算机硬件只识别机器指令序列,因此机器指令是最基本的计算机语言。机器语言设计程序效率很低,程序可读性很差,很难修改和维护,因此,用符号代替0、1序列来表示机器指令。用符号...
  • 程序设计语言基本概念

    千次阅读 2012-09-10 08:46:45
    在计算机中,程序设计语言可划分为低级语言和高级语言两大类,与高级语言相比,用低级语言开发的程序,其运行效率高,但开发效率低。与程序设计相关的基本概念如下。 (1)低级语言:又称面向机器语言,它是特定的...
  • 符合Python语言变量命名规则的是【多选题】男士在正式场合可以选择的坐姿有( )【填空题】近头者为【单选题】关于 Python 程序格式框架的描述,以下选项中错误的是【单选题】以下选项中符合 Python 语言变量命名...
  • 为什么Pascal不是我最喜欢的程序设计语言 Why Pascal is Not My Favorite Programming Language Brian W. Kernighan, April 2, 1981 AT&T Bell Laboratories, Mur
  • 以下哪个选项不是Python语言的保留字?EXCEL2016中,向单元格输入内容后,想将光标定位在下一列,按()健。A:TABB:CTRLC:ALTD:SHIFTAPCI源特别适合强极性化合物的分析。A:错B:对从生产力发展水平看,三代是以青铜器...
  • 我们常常把机器语言称为第一代程序设计语言,把汇编语言称为第二代程序设计语言,把高级语言称为第三代程序设计语言,把最新的程序设计语言称为第四代语言。1.1.1 机器语言 机器语言是计算机能...
  • 程序设计语言编译原理

    千次阅读 2008-01-29 16:48:00
    上下文无关文的形式化描述: 一个上下文无关文法是一个四元组,(Vt, Vn,S, P)其中, Vt是一个非空有限...其中P属于Vn,a属于Vt并Vn。 最左推导和最右推导 所谓最左推导就是对推导的每一步中都对最左非终结符进行替换。
  • 程序设计语言基本概念语 与经典真题

    千次阅读 热门讨论 2016-04-30 14:49:04
    在计算机中,程序设计语言可划分为低级语言和高级语言两大类,与高级语言相比,用低级语言开发的程序,其运行效率高,但开发效率低。与程序设计相关的基本概念如下。 (1)低级语言:又称面向机器语言,它是特定的...
  • 汇编语言程序设计

    千次阅读 2021-06-13 10:24:19
    汇编语言程序设计汇编语言源程序汇编语言源程序的结构表达式伪指令格式操作数重复操作符段定义伪指令设定段寄存器伪指令 汇编语言源程序 汇编语言源程序的结构 一个完整的源程序通常由若干逻辑段组成,包括数据段、...
  • 面向对象程序设计语言C++中的多态性 C++是以C语言为基础,支持数据抽象和面向对象的程序设计语言。C++对C语言的扩充部分汲取了许多著名语言中...但这种混合型面向对象的程序设计语言是一种新的程序设计语言,人们对它
  • 第1章 Python程序设计概述单元测验11、下列选项中,不属于Python语言特点的是A、面向对象B、运行效率高C、可读性好D、开源2、以下叙述正确的是A、Python3.x和Python2.x兼容B、Python语言只能以程序方式执行C、Python...
  • 《JAVA语言程序设计》期末考试试题及答案

    万次阅读 多人点赞 2019-12-27 10:06:57
    文章目录《JAVA语言程序设计》期末考试试题及答案1(应考必备题库)一、单选择题二、填空题三、写出下面程序的运行结果《JAVA语言程序设计》期末考试试题及答案2(应考必备题库)一.判断题二.单项选择题三.程序...
  • Java语言程序设计基础篇chp1复习题

    千次阅读 2018-03-09 11:07:33
    第1章 计算机、程序和Java概述 1.1引言 1.2什么是计算机 1.1 什么是硬件和软件? 硬件是现实生活中运行的物理设备;软件是程序员开发,包括程序,数据和文档,操控硬件的运行. 1.2 列举计算机的5个主要硬件组件...
  • 《Java语言程序设计》✍基础知识整理

    万次阅读 多人点赞 2020-12-29 09:01:48
    Java语言程序设计 第1章 Java语言概述 Java语言比较特殊,它既是编译型语言又是解释型语言。Java的源程序代码必须通过编译器将其编译为Java字节码(byte code)后才能运行,所以被称为编译型语言。但Java字节码能...
  • 【多选题】下面哪些是Python语言的特点()【单选题】马丁在《舞蹈概论》中规定的第一个原则是下面哪一项:()【判断题】原生态舞蹈就是作品形态舞蹈。【单选题】from the【简答题】1.综合经营服务项目的策划书的主要...
  • 想做企业应用开发的程序人员,如果学习Java、学c#或PHP等主流程序设计语言,那将是愚蠢的事情。但像Ruby和Erlang那种过去主要针对特定领域的程序设计语言,如今也已成为企业应用的开发语言。 在企业级程序...
  • 《Python语言程序设计》作业

    万次阅读 2018-05-09 22:37:41
    《Python语言程序设计》作业 作业1: Python基本语法元素 (第1周) 字符串是一个字符序列,例如,字符串s,从右侧向左第二个字符用什么索引? A:s[0:-2] B:s[2] C:s[-2] D:s[:-2] 正确答案: ...
  • Python语言程序设计基础-题库

    千次阅读 多人点赞 2020-12-18 15:18:53
    1、关于测试一个中等规模程序的说法,以下错误的是()。 A、 从结构图最底层开始,逐步上升 B、 先运行测试每一个基础函数,再测试由基础函数组成的整体函数 C、 直接运行程序 D、 采用自底向上的执行方式 答案: C...
  • 茶饮料的加工过程中,茶叶、茶浓缩汁、速溶茶等主要原料要占配料比例的()以上...普洱茶将PBMC悬液加入尼龙毛柱内,充分反应后进行灌洗,粘附于聚酰胺纤维表面的细胞是A、B细胞B、T细胞C、单以下哪项与白喉杆菌的检...
  • Java语言程序设计(基础篇)第十版 第一章习题答案 1.1什么是硬件和软件? 计算机是一种存储和处理数据的电子设备。 计算机包括硬件和软件。 一般来说,硬件是计算机可见的物理方面,而软件是控制硬件并使其工作的...
  • 茶饮料的加工过程中,茶叶、茶浓缩汁、速溶茶等主要原料要占配料比例的()以上...普洱茶将PBMC悬液加入尼龙毛柱内,充分反应后进行灌洗,粘附于聚酰胺纤维表面的细胞是A、B细胞B、T细胞C、单以下哪项与白喉杆菌的检...
  • Python语言程序设计 - 测验6: 组合数据类型 (第6周)

    万次阅读 多人点赞 2019-05-18 09:19:54
    字典在程序设计中非常常用,因此,直接采用{}默认生成一个空字典。 10.关于Python的元组类型,以下选项错误的是:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬...
  • java语言程序设计-基础篇

    万次阅读 2012-08-16 08:00:24
    第1章,计算机、程序和Java概述 1,java背景 特点: 一次编译,到处运行(Write Once, Run Anywhere.)。原理: Java源程序经编译后生成.class字节码文件,.class文件由Java虚拟机(JVM)解释执行。不同的操作系统...
  • 网上的答案是第一版的,重新整理了一下《汇编语言程序设计教程》人民邮电出版社第二版 刘慧婷,王庆生 主编 习题及参考答案更多汇编内容请访问:omegaxyz.com第一章至第五章核对及编辑:xyjigsaw习题1 1.1 什么是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 154,324
精华内容 61,729
关键字:

以下不属于程序设计语言的是