linux系统及编程基础课后答案 下载本文

第1章 习题答案

1. 什么是Linux?

答:Linux是一款优秀的计算机操作系统,支持多用户、多进程、多线程,实时性好,功能强大且稳定。同时,它又具有良好的兼容性和可移植性,被广泛应用于各种计算机平台上。作为Internet的产物,Linux操作系统由全世界的许多计算机爱好者共同合作开发,是一个自由的操作系统。

2. Linux的主要特点是什么?

答:Linux具有UNIX的所有特性并且具有自己独特的魅力,主要表现在以下几个方面: ? 开放性 ? 多用户 ? 多任务 ? 出色的稳定性能

? 良好的用户界面:Linux向用户提供了两种界面:用户界面和系统调用界面。

? 设备独立性:设备独立性是指操作系统把所有外部设备统一当作文件来看,只要安装它们的驱动程序,任

何用户都可以像使用文件那样操作并使用这些设备,而不必知道它们的具体存在形式。

? 丰富的网络功能:完善的内置网络是Linux的一大特点,Linux在通信和网络功能方面优于其他操作系统。

其他操作系统不包含如此紧密的内核结合在一起的联接网络的能力,也没有内置这些联网特性的灵活性。而Linux为用户提供了完善的、强大的网络功能。 ? 可靠的安全性

? 良好的可移植性:可移植性是指将操作系统从一个平台转移到另一个平台,使它仍然能按其自身的方式运

行的能力。

3. Linux的主要组成包括什么? 答:Linux主要组成为:

Linux内核(Kernel):内核(Kernel)是系统的心脏,是运行程序和管理硬件设备的内核程序,决定着系统的性能和稳定性,实现操作系统的基本功能。

Linux的Shell:Shell是系统的用户界面,提供用户与内核进行交互操作的一种接口。Shell是一个命令解释器,它解释由用户输入的命令并且把他们送到内核执行。Shell编程语言具有普通编程语言的很多特点,用这种编程语言编写shell程序与其他应用程序具有同样的效果。

Linux 文件系统:文件系统是文件存放在磁盘等存储设备上的组织方法。通常是按照目录层次的方式进行组织,用户能够从一个目录切换到另一个目录,而且可以设置目录和文件的权限、文件的共享程度。

Linux 实用程序(utilities)和应用程序(Applications):标准的Linux系统都有一套成为应用程序的程序集,包括文本编辑器、编程语言、X Window、办公套件、Internet工具、数据库等。

4. Linux与Windows的主要区别是什么? 答:主要区别:

(1)Linux的应用目标是网络

Linux的设计定位于网络操作系统。虽然现在已经实现Linux操作系统的图形界面,但仍然没有舍弃文本命令行。由于纯文本可以非常好地跨越网络进行工作,所以Linux配置文件和数据都以文本为基础。 (2)可选的GUI

目前,许多版本的Linux操作系统具有非常精美的图形界面。Linux支持高端的图形适配器和显示器,完全胜任与图形相关的工作。但是,图形环境并没有集成到Linux中,而是运行于系统之上的单独一层。这意味着用户可以只运行GUI,或者在需要时使用图形窗口运行GUI。 (3)文件名扩展

Linux不使用文件名扩展来识别文件的类型,这与Windows操作系统不同。Linux操作系统是根据文件的头内容来识别其类型。为了提高用户的可读性,Linux仍可以使用文件名扩展,这对Linux系统来说没有任何影响。Linux

通过文件访问权限来判断文件是否为可执行文件,任何一个文件都可以赋予可执行权限,程序和脚本的创建者或管理员可以将它们识别为可执行文件,这样做有利于安全,使得保存到系统上的可执行文件不能自动执行,可以防止许多脚本病毒。 (4)重新引导

在使用Windows系统时,也许已经习惯出于各种原因而重新引导系统(即重新启动),但在Linux系统中这一习惯需要改变。一旦开始运行,它将保持运行状态,直到受到外来因素的影响,比如硬件故障。实际上,Linux系统的设计使得应用程序不会导致内核的崩溃,因此不必经常重新引导,所以除了Linux内核之外,其他软件的安装、启动、停止和重新配置都不用重新引导系统。如果用户确实重新引导了Linux系统,问题很可能得不到解决,甚至还会使问题更加恶化,因此在学习Linux操作系统时,要克服重新引导系统的习惯。

另外,可以远程地完成Linux中的很多工作,只要有一些基本的网络服务在运行,就可以进入到那个系统。而且,如果系统中一个特定的服务出现了问题,用户还可以在进行故障诊断的同时让其他服务继续运行。当用户在一个系统上同时运行多个服务的时候,这种管理方式更为重要。 (5)命令区分大小写

所有的Linux命令和选项都区分大小写。 5. 什么是Linux的内核版本和发行版本?

答:Linux的内核版本是指在Linus Torvalds领导下开发小组开发出的系统内核的版本号。内核版本号由3个数字组成,形式如下:

major.minor.patchlevel

? major:目前发布的Kernel主版本号。

? minor:为次版本号,一般来说minor位为偶数的版本标明这是一个可以使用的稳定版本,如2.6.4;minor

位为奇数的版本一般加入了一些新的内容,不一定很稳定,是测试版本,如2.5.11。 ? patchlevel:表示对当前版本的修补次数

发行版本是一些组织或厂家将Linux系统内核与应用软件和文档封装起来,并提供一些安装界面和系统设定管理工具的一个软件包的集合。目前已经有了几百种发行版本。

6. Linux系统的用户有哪些?

答:Linux是多用户系统,用户分为根用户(系统管理员)和普通用户两大类。

每个用户在系统中都有唯一的用户名称,该用户名称为用户账号,使用户使用系统的凭证。根用户(系统管理用)又称为超级用户,用户账号为root,在系统中拥有最高权限,主要负责系统的管理工作。普通用户账号有根用户创建,命名时不能以数字和下划线作为第一个字符。普通用户是系统的使用者,只在自己的目录下工作,没有系统管理权限。

7. 什么是运行级别?Linux有哪些运行级别?

答:所谓运行级别就是操作系统当前正在运行的功能级别。这个级别从0到6,具有不同的功能,在/etc/inittab 文件中定义。七个运行级别为:

1) 0 - 关机(千万不要把initdefault 设置为0 ) 2) 1 - 单用户模式

3) 2 - 多用户模式,但是没有 NFS 4) 3 - 完全多用户模式 5) 4 - 没有用到 6) 5 - X11

7) 6 - 重启(千万不要把initdefault 设置为6 ) 8. 如何更改默认的运行级别?

答:运行级别可以由超级用户通过 telinit 命令来转换,此命令可以将转换信号传递给init,告诉它切换到哪个运行级别。也可以通过修改/etc/inittab文件来进行缺省运行级别的修改。

9. 如何登录和注销? 答:(1)登录

图形界面:图形提示用户名+口令 字符界面:输入用户名+口令 (2)注销

图形界面:运行“系统->注销”命令 字符界面:logout或ctrl+d或exit 10. 如何安全关闭系统? 答:图形界面:系统?关机

