《C语言接口与实现》Chapter2笔记

模块分为两个部分,即模块的接口与实现。接口规定了模块做什么(声明标识符、类型和历程)。实现指明模块如何完成其接口规定的目标。
客户端程序(client)是使用模块的一端代码(导入接口,实现导出接口)。多个客户端共享接口和实现,因而避免了不必要的代码重复。

一、接口
接口仅规定客户程序可能使用的那些标识符,尽而可能隐藏不想管的表示细节和算法。
客户程序和实现之间的这种依赖性称之为耦合(coupling),在实现改变时耦合会导致bug,当依赖性被与实现相关的隐藏或隐含的假定掩盖时,这种bug会难于改正。
在C语言中,接口通过一个头文件指定,头文件的扩展名通常为.h。这个头文件会声明客户程序可能是用的宏、类型、数据结构、变量和例程。用C预处理命令#include导入。
一个接口例子:

该接口命名为Arith,接口头文件命名为arith.h。避免名称碰撞(name collision)的一个方法是使用前缀,如模块名。

Arith接口中函数提供了标准C库缺失的一些有用功能,并对除法和模运算提供了良定义的结果,而标准则将这些操作的行为规定为未定义(undefined)或由具体实现来定义(implementation-define)。

C语言标准只是强调,如果x/y是可以表示的,那么(x/y)*y + x%y必须等于x,因而内建的运算符只对正的操作数有用。

标准库函数div和ldiv以两个整数或长整数为输入,并计算二者的商和余数,在一个结构的quot和rem字段中返回。它们是良定义的——总是向零舍入。

arith_div和arith_mod,它们也是良定义的——总是向数轴的左侧舍入。arith_div(x, y)的定义为超过实数z的最大整数,而z*y=x。arith_mod(x, y)则等于x – y*arith(x, y)。

arith_ceiling(x, y)返回不小于x/y的实数商的最小整数。arith_floor(x, y)返回不大于x/y的实数商的最大整数。

二、实现

在Arith_div中,如果除法向零舍入,而y不能整除x,那么Arith_div(x, y)的结果为x/y-1,否则,返回x/y:

测试除法所采用的舍入方式:

检查符号问题(首先判断x和y是否小于0,然后比较结果是否相等):

Arith_mod可以用Arith_div那样进行判断,也可以用%运算符实现:

Arith_floor刚好等于Arith_div,而Arit_ceiling等于Arith_div加1,除非y能整除x:

三、抽象数据类型

一个抽象数据类型是一个接口,它定义了一个数据类型和对该类型的值的所进行的操作。一个数据类型是一个值的集合。

以下接口定义了栈类型及其五个操作,:

结构、联合和枚举的名称(标记)占用了一个命名空间,该命名空间不同于变量、函数、和类型名所用的命名空间。

宏后加_INCLUDED有助于避免冲突。标准C将下划线前缀保留给实现者和未来扩展使用,因此要避免使用下划线前缀。

条件编译指令#ifdef 和#endif以及定义STACK_INCLUDED的#define,使之stack.h可以被包含多次也能避免重定义的错误。

定义ADT的接口X可以将ADT类命名为X_T,更进一步在接口内部用宏将X_T缩写为T,结尾用#undef删除上述缩写。

该接口提供了可用于任意指针的容量无限制的栈。其中Stack_free作用是释放一个栈指针,并将类型为T的变量设置位NULL指针,这种设计有助于避免先挂指针(dangling pointer),即指针指向已经被释放的内存。

四、客户程序的职责

接口通常会规定:未检查的运行时错误(unchecked runtime error)和已检查的运行时错误(checked runtime error),例如:未能打开一个文件。异常(exception),例如:内存损耗。

如果发生未检查的运行时错误,可能会继续执行,但结果是不可预测的。例如:Arith必须指明处以零是一个未检查的运行时错误。

如果发生已检查的运行时错误,不可避免,但可以终止执行。例如:传递给Stack_pop的栈为空。

接口可以规定异常及引发异常的条件。(暂时跳过不读)

 

《C语言接口与实现》Chapter1笔记

一个大程序由许多小的模块组成,理想情况下大部分模块来自于库。而「库函数全面测试过,只有应用程序相关的代码会包含bug」这种情况很少;另一个原因是一些库的规模太大了,从而导致对库本身功能的掌握变成了一项沉重的任务。

库的设计者必须在通用性、简单性和效率性三个约束之间如履薄冰、审慎而行。

本书描述了一个库的设计和实现,该库导出了一组模块,这些模块提供了用于小规模程序设计(programming-in-the-small)的函数和数据结构。
Continue reading →

《UNIX/LINUX编程实践教程》Chapter1笔记

