第5章应用软件开发平台 有了操作系统这个软件运行协同用户操作平台,人们就可以使用计算机了。终端用户 可以在上面运行应用程序,例如用文字处理软件编写文档、用播放器软件看电影、用电子表 格软件管理自己的信息等。程序员可以利用其提供的系统调用接口编写应用程序,获得操 作系统平台提供的服务。但是,对于程序员来说,仅有操作系统提供的系统调用接口是不行 的,他们需要有一个能够编辑程序代码的软件组织源程序,需要有编译软件将用高级语言编 写的程序转换成机器指令,以便其能被计算机执行,还需要有帮助他们发现和纠正程序中的 逻辑错误的调试工具。除了编辑器、编译器、调试器这些基本工具之外,现代应用程序开发 常常是基于某种共性软件设施进行的。那些软件设施为复杂应用系统的开发和运行提供了 极大的便利,它们的表现形式一般为某种API(ApplicationProgramInterface,应用程序接 口), 即从应用程序中可以直接调用的函数库,Java中的各种框架就可以看成这样的设施。 这些实际上是支持代码重用的软件设施,加上各种工具就形成了应用软件开发平台。这个 平台就好像是布满各种原材料和零配件的生产车间或装配场地,加上钳子、锤子等各种必需 的工具就能形成一套完备的系统。 应用软件开发平台本身也是软件,其作用就是帮助应用软件设计人员更有效地开发出 应用软件,它本身并没有直接的最终应用目的。有些开发平台是通用的,例如CORBA;而 有些是与特定领域相关的,例如SAP,它能够有效地支持企业管理类软件的开发。本章介 绍程序员开发应用软件时所用的应用软件开发平台。特别值得指出的是,随着开发平台的 发展,人们将相关工具和可重用的代码统一组织起来,形成了集成开发环境,程序员在其中 工作能够更自如地进行软件开发,大大提高了工作效率。 本章首先从程序设计语言说起,因为这是程序开发的基础,也是应用软件开发平台的功 能得以体现的对象;然后简要介绍开发工具和集成开发环境中的一些基本概念,旨在让读者 对应用软件开发平台形成一个总体轮廓。至于各种开发工具和集成开发环境的具体使用, 则不属于本书的内容。 5.高级程序设计语言 1 现在人们多采用高级程序设计语言编写应用软件。不过,计算机世界中有几千种不同 的高级语言。这些高级语言在语义、语法以及功能上都有着很大不同,因而它们也都有着各 自不同的编译器。与之对应的就是程序员看到的不同的应用软件开发平台。因此,本章对 应用软件开发平台的介绍首先从高级语言入手。 计算机世界中的高级语言非常多,这些语言产生的时间、背景不同,设计的目标也不同。 程序员会根据所做项目的情况,有时还会根据自己的开发背景选择程序设计语言。经典的 程序设计语言有FORTRAN 、Pascal、BASIC 、C、COBOL 、Ada、C++、Java、Delphi、Python 等。在这些语言中,早期较重要的有FORTRAN 、Pascal、BASIC 以及C语言。而现在最常 第5章应用软件开发平台 用的是Python、Java、C++以及C。FORTRAN 是最早产生的高级程序设计语言,它是为工 程计算而设计的,因而它非常适合处理公式以及进行各种数值计算。BASIC 是一种非常容 易学的语言,它现在仍然在被使用,只不过用的是它的高级后代VisualBasic。而Pascal是 一门系统地体现结构化程序设计思想的高级语言。因此,它曾经作为各个大学计算机系必 修课程的教学语言。后来的Delphi就是由Pascal语言发展而来的。C语言是为了编写 UNIX 而设计的一种语言。因为是用来写操作系统的语言,所以它具有低级语言的一些特 征,能够像汇编语言一样对硬件进行操作。但同时它也具有高级语言的特性,具有结构语 句,也比较接近人的语言。因为这些特点,C语言现在仍然是比较常用的一种程序设计语 言。现在的操作系统(如UNIX 、Linux)就是用C语言编写的。现在C语言更多地被用在 嵌入式程序设计等与底层硬件比较接近的应用软件的开发中。 C语言属于结构化程序设计语言。人们把程序的任务分解为一个一个功能,分别加以 实现,称之为函数,程序的主流程就是调用这些功能函数完成任务。这种程序设计模式也被 称为面向过程的程序设计,因为程序的主体是一个求解任务的过程。但是,随着程序设计规 模的扩大以及软件业的发展,人们的思想发生了变化。人们发现,如果把设计应用软件的事 情看作在创造一个个对象或者说物体,那么就可以更好地模拟现实世界。程序设计就是设 计一个个具有属性和行为的对象。应用软件因此不再是函数的集合体或者解题过程的描 述,而是变成了对象的集合体。程序员在程序中定义对象以及对象的属性和行为,然后通过 对象之间相互作用产生需要的结果。在这种思想指导下,产生了两个非常流行的程序设计 语言———C++和Java。 从名字上看就知道C++和C是有关系的,而且好像应该是C语言的超级加强版,因为 它有两个加号。事实也是这样的。C++保留了C语言的语法和语句。C语言的程序在C+ + 环境中可以继续运行,这是因为在设计C++时C语言已经非常流行,有不计其数的程序是 用C语言开发的。C++比C语言要丰富很多,它增加了面向对象的一系列支持,如类、模 板、名字空间、异常等概念,以及运算符重载、引用,还有在任何地方声明变量的能力等。因 此,C++的功能更强大。 Java是目前主流的开发语言之一,它也是一个面向对象的程序设计语言。不过,另一 个追求目标使它与C++有很大的不同。这个目标就是跨平台。我们知道,有很多种不同的 操作系统平台,不同的操作系统提供的终端用户接口、程序员级接口以及底层的运行机制都 是不一样的。因而在不同操作系统上运行的应用软件也是不同的,它们必须适应自己底层 的平台环境。这些编译后的应用软件,甚至在源程序中,都带有与操作系统相关的元素,如 对特定系统接口的调用。所以,通常在一个操作系统上设计开发的应用软件是不能在另一 个操作系统上运行的。例如,Linux操作系统的应用软件就不能在Windows操作系统平台 中运行,反之亦然。而Java的跨平台目标就是要让应用软件可以在任意操作平台上运行。 Java并没有采用像C++那样的传统程序设计思路,即把高级语言源程序编译成可执行 的机器指令代码文件,然后再执行。因为这样编译的结果是针对编译器所在的具体操作系 统平台的,可执行文件也就被限制在特定的平台上了。为了实现跨平台的目标,Java语言 的源程序写完之后,会被转换成一种Java定义的中间状态的字节码形式。同时,Java语言 的设计人员还设计了一个在操作系统之上的称为Jaa虚拟机(aaVitacie, vJvrulMahnJVM) 的平台层。Java虚拟机实际上也是一个程序,它运行在操作系统平台之上,其作用就是把 179 va程序必须在 让Ja va程序有一个统一的运行平台。可以 Java字节码翻译成程序当时所在运行平台的机器指令形式并执行。因此,JaJava虚拟机上才能运行。也就是说,Java字节码到不同运行平台的映射是由Java虚拟机完 成的。Java虚拟机屏蔽了不同运行平台的差异, 看出,运行Java程序时,每条指令都是经过Ja 释执行。而C++等语言编写的应用程序被编译后生成的可执行文件的代码都是机器指令, 所以执行程序时,CPU可以直接逐条完成指令。因此,Ja 行的程序慢,这是Java为跨平台付出的代价。 最后要特别说一下最近超级流行的一个“ VanRossum于20世纪年代末在荷兰国家数学和计算机科学研究所设计的。Py 动态的、面向对象的脚本语言,是一门解释性高级编程语言。它最初被设计用于编写自动化 脚本,就是Shell脚本。但随着版本的更新和语言新功能的添加,它被越来越多地用于独立 项目和大型项目的开发。Python源代码遵循GPL协议,由一个核心开发团队维护。 Python的优点是非常容易上手,关键字少, 支持。尤其是随着人工智能研究的兴起, 此,最近几年Python已经上升为第一位的程序设计语言。 Python也是跨平台的,这一点和Java一样。因此Python在Linux、UNIX、Windows、 嵌入式系统中都有很好的应用。Python也可以嵌入C\C+ ................ .................................. .. .... .. ................................ .................................................................................... 目前常用的高级程序设计语言有Python、JC语言是面向结构的程序设计语言。 C++和Java都是面向对象的程序设计语言。 Java有跨平台的特性。 Python对大多数人工智能模型都提供了非常好的支持。 ................ 重点提 5.2开发工具和集成开发环境 5.2.1单独的开发工具 由于编写程序的需要,在程序设计的历史进程中,逐渐形成了各种供程序员使用的工 具。这些工具中最主要的有3类,即用来编辑源程序的编辑软件、把高级语言编译成机器语 言的编译软件以及调试程序的调试软件。这些工具构成了应用软件开发平台的基本元素。 不过,刚开始时应用软件开发平台中的这些软件工具都是独立的,它们之间并没有必然 的联系。程序员需要自己决定使用哪个工具完成某个阶段的工作。某个阶段候选的工具也 不只有一个。例如,编辑程序时,程序员可以选择ema 辑软件都可以用来编辑程序。在这些编辑器中, 对程序设计有特殊的支持,如用特殊的颜色显示程序设计语言中的特殊保留字。但有些编 辑软件就是普通的编辑器,它们的目标就是帮助用户写一般的文档, 事本软件一样。但是,只要程序员愿意,他们同样可以用这些编辑器输入程序。采用单独的 开发工具,在程序员编辑完源程序后,他们需要把代码以某种扩展名的文件形式保存起来。 va虚拟机的转换之后再执行的,这被称为解 va程序的执行要比其他编译后执 古老的”语言———Python。Python是由Guido th on是一种 语法结构简单,但同时却有非常广泛的标准类库 on对大多数模型都提供了非常好的支持。因 Pyth +程序中作为脚本使用。 示 ava、C++、C等。 cs,也可以选择vi。实际上,有很多编 有些是专门为编写程序而设计的。它们会 就像Windows中的记 180 第5章 应用软件开发平台 18 1 特殊的扩展名用来表明该源程序是用什么语言写的,例如.c表示是C语言的源程序,这样 做通常是后面要用到的编译程序的要求。接下来,程序员需要用其所在平台上的编译软件 编译源程序。每种语言在支持的平台上都会有对应的编译器。例如,在Linux平台上,C语 言的编译器称为gcc。程序编译成功后,并不意味着程序的运行结果是正确的。因为程序 中可能存在逻辑性错误。为此,当程序并没有产生预期的结果时,程序员需要调试程序以确 定到底哪里有问题。这时程序员会选择调试工具帮助他们解决问题。例如,如果在Linux 系统上,程序员通常会选择一个称为gdb的调试器调试程序。尽管程序员在开发应用软件 的过程中,每个阶段都有相应的工具可以使用,但是这些工具并没有被关联在一起。程序员 必须知道他要用什么工具做下一步的工作。这就好像生产车间里放着很多可用的工具,但 是,操作员必须自己决定接下来用什么来做事。使用单独的开发工具,程序员有很大的自由 度,如果他们不喜欢某个调试器,那么完全可以换一个更好的。 因为单独的开发工具基本上都是早期出现的,所以多是基于文本命令界面的。这里要 说的是,尽管这些工具出现得很早,但是,它们的功能一点儿也不差,而且这些工具仍处于不 断发展进步之中,所以现在仍然有很多程序员喜欢使用这些工具。下面通过几个典型的工 具体验一下这些单独的开发工具的特点以及在文本界面下开发应用软件的过程。 首先是编辑器,这里以vi为例。在Linux的Shell提示符后输入vi,就进入了vi编辑 图5-1 vi 编辑器 器,如图5-1所示。vi就是visual,意思是马上就可以看到 编辑的结果,这是相对于以前一些不能够马上见到编辑结 果的编辑器来说的,当然现在绝大多数编辑器都支持所见 即所得了。不过,在vi出现时这个特性还是比较先进的。 vi支持用不同的颜色表示程序中不同的内容,例如关 键字include和其他语句的颜色就不同。函数printf()的 参数是一个用双引号括起来的字符串"hello,world",这 个字符串也用另一个颜色显示。这样程序员就可以看出 双引号中间的字符串是什么,可以防止程序员忘记了写后 面的双引号,造成程序的编译错误或者运行中的逻辑错误。vi不支持鼠标,也没有命令菜 单。它的命令和需要编辑的内容全是通过键盘输入的。为了区分键盘输入的内容是编辑命 令还是被编辑的内容,vi设置了命令和编辑两个模式。按Esc键即进入命令模式。在命令 模式下,键盘的输入被解释成命令。例如,输入 :q 表示退出vi,输入 :w 表示存盘。而按字母键a表示在当前光标后输入内容,输入这个命令后,vi即进入编辑模 式,如图5-2所示。这时屏幕下方的“--插入--”也提示了这时可以往文本中添加内容。 例如,从键盘输入“:q”,这两个字符就会出现在编辑内容中,如图5-2所示。这时按Enter 键,光标会移到下一行。接下来如果按Esc键再输入“:q”,就会看到这两个字符出现在屏 幕的下方,如图5-3所示,表明现在处于命令模式,输入了退出命令。如果接下来按Enter 键,那么vi就会结束并退出。 图5-2 vi 的编辑模式图5-3 vi 的命令模式 vi设置了很多命令。例如,在命令模式下,按x键会删除光标处的字符,输入dd会删除 光标所在的行,输入s会删除光标处的字符并进入输入模式,输入S会删除光标所在的行并 进入输入模式。在命令模式下,按y键(yank,复制)就可以复制光标所在行;移动光标,然后 再按p键(put,放置),就可以把这一行粘贴到光标所在位置。按斜杠(/)键,就可以在后面 输入要查找的内容。例如,在图5-4中,在/后输入printf然后按Enter键,就可以看到如 图5-5所示的查找结果。vi还有很多命令,这里不一一介绍,可以在网上找到很多它的详细 用法介绍,使用时可以查看。 图5-4 vi 的查找命令图5-5 vi 的查找结果 vi的不支持鼠标、通过键盘输入命令这两个特性让初次接触它的用户感觉很不方便。 在某种程度上可以说vi的界面并不友好。这是因为它是特定条件下的产物,受制于当时的 条件。不过,时至今日,vi仍然没有退出舞台,那是因为键盘输入命令实际上也有它的优 势,那就是程序员的手不用在鼠标和键盘之间切换。对于熟悉命令的人来说,这样确实很省 力、方便,速度非常快。因而,现在仍然有很多程序员喜欢vi,仍在使用它。 源程序编辑完毕之后,要想让它能在计算机上运行,必须转换成机器指令。在Linux的 命令行界面上,最常用的编译器是gc 。gc 是GNUCompilerColection的简称。假定前 182 第5章 应用软件开发平台 18 3 面的文件被保存为hello.c,如果要编译前面编辑的文件,那么可以输入以下命令: gcc hello.c -o hello 命令中的-o是gcc的选项,选项后的参数hello表示生成的可执行文件的名字为hello,否则 gcc会产生默认的文件a.out。图5-6显示出一个错误提示,指出文件hello.c的12行有错 误。这是因为前面在文件的末尾输入了“:q”。去掉这一行,重新编译,即成功地生成可执行 文件hello。运行hello,屏幕上显示出“Hello,world”,如图5-7所示。这正是该程序的正确 输出。 图5-6 gcc 编译文件hello.c 图5-7 成功编译文件hello.c 并运行 除了-o之外,gcc还有很多选项供程序员使用。在Shell的命令提示符后输入 gcc -help 图5-8 gcc 的选项 可以看到这些选项,如图5-8所示。程序员可以按照自己的需要选择这些选项,让gcc完成 不同的工作。例如,在前面的编译过程中,gcc实际上按顺序完成了预处理、编译、汇编、连 接等几个工作。可以用选项把前面gcc一次完成的4个步骤分开来做。首先进行预处理。 预处理过程主要处理源文件中的#ifdef、#include和#define等命令。预处理使用的选项 184 是-E,表示只进行预处理,不做编译、汇编和连接。预处理过程输入的文件是C 语言源文 件。预处理过程会产生一个中间结果,用-o选项指定存放预处理结果的文件名为hello.i。 这样预处理hello.c的具体命令即为 gcc -E hello.c -o hello.i 接下来对预处理的结果进行编译。编译过程的输入就是预处理产生的中间文件hello.i。 编译后生成汇编语言文件,所以文件的扩展名应该是.s。这时用gcc的选项-S,意思是只做 编译,不做汇编和连接,命令如下: gcc -S hello.i -o hello.s 下面对编译后的文件进行汇编,将其转换成机器指令文件。在Linux下机器语言文件 的扩展名为.o。使用如下命令: gcc -c hello.s -o hello.o 这时生成的文件就是机器指令文件了,但是它仍然不能够执行,因为其中有一些对库函数的 调用需要进行连接。最后,用下面的命令将机器指令文件hello.o与其他机器指令文件或库 文件连接成一个可执行的二进制代码文件: gcc hello.o -o hello 上述整个过程如图5-9所示。 如果程序中存在问题,那么程序执行的结果就可能不像程序员期望的那样。这时程序 员需要把问题找出来,调试工具会帮助程序员完成这件事。例如,如果在前面的hello.c文 件中增加一段代码,希望能够输出1~5这几个数字的和,如图5-10所示。但是编译后程序 的执行并没有输出预想的结果,如图5-11所示。 图5-9 用gcc 进行预处理、编译、汇编和连接图5-10 更改后的hello.c 图5-11 hello.c 编译后运行的结果 第5章 应用软件开发平台 18 5 检查程序好像也没有问题。这时,程序员就可以让调试器帮忙了。在Linux命令行界 面中常用的调试器是gdb。要想使用gdb,必须在编译源程序时使用-g选项,这样编译过程 中就会为调试产生必需的辅助信息。用-g选项重新编译程序之后,就可以运行gdb对生成 的可执行文件进行调试了,如图5-12所示。在图5-12中,运行gdb之后,在gdb的提示符 (gdb)后输入gdb的调试命令break,即 break 12 break命令的作用是在程序中设置断点。上面这条命令的意思就是在hello程序的第12行 设置断点。第12行就是for循环语句的那行。 接下来,用gdb命令run执行hello程序,如图5-13所示。程序将执行到第12行的断 点处。这时输入gdb命令next,让程序向下执行这条语句,即for语句,如图5-14所示。再 用gdb命令print查看变量i的值,从图5-14中可以看到变量i的值是1,这是一个正确 的值。 图5-12 运行gdb 调试hello 图5-13 执行gdb 命令run 接着再输出变量sum 的值,如图5-15所示。可以看到,变量sum 的值是一个很大的 数,即1073828704。现在可以初步判断是变量sum 的初值出了问题。 输入调试命令next,让程序继续执行下一条指令,即sum=sum +i。然后再输出变量 i和sum 的值,发现i变为2,sum 的值被加了1,如图5-16所示。这说明程序到这里的逻辑 15 查看变量sum 的值 t结束调试过程。重新用vi打开hc源程序,发现变量s elo.um r循环之前增加给sum赋初值0的语句,如图5-17所示。 如图5-18所示。其实,这个例子如 这里只是为了说明gdb的功能。对于复杂的 图5-14 执行gdb命令next和print 图5- 是正确的。用gdb命令qui 没有赋初值就使用了。因此,在fo 然后再编译、执行,发现程序的执行结果就是正确的了, 果不用gdb帮忙,程序员也可能会找出问题, 程序,程序员没有gdb的帮助就会很难或者花费很多时间才能找到问题的所在。 图5-16 执行下一条指令 图5- 图5-17 修改hello. c 源程序 18 重新编译、执行hello 程序 186 第5章应用软件开发平台 单独的开发工具赋予了程序员很大的灵活性,他们可以按照自己的喜好选择工具完成 应用软件的开发。不过,这些单独的开发工具一般都是在文本命令行界面下的。因此,一般 经验比较丰富、接触计算机较早的程序员采用这些工具的比较多,因为他们开始接触计算机 时,计算机以文本命令行界面为主,因而他们比较习惯这种界面。而对于新生代的程序员来 他们更喜欢图形界面的操作平台。让他们自己选择工具,一些人会不知所措。 .............. ................................ .................................................................................... 编辑、编译、调试工具是应用软件开发平台的基本元素。 单独的开发工具可以让程序员更自由地选择自己喜欢的工具。 单独的开发工具多是基于操作系统的文本命令界面的。 g和gdb。 .............. 示 为了克服单独的开发工具的缺点,不再让程序员自己寻找和组合开发工具,人们把软件开 发过程中必需的工具整合在一起,形成了集成开发环境。这样,程序员只要启动一个集成环境 软件就可以在其中完成全部的程序开发步骤了。这就好像把生产车间里面零乱的工具组装成 一个机床。在程序设计的历史中出现了很多集成开发环境。这是因为有很多种不同的程序设 在每个操作系统平台上都会有一个或者几个集成开发环境。 +的集成开发环境有VisualC++、TurboC/C++、C++ r、CodeBlocks、DevC++等,Java的集成开发 o、NetBeans、JDeveloper、IntelliJIDEA、Java o等。其中一些开发平台可以支持多种语言,如Eclipse、Qt 这些集成开发环境的一些早期版本也是在文本命令行界面的操作平台上出现的,如 这些集成开发环境就多是图形界面的了。这些集成 但是主要界面框架和基本功能是一致的。它们都支 这些功能的用法也基本类似。这就好像各种汽车的样 基本的组成都是车体和车轮,主要功能都是能在路上行驶。 都是通过控制方向盘、离合、刹车等装置实现驾驶。 只要熟悉了一种集成开发环境,就很容易快速掌握另 r的界面。QtCreator是一个跨平台的集成开发环 cOS桌面操作系统上运行。在QtCreator高级代码编辑器 n和其他语言编写代码。 图5-19反映出目前多数集成开发环境的面貌。界面中间的窗口是程序的编辑窗口,程 序员可以在其中输入代码。左侧的窗口会显示出当前项目(或解决方案)涉及的各种文件。 用于显示项目中包含的类以及类的属性等内 这里可以输出程序编译和连接的结果、程序调试的中间结果等。 界面上方是菜单栏和工具栏。菜单栏和工具栏反映了开发环境的主要功能,例如从菜单栏 说, .................................. .. .... ..重点提 ux上最常见的编辑、编译、调试工具分别是vi、 c Lin 5.2 集成开发环境 2. 计语言,而一般针对某一种语言, 例如,在Windo ws操作系统上,C+ er、Vi alStudioCode、VisualStud io、QtC Build reato su 环境有JDK 、Eclipse、JB uilder、WebSphereStudi Workshop、SunJavaStudi Creator等。 TurboC 。后来随着图形界面的普及, 开发环境在界面和用法上有一些不同, 持编辑、编译、调试、运行等基本功能, 子和功能会有一些不同,但是, 车的驾驶方式也不相同,不过,总的来说, 集成开发环境与此非常类似。因此, 一种。图 5 19是集成开发环境QtC 境,可在Windows、Lin reato ux和ma 上可以用C++、 QML 、JavaScript、Py tho 除此之外,左侧窗口中通常还有一些标签窗口, 容。界面下方是输出窗口, 187