文本界面:有shutdown、halt、reboot、init。 11. 简述X Window的原理。 答:X Window系统由三部分构成。 (1)X Server:控制实际的显示与输入设备

(2)X Client:向X Server发出请求以完成特定的窗口操作。 (3)通信通道:负责X Server与X Client之间的通信。

X Server是用来控制实际的显示设备和输入设备(键盘和鼠标或其他输入设备)的软件。X Serve可以建立窗口、在窗口中画图形、图像和文字;响应X Client的需求。它不会自己执行动作,只有在X Client提出请求后才完成动作。每一个显示设备只有一个唯一的X Server。X Server一般由系统的供应厂商提供,用户通常无法修改。对操作系统而言,X Server只是一个普通的用户程序而已,因此很容易更换一个新的版本,甚至可编译运行由第三方厂商提供的原始程序。

X Client是指使用系统窗口功能的一些应用程序。把X下的应用程序称作X Client,原因是它们是X Server的客户,X Client要求服务器应它的请求完成特定的动作。X Client无法直接影响窗口或显示,它们只能向X Server发送请求,让X Server来完成它们的需求。用户可以使用不同来源的X Client:一些是由系统提供的(例如时钟) ,一些来自于第三方厂商,一些是用户为了特殊应用而编写的自己的客户程序。

通信通道是X Server和X Client之间传递信息的通道,凭借这个通道,X Client发送请求给X Server,而X Server借助于它向X Client回送状态及一些其他的信息。

第2章 习题答案

1.简述Linux文件系统的特点。

答:Linux文件系统具有如下5个主要的特点。

(1)Linux文件系统采用树形结构,从根目录root (/)开始。

(2)Linux的虚拟文件系统允许众多不同类型文件系统共存,并支持跨文件系统的操作。

(3)Linux的文件是无结构字符流式文件,不考虑文件内部的逻辑结构,只把文件简单地看作是一系列字符的序列。

(4)Linux的文件可由文件拥有者或超级用户设置相应的访问权限而受到保护。

(5)Linux把所有的外部设备都看做文件,可以使用与文件系统相同的系统调用和函数来读写外部设备。 2.什么是虚拟文件系统,Linux为什么采用虚拟文件系统?

答:虚拟文件系统是Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口;同时,它也提供了内核中的一个抽象功能,允许不同的文件系统共存。虚拟文件系统既没有文件,也不直接管理文件,它只是用户与实际文件系统之间的接口。它并不需要保存在永久存储介质中,只是在需要时由内核在内存中创建起来的一个文件系统,所以叫做虚拟文件系统。

Linux 允许众多不同类型的文件系统共存,并支持跨文件系统的操作,这是由于虚拟文件系统的存在。系统中所有的文件系统不但依赖虚拟文件系统共存,而且也依靠虚拟文件系统协同工作。 3.在所用的Linux系统上,根目录下主要含有哪些子目录,各子目录的含义?

答:

? /bin:存放二进制可执行命令目录;

? /home:用户主目录的基点目录,默认情况下每个用户的主目录都设在该目录下,如默认情况下用户user01

的主目录就是/home/user01;

? /lib:存放标准程序设计库目录,又叫动态链接共享库目录,目录中存放的文件作用类似windows里的.dll

文件;

? /etc:存放系统管理和配置文件目录;

? /dev:存放设备特殊文件目录,如声卡文件、磁盘文件等;

? /usr:最庞大的目录,存放应用程序和文件目录,其中包含如下目录:

/usr/local/bin:存放本地增加的命令目录; /usr/local/lib:存放本地增加的库目录; /usr/X11R6:存放X window目录; /usr/bin:存放众多的应用程序目录;

/usr/sbin:存放超级用户的一些管理程序目录; /usr/doc:存放linux文档目录;

/usr/include:存放Linux下开发和编译应用程序所需头文件目录; /usr/lib:存放常用的动态链接库和软件包的配置文件目录; /usr/man:存放帮助文档目录;

/usr/src:存放源代码目录,Linux内核的源代码就放在/usr/src/linux子目录中; ? /proc:虚拟目录,是系统内存的映射,可直接访问这个目录来获取系统信息; ? /root:系统管理员的主目录;

? /var:存放系统产生的经常变化文件目录,例如打印机、邮件、新闻等假脱机目录、日志文件、格式化后

的手册页以及一些应用程序的数据文件等等; ? /tmp:存放公用临时文件目录。 4.什么是文件?Linux下主要有哪些类型文件?

答:文件是指由创建者定义的,具有文件名的一组相关元素的集合,文件可以是文本文档、图片、程序等。

Linux下的文件类型包括:普通文件,也称为常规文件,是Linux中最一般格式的文件,包括系统文件、用户文件和库函数;目录文件,是由文件目录信息构成的特殊文件,目录文件的内容不是应用程序和数据,而是用来检索普通文件的目录信息;设备文件,在Linux中输入输出设备被看做特殊文件,设备文件分两类,字符设备文件和块设备文件;符号链接文件,是一种特殊类型的文件,它的内容只是一个字符串,该字符串可能指向一个存在的文件也可能什么都不指向。

5.什么是工作目录、用户主目录 ?

答:工作目录是用户在登录到Linux系统中后所处于的目录,也称为当前目录。工作目录用―.‖表示,其父目录用―..‖表示。可用pwd命令查看工作目录,可用cd命令改变工作目录。

用户主目录是系统管理员增加用户时创建的(以后也可以改变),每个用户都有自己的主目录。普通用户的主目录在/home下,root用户作为系统管理员,因为身份特殊所以有自己的主目录,在/root下。

6.根据下图,圆圈代表目录,方框代表文件,当前目录为n,用相对路径法和绝对路径放分别写出文件g、o、z的路径。

答:文件g的相对路径为:../../e/g;绝对路径为:/e/g

文件o的相对路径为:../../e/i/o;绝对路径为:/e/i/o 文件z的相对路径为:./v/x/z;绝对路径为:/f/n/v/x/z 7.举例说明cat、more和less命令的用法。

答:cat命令可以把多个文件连接后输出到标准输出(屏幕)或加 “> 文件名”输出到另一个文件中。如显示当前目录下文件testfile1的内容可用如下命令:cat testfile1。

more命令显示文本文件的内容,一次显示一屏,满屏后停下来,可按键继续。如显示/etc/profile文件的内容,每屏10行可用如下命令:more -10 /etc/profile。

less命令与more命令相似,分屏显示文件的内容。less命令允许用户向前(PageUp)或向后(PageDown)浏览文件。如文件/etc/profile中查找字符串“HOSTNAME”,并从该字符串后显示可以如下命令:less -p HOSTNAME /etc/profile。

8.将主目录下的文件.bashrc复制到/tmp下,并重命名为bashrc,用命令实现上述过程。 答:cp ~/.bashrc /tmp/bashrc。

9.举例说明比较文件的异同使用哪些命令?