《UNIX/LINUX编程实践教程》——第1章 Unix系统编程概述笔记

本书首先分析操作系统的职责入手,来解释如何编写与操作系统紧密相关的程序。然后通过夫人年西标准的Unix命令,以及它们用到的系统调用,进一步指导读者自己编程实现相应的功能。

计算机用操作系统来管理所有的资源,并将不同的设备和不同的程序连接起来。

在进行系统编程时,必须对系统的结构和工作方式有更深的了解,要知道内核提供哪些服务(系统调用),如何使用它们,系统有那些资源和设备,不同的资源和设备如何操作。

系统资源:处理器、输入输出(I/O)、进程管理、内存、设备、计时器、进程间通信、网络等。

学习方法:

  • 通过三个步骤来理解:分析程序->学习系统调用->编程实现。
  • 通过三个问题来实现:它能做什么? 它是如何实现的? 能不能自己编写一个?

目录树:文件和目录被组织成树状结构,Unix提供相应的命令来对目录进行操作。

文件系统的最顶端是「/」(根目录),根目录一般都包含几个子目录,且都有它们特定的用途。

目录操作命令:

  • ls——列出目录内容。
  • cd——改变当前目录。
  • pwd——显示当前目录。
  • mdkdir、rmdir——新建、删除目录。

文件命名规则:在Unix系统中,文件名最长可以是250个字符,不能包含根目录符号「/」。

文件操作命令:

  • cat,more,less,pg——查看文件的内容。
  • cp——文件复制。
  • rm——文件删除。
  • mv——重命名或移动文件。
  • lpr,lp——打印文件。

文件许可权限:每个文件都有文件所有者(owner)和文件许可权限。

文件许可分为3组:r(read)、w(write)、x(execute)。

用户也被分成三组:user(文件所有者)、group(与文件所有者同组的用户)、other(其他用户)。

通过命令ls -l filename 可以查看文件文件许可权限。

Unix系统编程中3个重要的方面:

  • 通信。某个用户或进程如何与其他用户或进程交换信息?
  • 协作。程序如果来协调多个进程使他们能够没有冲突地访问共享资源?
  • 网络访问。计算机中的程序是如何来使用网络的呢?

Unix的计算器:bc并不做任何计算,bc是dc的预处理器,它将用户输入的表达式转换成逆波兰表达式,通过管道(pipe)交给dc,dc计算表达式的值,将结果返回给bc,bc再将结果以合适的形式显示在显示器上。

通过自己动手编写more程序,理解标准输入输出、管道重定向、「/dev/tty」以及本书解决问题的步骤。

Unix系统的主要结构:内存被分为系统空间和用户空间,内核和它的数据结构位于系统空间,用户程序位于用户空间。用户通过终端连接到系统,文件存放在磁盘上,各种各样的设备被内核直接管理,用户程序可以通过内核来访问设备,最后还有网络连接,用户可以通过网络接入系统。

小结:

  • 计算机系统中包含了很多系统资源,如硬盘、内存、外围设备、网络连接等,程序利用这些资源来对数据进行存储、转换和处理。
  • 多用户系统需要一个中央管理程序,Unix的内核就是这样的程序,它可以对程序资源进行管理。
  • 用户程序要访问设备必须经过内核。
  • 一些Unix的系统功能是由多个程序的协作而实现的。
  • 要编写系统程序,必须对系统调用和相关的数据结构有深入的理解。

2014-06-17

《UNIX/LINUX编程实践教程》——实现more

一、能做什么?

more可以分页显示文件的内容。正常运行后more会显示文件第一屏的内容,在屏幕的底部,more用反白字体显示文件的百分比,这时如果按空格键,文件的下一屏内容会显示出来,如果按回车键,显示的则是下一行,如果输入“q”,结束显示,如果输入“h”,显示出来的是more的联机帮助。
more有三种用法:

$ more filename

显示文件filename的内容。

$ command | more

More将command命令的输出分页显示。

$ more < filename

从标准输入获取要分页显示的内容,而这时more的标准输入被重定向到文件filename。

Continue reading →

openSUSE KED下设置「显示桌面」快捷键

最近使用openSUSE,有一个地方让我特别别扭,就是它不像Windows一样用WIN+D显示桌面,每次打开一大堆窗口想显示桌面要一个个按化小,于是请教了高手。

其实panel tool box可以添加这个功能,具体步骤如下:

  1. 点击右下角的panel tool box 选择Add Widgets。
  2. 在搜索框输入「Show Desktop 」,找到后双击添加到面板上。
  3. 右键面板上的「Show Desktop」,选择「Show Desktop Settings」.
  4. 点击None,输入Win+D,最后点击OK即可。