答: comm命令对两个已经排好序的文件进行比较,comm从文件1和文件2中读取正文行进行比较,生成三行输出:在两个文件中都出现的行,仅在文件1中出现的行,仅在文件2中出现的行。如比较当前目录下的已排好序的两文件memo1和memo2的异同用命令:comm memo.1 memo.2。

diff命令比较文本文件,并找出它们的不同。diff命令比comm命令更强大,不要求文件预先排好序。如果两个文件完全一样,该命令不显示任何输出。如比较当前目录下的未排好序的两文件memo1和memo2的异同可用如下命令:diff memo.1 memo.2。

10.举例说明怎样对文件进行压缩和备份?

答:对文件压缩的命令主要有bzip2和gzip;对文件备份的命令主要有tar。

如用bzip2命令压缩当前目录下的文件memo.1:bzip2 memo.1。 用gzip命令压缩压缩当前目录下的文件memo.1:gzip memo.1。

用tar命令将当前目录下的文件memo.1、memo.2、memo.3备份到文件memo.tar中: tar cvf memo.tar memo.1 memo.2 memo.3。

11.将/home/stud1/wang目录做归档压缩,压缩后生成wang.tar.gz文件,并将此文件保存到/home目录下,用命令实现上述过程。

答:,实现此任务的tar命令格式为tar zcvf /home/wang.tar.gz /home/stud1/wang 。 12.在Linux下有一文件列表内容如下:

(1)要完整显示如上文件类别信息,应该使用什么命令? 答:ls -l

(2)上述文件列表内容的第一列内容“lrwxrwxrwx”中的“l”是什么含义?对于其它类型的文件或目录还可能出现什么字符,它们分别表示什么含义?

答;“l”表示该文件是符号链接文件。“-”表示该文件是普通文件,“d”表示该文件是目录,“b”表示该文件是块设备文件,“c”表示该文件是字符设备文件。

(3)上述文件列表内容的第一列内容“lrwxrwxrwx”中的第一、二、三个“rwx”分别代表什么含义?

答:第一个“rwx”表示该文件的文件主人具有读写执行的权限,第二个“rwx”表示该文件的主人同组用户具有读写执行的权限,第三个“rwx”表示该文件的其他用户具有读写执行的权限。 (4)上述文件列表内容的第五列内容“6”是什么含义? 答:表示该文件的链接数。

(5)上述文件列表内容的最后一列内容“nurse2->nurse1”是什么含义? 答:表示文件nurse2是符号链接文件,其链接到文件nurse1。

13.在根目录下创建目录gdc,并设置权限为gdc的主人具有读写执行权限,与主人同组用户可读写,其它任何用户则只能读。

答:mkdir /gdc;chmod u=rwx,g=rw,o=r。

14.在用户user的主目录下新建目录software,并将路径/etc下所有以h开头的文件及目录拷贝到software中,用命令实现上述过程。

答:mkdir /home/user/software; cp /etc/h* /home/user/software

15.什么是符号链接,什么是硬链接?符号链接与硬链接的区别是什么?

答: 符号链接文件包含到另一个文件的路径名。当用户需要在不同的目录下用到相同的文件时,不需要在每一个目录下都存放该文件,只要在某个固定的目录下存放,然后在其它的目录下用命令链接(link)它即可,不必重复的占用磁盘空间,

硬链接指通过索引节点来进行的链接。在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),文件属性保存在索引结点里,系统是通过索引节点(而不是文件名)来定位每一个文件。在Linux系统中,可以通过命令让多个文件名指向同一索引节点,这多个文件即为硬链接文件。

符号链接可以建立对于文件和目录的链接,硬链接只能建立对文件的链接;符号链接可以跨文件系统,即可以跨磁盘分区,硬链接不可以跨文件系统;符号链接的文件类型位是l,链接文件具有新的i节点,硬链接的文件类型位是“-”,且硬链接文件的i节点同被链接文件相同。

第3章 习题答案

1.vim有几种工作模式?各模式之间如何转换? 答:

shell提示符启动vim退出vim命令模式文本插入命令Esc键插入模式末行模式自动返回:键

2.进入vim有几种方式?退出vim有几种方式? 答:

进入:vi或者vi+filename

退出:命令模式ZZ,末行模式:q或者q!

3.在命令模式下如何将光标定位到指定行?如何删除文本中的字符、行?如何查找匹配某个模式的行? 答:

定位到指定行:nG。

删除字符:命令模式下x;删除行:命令模式下dd。 查找:命令模式下/+pattern。

4.在末行模式下如何复制一段文本?移动一段文本?替换一段文本? 答:

末行模式下复制:n1,n2 co n3。移动:n1,n2 m n3。替换:n1,n2 s/pattern1/pattern2 5.举例说明插入命令、附加命令和打开命令的区别。 答:

插入:当前光标前插入字符。附加:当前光标后插入字符。打开:当前行下一行行首插入字符。 6.将文本To err is human. a computer.变成To err is human,在vim中如何操作? 答:

命令模式下:将光标移到computer前,按dw。

7.将文本There is something wrong here中的wrong删除,在vim中如何操作? 答:

命令模式下:将光标移动到wrong前,5x。

8.使用哪个命令可以在当前工作编辑环境中向后搜索以单词hello开始的行? 答:

使用命令方式下:/hello。

9.使用哪个命令可以将所有出现的“HELLO”替换为“hello”? 答:

末行命令:1,$ s/hello/HELLO/gc 10.如何撤销上次操作? 答:

命令方式下:u

第4章 习题答案

1. 简述Linux系统引导过程。 答:

加电加载BIOS预引导(LILO/GRUB)加载系统内核映像(kernel boot)rc.sysinitinitrc建立用户接口loginShell 2. 在Linux系统中运行级别分为几级?分别有何特点? 答:

系统的运行级别是系统运行时所处的一种状态,不同的运行级别在用户登录及使用上有一些不同。Linux系统提供7种运行级别,7种运行级别定义如下:

运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动。 运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆。 运行级别2:多用户状态(没有NFS支持)

运行级别3:完全的多用户状态(有NFS),标准运行级别,登录后进入命令行模式。 运行级别4:系统未使用,保留。

运行级别5:多用户模式,X11控制台,登录后进入图形GUI模式。

运行级别6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动。 3. 关闭系统的shutdown、halt、reboot、init命令各有何特点? 答:

(1)shutdown命令

使用shutdown命令可以安全的关闭Linux系统,shutdown命令是用shell编写的程序,必须由超级用户才能执行,shutdown命令执行后,会以广播的形式通知正在系统中工作的所有用户,系统将在指定的时间内关闭,请保存文件,停止作业,注销用户。shutdown命令的语法格式:shutdown [-fFhknrc(参数名称)] [-t 秒数] 时间 [警告信息]

(2)halt命令

halt是最简单的关机命令,相当于shutdown –h组合,halt执行时,kill掉所有应用程序,然后调用系统指令sync,

用户执行Linux命令sync将所有内存信息通过文件系统写入硬盘,然后停止内核。Halt命令格式:# halt

(3)reboot命令

reboot命令的执行过程与halt基本类似,不同的是halt是用于关机,而reboot是关机后引发系统重启。命令格式:# reboot

(4)init命令

init进程是所有进程的祖先,其进程号始终为1,init命令主要用于系统不同运行级之间的切换,切换的工作是立即完成的。

4. Linux系统用户的类型都有哪些? 答:

(1)超级用户 (2)普通用户 (3)特殊用户

5. Linux用户管理有哪几种方法? 答:

Linux系统对用户管理一般提供三种方法: (1)通过GUI方式管理

(2)通过修改用户管理相关配置文件管理 (3)通过系统管理命令管理

6. Linux用户管理相关的文件有哪些?解释文件内容。 答:

在Linux系统中,主要使用/etc目录下的三个文件来维护用户及用户组的相关信息。 (1)/etc/passwd文件,其中存放关于账户相关的信息

(2)/etc/shadow文件,/etc/passwd的影子文件,来存放用户的加密口令。 (3)/etc/group文件,其中存放用户组相关的信息资料。

7. 使用useradd命令添加用户student,然后使用userdel删除该用户。 答:

useradd student passwd student userdel student

8. Linux系统中设备如何标识? 答:

用户是通过文件系统与设备接口的,所有设备都作为设备文件,设备文件的文件名一般由两部分构成,第一部分是主设备号,第二部分是次设备号。其中,主设备号代表设备的类型,可以唯一地确定设备的驱动程序和界面,如hd表示IDE硬盘,sd表示SCSI硬盘,tty表示终端设备,lp表示打印机等;次设备号代表同类设备中的序号,如hda表示IDE主硬盘,hdb表示IDE从硬盘,tty0表示编号为0的终端,lp0表示第一个打印机等。

9. 如何进行u盘挂载?卸载? 答:

挂载u盘设备(假设u盘标识为sdb1)到/mnt/usb目录。 #mount /dev/sdb1 /mnt/usb 10. 什么是进程? 答:

“进程”(Process)来描述程序动态执行过程。

11. 练习使用进程管理命令对进程进行查看、调度、终止。 答:

ps,at,kill

12. Linux系统的日志分为哪几类? 答:

Linux系统中的有三个主要的日志子系统: (1)连接时间日志子系统 (2)进程统计日志子系统 (3)错误日志子系统

13. Linux系统中主要的日志文件有哪些?解释其文件内容。 答:

(1)/var/log/dmesg

/var/log/dmesg文件保存内核启动的信息,在这个文件里,用户可以看到内核和各种驱动程序的加载,加载硬件驱动时系统也会显示出相应的信息。

(2)/var/log/messages

/var/log/messages文件是Linux系统中最全面的log文件,它记录了内核和应用程序发生错误时的信息和系统运行的一般信息。

第5章 习题答案

1. 为什么Red Hat Enterprise Linux更适合于做网络操作系统?

答:Linux应网络而生,先天最大的优点在于其作为服务器的强大功能。Red Hat Enterprise Linux更是小红帽公司的旗舰产品,面向企业用户,针对网络应用做出优化,可靠性,安全性高。作为主流的Linux网络操作系统,现在已成为Linux服务器应用市场的主流。

2. Ping命令的返回值有哪些?各有什么含义?

答:有三个返回值值icmp_seq,ttl,time。icmp_seq表示当前是第几个icmp包,ttl表示最大生存周期(time to live),3. 使用Nslookup www.dlpu.edu.cn命令进行域名解析的全过程?

答:nslookup是DNS客户端,当在本机终端输入Nslookup www.dlpu.edu.cn之后,本机先发DNS查询数据包到本机所指定的DNS服务器,DNS服务器收到查询包后进行解析,如果本地网络内的DNS服务器无此条记录,本地DNS服务器会向互联网上的其它DNS服务器提出解析请求,得到最终结果,如没有就返回错误。本地DNS在缓存此条记录的同时把此解析结果返回给本机。本机得到了www.dlpu.edu.cn的真实IP或者是无法解析的结果。

4. NFS和samba有什么异同点?

答:两者都是为了实现网络文件共享,不同点就是NFS是文件系统,samba是网络协议;NFS只能用于Unix,5. 有哪几种虚拟Web主机技术,各起什么作用?

答:有三种:基于域名,基于IP地址和基于端口号。基于域名可以实现多个域名分别指向同一台主机上不同WEB应用;基于IP可以给主机设置多个不同的IP区别不同的WEB应用;基于端口可以让主机通过不同的端口来区分不同的WEB应用。

6. 邮件服务器有哪几种服务器?哪些是发邮件,哪些是收邮件的?

答:邮件服务器有三种:smtp,pop,imap。Smtp是发邮件服务器,pop,imap是收邮件服务器,其中pop和imap7. 练习邮件服务器的配置过程,查找资料学会outlook邮件客户端的设置和使用?

答:以用outlook设置test@126.com这个邮箱为例,第一步得了解126.com收发邮件服务器域名或者地址,启动outlook填入用户名和邮箱地址,设置pop服务器为pop.126.com,设置smtp服务器为smtp.126.com下一步下一相比允许将邮件收到本地客户端。

Linux类系统内部的共享,而samba还可以在Unix,Linux类系统与windows系统之间实现文件共享。 time表示这个icmp包从发出到返回所花的时间。例如:icmp_seq=1 ttl=64 time=2.03 ms。

步。最后别忘了在工具—-帐户里选中此邮箱并且右键属性设置其smtp服务器需要验证,不然会导致发邮件发不出去。

8. 练习FTP服务器的配置过程,学会字符界面下ftp命令连接服务器上下载文件的基本使用方法。

答:以通过ftp命令连接ftp.dlpu.edu.cn为例:先在cmd中输入ftp进入到ftp命令行状态。输入open ftp.dlpu.edu.cn回车连接上服务器,在提示下输入用户名anonymous,密码随便,成功后输入dir查看远程服务器上的文件目录,用cd 目录名称的方式进入到下一级目录,用cd ..回到上一层目录,用pwd查看当前在服务器的那个目录下,用lcd查看本地当前目录和改变本地目录。

9. 查找资料了解什么是LAMP服务器?它的需要哪些程序?

答:Linux+Apache+Mysql+Perl/PHP/Python一组常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被放在一起使用,拥有了越来越高的兼容度,共同组成了一个强大的Web应用程序平台。随着开源潮流的蓬勃发展,开放源代码的LAMP已经与J2EE和.Net商业软件形成三足鼎立之势,并且该软件开发的项目在软件方面的投资成本较低,因此受到整个IT界的关注。从网站的流量上来说,70%以上的访问流量是LAMP来提供的,LAMP是最强大的网站解决方案。要安装LAMP服务器步骤是要依次安装apache、mysql和PHP。

第6章 习题答案

1.什么是shell?Linux的shell主要有哪几种类型? 答:

Shell是一个用户接口,是一个命令解释器,除此之外,shell命令本身还可以作为程序设计语言,将多个shell命令组合起来,编写能实现系统或用户所需功能的程序。

Shell类型:bash,bsh,csh,tcsh,ksh,ash,zsh

2.如何编辑一个shell脚本、shell脚本的执行方式有哪些? 答:

Vi+shellscriptname

执行方式:(1)为脚本文件加上可执行权限,然后在命令行直接输入shell脚本文件名执行。 (2)sh shell脚本名 (3). shell脚本名 3.shell变量都有哪些? 答:

在shell编程中可以使用四种变量:用户自定义变量、环境变量、位置变量和特殊变量。 4.shell中都有哪些引号,他们之间的区别是什么? 答:

在shell中引号分为三种:单引号,双引号和反引号。

单引号 (?) 由单引号括起来的字符都作为普通字符出现。特殊字符用单引号括起来以后也会失去原有意义,而只作为普通字符解释。

双引号(―)由双引号括起来的字符,除“$”、“\\”、“‘”、和“‖”这几个字符仍是特殊字符并保留其特殊功能外,其余字符作为普通字符对待。

反引号(`)反引号括起来的字符串被shell解释为命令,在执行时,shell首先执行该命令,并以它的标准输出结果取代整个反引号(包括两个反引号)部分。

5.一个shell脚本,内容如下: #!/bin/bash

# finduser----寻找是否有第一个参数指定的用户登录 if [ $# -ne 1 ]

then

echo usage: finduser username >&2 exit 1 fi

who | grep $1 验证该脚本执行结果。 答:

6.一个shell脚本内容如下: echo “enter username: ” read user

until who | grep “$user” > /dev/null do sleep 30 done

验证该脚本执行结果。 答:

7.一个shell脚本,内容如下: #!/bin/bash if [ $# -ne 2 ] then

echo “usage: $0 mdays size ” 1>&2 exit 1 fi

if [ $1 –lt 0 –o $1 –gt 30 ] then

echo “mdays is out of range” exit 2 fi

if [ $2 –le 20 ] then

echo “size is out of range” exit 3 fi

find / -xdev –mtime $1 –size +$2 –print 验证该脚本执行结果。 答:

从根目录开始查找所有$1小时前修改,大小大于$2块的文件。 8.一个shell脚本,内容如下:

echo –n “which color do you like?” read color case “$color” in [Bb]l??)

echo I feel $color echo The sky is $color;; [Gg]ree*)

echo $color is for trees echo $color is for seasick;; red | orange)

echo $color is very warm!;; *)

echo no such color as $color;; esac

echo “out of case” 验证该脚本执行结果。 答:

9.设计一个shell脚本:求命令行上所有整数和。 答: sum=0

while [ $# != 0 ] do

let sum=sum+$1 shift done

echo “the sum of arguments is $sum”

10.设计一个shell脚本:判断当前工作目录下所有的文件类型,如果是目录显示目录名,如果是文件查看文件内容,如果都不是,显示提示信息。

答:

for file in ./* do

if [ -d “$file” ] then

ls “$file”

elif [ -f “file” ] then

more “$file” else

echo “$fiel is not a directory or a regular file.s” done

第7章 习题答案

1.gcc编译过程一般分为哪几个阶段?各阶段的主要工作是什么?

答:gcc编译过程一般分为预处理、编译、汇编、链接四个阶段,各阶段的主要工作如下: (1)预处理阶段

在该阶段,编译器将上述代码中的stdio.h编译进来。GCC首先调用cpp进行预处理,根据以字符#开头的命令修改原始的C程序。如hello.c中#include 指令告诉预处理器读系统头文件stdio.h的内容,并把它直接插入到程序文本中去。结果就得到经过编译预处理的源代码hello.i。

但实际工作中通常不用专门生成这种文件,因为基本上用不到。若非要生成这种文件不可,可以利用下面的示例命令。

$gcc -E hello.c -o hello.i (2)编译阶段

GCC调用cc1检查代码的规范性,是否有语法错误等,以确定代码实际要做的工作,在检查无误后,把代码翻译成汇编语言,生成汇编处理后的汇编代码hello.s。这个阶段对应的GCC命令如下所示。 $gcc -S hello.i -o hello.s

汇编语言是非常有用的,它为不同高级语言不同编译器提供了通用的语言。如:C编译器和Fortran编译器产生的输出文件用的都是一样的汇编语言。 (3)汇编阶段

GCC调用as把编译阶段生成的hello.s文件转成编译后的目标文件hello.o,但hello.c中所引用的其他文件中函数(如printf)的内存位置尚未定义。这个阶段对应的GCC命令如下所示: $gcc -c hello.s -o hello.o (4)链接阶段

GCC调用ld将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。如GCC找到hello.c所调用的函数printf函数库所在位置/user/lib,把函数的实现链接进来,生成最终的可执行文件hello。可以利用下面的示例命令完成。 $gcc hello.o -o hello

如果我们不想生成中间的各类型文件,可用如下命令由源文件直接编译链接成可执行文件。

$gcc hello.c -o hello 2.简述GNU gdb的功能。

答:gdb是Linux系统中一个功能强大的GNU调试程序,它可以调试C和C++程序,使程序开发者在程序运行时观察程序的内部结构和内存的使用情况。gdb提供如下功能: (1)运行程序,设置所有的能影响程序运行的参数和环境; (2)控制程序在指定的条件下停止运行; (3)当程序停止时,可以检查程序的状态; (4)修改程序的错误,并重新运行程序; (5)动态监视程序中变量的值;

(6)可以单步逐行执行代码,观察程序的运行状态; (7)分析崩溃程序产生的core文件。 3.用gdb调试下面的程序。 #include #include #include main () {

char my_string[] = \ my_print (my_string); my_print2 (my_string); }

my_print (char *string) {

printf (\}

my_print2 (char *string) {

char *string2; int size, i;

size = strlen (string);

string2 = (char *) malloc (size + 1); for (i = 0; i < size; i++) string2[size - i] = string[i]; string2[size+1] = `\\0';

printf (\}

答:gcc -g -o greeting greeting.c

这个程序执行时显示结果: The string is hello there The string printed backward is

输出的第一行是正确的, 但第二行打印出的东西并不是我们所期望的。我们所设想的输出应该是: The string printed backward is ereht olleh。

由于某些原因, my_print2 函数没有正常工作。用gdb 看调试程序, 先键入如下命令:

gdb greeting

-------------------------------------------------------------------------------- 注意: 记得在编译 greeting 程序时把调试选项打开. -------------------------------------------------------------------------------- 用gdb的run命令运行greeting。 (gdb) run

Starting program: /root/greeting The string is hello there The string printed backward is Program exited with code 040

这个输出和在 gdb 外面运行的结果一样。 问题是,为什么反序打印没有工作? 为了找出症结所在, 在 my_print2 函数的 for 语句后设一个断点, 具体的做法是在 gdb 提示符下键入 list 命令三次, 列出源代码: (gdb) list (gdb) list (gdb) list

第一次键入 list 命令的输出如下:

如果按下回车, gdb 将再执行一次 list 命令, 给出下列输出:

再按一次回车将列出 greeting 程序的剩余部分:

根据列出的源程序, 你能看到要设断点的地方在第21行, 在 gdb 命令行提示符下键入如下命令设置断点: (gdb) break 21

gdb 将作出如下的响应:

现在再键入 run 命令, 将产生如下的输出:

你能通过设置一个观察 string2[size - i] 变量的值的观察点来看出错误是怎样产生的, 做法是:

现在可以用 next 命令来一步步的执行 for 循环了: (gdb) next

经过第一次循环后, gdb 告诉我们 string2[size - i] 的值是 `h`. gdb 用如下的显示来告诉你这个信息:

这个值正是期望的,后来的数次循环的结果都是正确的。当 i=10 时, 表达式 string2[size - i]的值等于 `e`, size - i 的值等于 1, 最后一个字符已经拷到新串里了。

如果你再把循环执行下去, 你会看到已经没有值分配给 string2[0] 了, 而它是新串的第一个字符, 因为 malloc 函数在分配内存时把它们初始化为空(null)字符, 所以 string2 的第一个字符是空字符,这解释了为什么在打印 string2 时没有任何输出了。

现在找出了问题出在哪里, 修正这个错误是很容易的. 你得把代码里写入 string2 的第一个字符的的偏移量改为 size - 1 而不是 size. 这是因为 string2 的大小为 12, 但起始偏移量是 0, 串内的字符从偏移量 0 到 偏移量 10, 偏移量 11 为空字符保留。

为了使代码正常工作有很多种修改办法。 一种是另设一个比串的实际大小小 1 的变量。 这是这种解决办法的代码:

#include #include #include main() {

char my_string[]=\ my_print(my_string); my_print2(my_string); }

my_print(char *string) {

printf(\}

my_print2(char *string) {

char *string2;

int size,size2,i; size=strlen(string); size2=size-1;

string2=(char*)malloc(size + 1); for (i=0;i

string2[size2-i]=string[i]; string2[size+1]='\\0';

printf(\}

4.简述GNU make的工作过程。

答:make的主要功能是执行生成新版本的目标程序所需的各个步骤,即自动检测一个大型程序的哪一部分需要重新编译,然后发出命令重新编译。GNC的make的工作过程如下: (1)依次读入每个makefile文件; (2)初始化文件中的变量;

(3)推导隐式规则,并分析所有规则; (4)为所有目标文件创建依赖关系链;

(5)根据依赖关系和时间数据,确定哪些文件需要重新生成; (6)执行相应生成命令。

5.makefile文件的作用是什么?其书写规则是怎样的?

答:要用make维护一个程序,必须创建一个makefile文件,makefile文件告诉make以何种方式编译源代码和链接程序。makefile有自己的书写格式、关键字、函数,像C语言有自己的格式、关键字和函数一样,makefile描述规则组成如下所示。 目标 : 依赖文件 [TAB]命令

6.设某个程序由四个C语言源文件组成,分别是a.c、b.c、c.c、d.c,其中b.c和d.c都使用了defs.h中的声明,最后生成的可执行文件名为pgm。试为该程序编写相应的makefile文件。 答:

pgm : a.o b.o c.o d.o

gcc -o pgm a.o b.o c.o d.o a.o : a.c

gcc -c a.c b.o : b.c defs.h

gcc -c b.c c.o :c.c

gcc -c c.c d.o : d.c defs.h

gcc -c d.c

7.编写程序,用系统调用fork()创建两子进程。父进程显示50次字符串“father”,子进程1显示50次字符串“son”,子进程2显示50次字符串“daughter”。观察并记录屏幕上显示结果,分析原因。(提示:可在各进程中加入sleep,观察结果分析原因。) 答:

#include

main() {

int p1,p2,i,j,k;

while ((p1=fork())==-1); if(p1==0) {

for(i=0;i<50;i++) { printf(\ } else {

while ((p2=fork())==-1); if (p2==0) {

for (j=0;j<50;j++)

{ printf(\ } else {

for(k=0;k<50;k++){printf(\

} } }

编译运行结果如下:

从运行结果可知父亲进程、女儿进程、儿子进程并发执行。 如果在每个printf后面加上sleep(1),结果如下:

从运行结果可知加上sleep后父进程和两个子进程并发程度更大。

8.编写一个程序,该程序当我们输入Ctrl+C时输出字符串“ I got signal”。在其余的时间,该程序只是无限循环,

每一秒输出一条“hello world”信息。 答:

#include #include #include void ouch(int sig) {

printf(\ (void) signal(SIGINT,SIG_DFL); }

int main() {

(void) signal(SIGINT,ouch); while(1) {

printf(\ sleep(1);

} }

9.编写程序,实现简单shell的基本功能。读入用户从键盘输入的命令,并执行它。 答:

#include main() { }

10.利用文件系统的系统调用creat()、open()、read()、write()、close()编写一个程序,把一个文件读出写到另一个文件中,实现简单的copy功能。 答:

main(argc,argv) int argc; char *argv[]; {int fd1,fd2,n;

char command[32]; char * prompt=\

while (printf(\{

if (fork()==0)

execlp(command,command,(char*)0); wait(0); else

}

char buf[512];

fd1=open(argv[1],0); fd2=creat(argv[2],0644); while((n=read(fd1,buf,512))>0) write(fd1,buf,n); close(fd1); close(fd2); }

第8章 习题答案

1. GTK+基于什么语言编写的?它与gnome有什么联系?

答:基于C语言编写的图形类库,gnome就是基于GTK图形库编写的Linux图形操作界面,由于gnome的流行,使得GTK编程成为Linux的图形化编程的主流。

2. GTK+和哪些函数库存在着依赖关系?

答:Glib,Pango,ATK,GDK,GdkPixbuf,Cairo。 3. 什么是GTK+信号?它和Linux中的信号概念一致吗?

答:信号(Signal)是GTK中出现的新的并且比较重要的概念。注意这里讲的“信号”不同于UNIX,Linux的signal,只是名称一样。当处理X事件时,如键盘按键按下,GTK的组件接收到这一事件,便发出响应的信号。类似于Windows编程中的消息事件机制。

4. 简述GTK+信号与回调过程?

答:使用函数gtk_signal_connect把组件object与回调函数func联系起来,name 是所发出的信号的名称。func_data是传递给回调函数的参数。比如要使一个按钮执行一个动作,就需用此函数设置信号和信号处理函数之间的连接。

gint

gtk_signal_connect(GtkObject

*object,gchar

*name,

GtkSignalFunc

func,gpointer func_data );

回调函数的格式如下,其中widget是发出信号的组件,callback_data是传递参数的指针。 void callback_func(GtkWidget *widget,gpointer callback_data); 5. 简述编写GTK+程序的步骤?

答:步骤如下:初始化,创建主窗口,创建并加入子窗口,设置组件回调,显示窗口,进入事件循环。 6. GTK+程序的编译参数都代表什么意义?

答:`gtk-config--cflags`产生编译GTK所使用的头文件位置,`gtk-config--libs`产生连接gtk程序编译时所使用的库。pkg-config --cflags gtk+-2.0就是列出include目录,pkg-config --libs gtk+-2.0就是列出编译连接库,也可以合在一起使用如:pkg-config --cflags --libs gtk+-2.0。

7. 用GTK+编写一个类似于Windows下的计算器程序。

答:源代码仅供参考: #include #include static GtkWidget *entry; gint count=0; gdouble nn=0; gdouble mm=0;

gint s=0;

gboolean first=TRUE; gboolean have_dot=FALSE; gboolean have_result=FALSE; gchar number[100]; void clear_all(void) {

gint i=0;

gtk_entry_set_text(GTK_ENTRY(entry),\ nn=0; mm=0; s=0; count=0; first=TRUE; have_dot=FALSE; have_result=FALSE; for(i=0;i<100;i++) number[i]='\\0'; }

void on_num_clicked(GtkButton *button,gpointer data) {

const gchar *num; gint i; if(have_result) clear_all(); if(count==6) return; count++;

num=gtk_button_get_label(GTK_BUTTON(button)); i=g_strlcat(number,num,100); if(first)

nn=strtod(number,NULL); else

mm=strtod(number,NULL);

gtk_entry_set_text(GTK_ENTRY(entry),number); }

void on_dot_clicked(GtkButton *button,gpointer data) { gint i;

if(have_result) clear_all(); if(have_dot==FALSE)

{

have_dot=TRUE;

i=g_strlcat(number,\

gtk_entry_set_text(GTK_ENTRY(entry),number); } }

void on_clear_clicked(GtkButton *button,gpointer data) {

clear_all(); }

void on_suan_clicked(GtkButton *button,gpointer data) {

gint i;

switch(GPOINTER_TO_INT(data)) {

case 1:

gtk_entry_set_text(GTK_ENTRY(entry),\ s=1; first=FALSE; count=0; break; case 2:

gtk_entry_set_text(GTK_ENTRY(entry),\ s=2; first=FALSE; count=0; break; case 3:

gtk_entry_set_text(GTK_ENTRY(entry),\ s=3; first=FALSE; count=0; break; case 4:

gtk_entry_set_text(GTK_ENTRY(entry),\ s=4; first=FALSE; count=0; break; }

have_dot=FALSE;

for(i=0;i<100;i++) number[i]='\\0'; }

void on_eq_clicked(GtkButton *button,gpointer data) {

double numb; gchar *result; gchar num[100]; switch(s) {

case 1:

numb=nn+mm; break; case 2:

numb=nn-mm; break; case 3:

numb=nn*mm; break; case 4:

if(mm==0) {

gtk_entry_set_text(GTK_ENTRY(entry),\ break; }

numb=nn/mm; break; }

result=g_ascii_dtostr(num,100,numb); gtk_entry_set_text(GTK_ENTRY(entry),result); have_result=TRUE; }

int main(int argc,char* argv[]) {

GtkWidget *window; GtkWidget *vbox;

GtkWidget *hbox,*hbox1,*hbox2,*hbox3,*hbox4; GtkWidget *button; GtkWidget *label; GtkWidget *label1;

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window),500,300); gtk_container_set_border_width(GTK_CONTAINER(window),10); gtk_window_set_title(GTK_WINDOW(window),\计算器\

gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);

g_signal_connect(G_OBJECT(window),\

vbox=gtk_vbox_new(TRUE,0);

gtk_container_add(GTK_CONTAINER(window),vbox); hbox=gtk_hbox_new(TRUE,0);

gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,TRUE,5); label=gtk_label_new(\

gtk_box_pack_start(GTK_BOX(hbox),label,TRUE,TRUE,5); label1=gtk_label_new(\

gtk_box_pack_start(GTK_BOX(hbox),label1,TRUE,TRUE,5);

time_t now;

struct tm *l_time; gchar buf[100];

now=time((time_t *)NULL); l_time=localtime(&now);

sprintf(buf,\ gtk_label_set_text(GTK_LABEL(label1),buf);

button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\

entry=gtk_entry_new();

gtk_editable_set_editable(GTK_EDITABLE(entry),FALSE); gtk_widget_set_direction(entry,GTK_TEXT_DIR_RTL); gtk_box_pack_start(GTK_BOX(vbox),entry,TRUE,TRUE,5);

hbox1=gtk_hbox_new(FALSE,0);

gtk_box_pack_start(GTK_BOX(vbox),hbox1,TRUE,TRUE,5); button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\

hbox2=gtk_hbox_new(FALSE,0);

gtk_box_pack_start(GTK_BOX(vbox),hbox2,TRUE,TRUE,5); button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\

hbox3=gtk_hbox_new(FALSE,0);

gtk_box_pack_start(GTK_BOX(vbox),hbox3,TRUE,TRUE,5); button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox3),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox3),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox3),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox3),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\

hbox4=gtk_hbox_new(FALSE,0);

gtk_box_pack_start(GTK_BOX(vbox),hbox4,TRUE,TRUE,5); button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox4),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox4),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox4),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\ button=gtk_button_new_with_label(\

gtk_box_pack_start(GTK_BOX(hbox4),button,TRUE,TRUE,5);

g_signal_connect(G_OBJECT(button),\

gtk_widget_show_all(window); gtk_main(); return FALSE; }

运行结果图:

第9章 习题答案

1. Qt自带图形开发工具由哪些工具组成?

答:Qt Designer可视化地设计视窗,Qmake由简单的宇平台无关的项目文件生成Makefile,Qt助手快速地发现你所需要的帮助,qembed转换数据,比如把图片转还为C++代码,qvfb在桌面上运行和测试嵌入式应用程序,makeqpf为嵌入式设备提供预先做好的字体,moc元对象编译器,uic用户界面编译器,qtconfig一个基于Unix的Qt配置工具,这里是在线帮助。

2. 在无第三方开发工具的情况下,如何编译QT程序?

答:先用vi编辑源代码保存,在编译程序之前,要首先生成它的Makefile文件。打开一个终端,然后切换至

保存有项目的位置,使用以下命令来生成Makefile文件:

[root@localhost~]#qmake -o Makefile hellopro

现在,就可以运行make来编译程序了,根据系统的性能,这个步骤需要花费一点时间。当编译工作完成后,[root@localhost~]#qmake -o Makefile hellopro [root@localhost~]#make [root@localhost~]#.hello

3. Qt编程的核心机制是什么?与Windows编程有什么异同点?

答:信号(signals)和槽(slots)机制是Qt的核心机制,信号和槽是一种高级接口,应用于对象之间的通信,它是Qt的核心特性,也是Qt区别于其它工具包的重要地方。信号和槽是Qt自行定义的一种通信机制,它独立于标准的C/C++语言,因此要正确的处理信号和槽,必须借助一个称为moc(Meta Object Compiler)的Qt工具,该工具是一个 C++ 预处理程序,它为高层次的事件处理自动生成所需要的附加代码。它与Windows事件驱动机制相类似又不完全相同。

4. Eclipse+Qt开发环境的配置过程是什么?试搭建起Eclipse+Qt开发平台。

答:先安装Eclips,然后到这个网站http://qt.nokia.com/developer/eclipse-integration上去下载Qt plugin压缩包,解压得到两个子文件夹分别为plugins和features,将这两个文件夹覆盖/usr/lib/eclipse/文件夹下的同名文件夹,打开Eclipse , 在\窗口->首选项->qt\里配置如下信息:

Name : Qt

Bin Path : /usr/lib/qt4/bin Include Path : /usr/include/ 5. 标准输入框能为哪些数据类型的提供输入?

答:标准输入框能提供多种数据类型的输入,比如字符串,Int类型,Double类型或是下拉列表框的条目。 6. 基于QT编写一个计算器程序。 答:源代码仅供参考: main.cpp: #include \#include int main(int argc, char **argv) {

int result = 0;

QApplication app(argc, argv); CWidget *main = new CWidget(); main->setCaption(\

app.connect(&app,SIGNAL(lastWindowClosed()),SLOT(quit())); main->show(); result = app.exec(); return result; }

cwidget.h:

#ifndef CWIDGET_H #define CWIDGET_H #include

输入./hello来运行程序。以上整个的编译运行命令行过程总结如下:

#include #include #include #include #include #include class CWidget : public QWidget {

Q_OBJECT public:

CWidget(QWidget *parent=0, char *name=0); ~CWidget(); private:

QLineEdit *edit; QPushButton *button[16]; QVBoxLayout *mainLayout; QHBoxLayout *topLayout; QGridLayout *bottomLayout; int firstNum; int secondNum; int oper; protected slots: void setValue(); void setOper(); void calculate(); void clear(); protected:

virtual bool event(QEvent *e); private: void initialize(); void createForm(); void onClicked(int key); }; #endif

cwidget.cpp: #include \#define KEY_CLR \#define KEY_ADD \#define KEY_SUB \#define KEY_MUL \#define KEY_DIV \

#define KEY_EQ \#define KEY_0 \#define KEY_1 \#define KEY_2 \#define KEY_3 \#define KEY_4 \#define KEY_5 \#define KEY_6 \#define KEY_7 \#define KEY_8 \#define KEY_9 \#define BUTTONWIDTH 30 #define BUTTONHEIGHT 30 static char *buttontext[] = {

KEY_1,KEY_2,KEY_3,KEY_4, KEY_5,KEY_6,KEY_7,KEY_8,

KEY_9,KEY_ADD,KEY_SUB,KEY_MUL, KEY_DIV,KEY_EQ,KEY_CLR,KEY_0 };

CWidget::CWidget(QWidget *parent, char *name) {

initialize(); createForm(); }

CWidget::~CWidget() {

delete edit; delete *button; delete mainLayout; delete topLayout; delete bottomLayout; }

void CWidget::calculate() {

switch(oper) {

case Qt::Key_Plus:

firstNum += secondNum;break; case Qt::Key_Minus:

firstNum -= secondNum;break; case Qt::Key_Asterisk: firstNum *= secondNum;break; case Qt::Key_Slash:

firstNum /= secondNum;break; default:

firstNum = firstNum; }

edit->setText(QString::number(firstNum)); }

void CWidget::setValue() {

QString tempStr; tempStr = edit->text();

if(tempStr.length() < edit->maxLength()) tempStr += ((QPushButton *)sender())->text(); else {

QMessageBox::information( this, tr(\ }

if(-1==oper) {

firstNum = tempStr.toInt();

edit->setText(QString::number(firstNum)); } else {

secondNum = tempStr.toInt();

edit->setText(QString::number(secondNum)); } }

void CWidget::setOper() {

QString str=((QPushButton *)sender())->text(); if(str == \

onClicked(Qt::Key_Plus); else if(str == \

onClicked(Qt::Key_Minus); else if(str == \

onClicked(Qt::Key_Asterisk); else if(str == \

onClicked(Qt::Key_Slash); else if(str == \ calculate(); }

void CWidget::clear() {

edit->clear();

edit->setText(tr(\ initialize(); }

void CWidget::initialize() {

firstNum = 0; secondNum = 0; oper = -1; }

void CWidget::createForm() {

setMinimumSize(80,200); setMaximumSize(80,200);

mainLayout = new QVBoxLayout(this,20); topLayout = new QHBoxLayout(mainLayout,30); edit = new QLineEdit(this,\ edit->setAlignment(Qt::AlignRight); edit->setMaxLength(9); edit->setText(tr(\ edit->setReadOnly(true); topLayout->addWidget(edit);

bottomLayout = new QGridLayout(mainLayout,4,4,10); int n;

for(int r=0; r<3; r++) for(int c=0; c<3; c++) {

n = c+3*r;

button[n] = new QPushButton(buttontext[n],this,buttontext[n]); button[n]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[n],r,c);

connect(button[n],SIGNAL(clicked()),this,SLOT(setValue())); }

button[9] = new QPushButton(buttontext[9],this,buttontext[9]); button[9]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[9],0,3);

connect(button[9],SIGNAL(clicked()),this,SLOT(setOper()));

button[10] = new QPushButton(buttontext[10],this,buttontext[10]); button[10]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[10],1,3);

connect(button[10],SIGNAL(clicked()),this,SLOT(setOper()));

button[11] = new QPushButton(buttontext[11],this,buttontext[11]); button[11]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[11],2,3);

connect(button[11],SIGNAL(clicked()),this,SLOT(setOper()));

button[12] = new QPushButton(buttontext[12],this,buttontext[12]); button[12]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[12],3,3);

connect(button[12],SIGNAL(clicked()),this,SLOT(setOper()));

button[13] = new QPushButton(buttontext[13],this,buttontext[13]); button[13]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[13],3,2);

connect(button[13],SIGNAL(clicked()),this,SLOT(calculate()));

button[14] = new QPushButton(buttontext[14],this,buttontext[14]); button[14]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[14],3,1);

connect(button[14],SIGNAL(clicked()),this,SLOT(clear()));

button[15] = new QPushButton(buttontext[15],this,buttontext[14]); button[15]->setFixedSize(BUTTONWIDTH,BUTTONHEIGHT); bottomLayout->addWidget(button[15],3,0);

connect(button[15],SIGNAL(clicked()),this,SLOT(setValue())); }

bool CWidget::event(QEvent *e) {

if(e->type() == QEvent::KeyPress) {

QKeyEvent *KeyEvent = static_cast(e); switch(KeyEvent->key()) {

case Qt::Key_Plus:

onClicked(Qt::Key_Plus);break; case Qt::Key_Minus:

onClicked(Qt::Key_Minus);break; case Qt::Key_Asterisk:

onClicked(Qt::Key_Asterisk);break; case Qt::Key_Slash:

onClicked(Qt::Key_Slash);break; case Qt::Key_Equal: calculate();break; } }

return QWidget::event(e); }

void CWidget::onClicked(int key) {

edit->clear();

edit->setText(tr(\ oper = key; }