2008-8-31
P250
用True 和False 之类的词来表示布尔表达式的结果,如果所用语言不支持这种类型,用预
定义宏或全局变量的方法来创造一个。
用True 和False 作变量名使得用意很清楚。你不用记“1”和“0”表示什么意思,也不用
偶尔回头检查。
在C中用1 == 1的形式定义TRUE和FALSE。
在C中,有时很难记住是否TRUE等于1和FALSE
等于0 或者正好相反,你得记住测试FALSE 和测试空终止符或其它零值一样。否则用下面定义
TRUE和FALSE的方法来避免出现这个问题。
这个C 程序用易于记住的方法定义布尔量:
# define TRUE (1 ==1)
# define FALSE(!TRUE)
,C和Pascal 用短路法计算,如
果第一个运算and是假,那么第二个运算不再执行,因为整个式就已经是假了。
17.1.7 C语言中与0比较的用法
C 语言中0有几个用途。它是一个数字量;在字符串中它是一个结束符(’\0’),它是地
址指针所允许的最小值;在逻辑表达式中它表示假,因为它有这么多的用途,你在编程时要清
楚地表明是哪种。
隐含地和逻律变量比较。正如前面提到,这样写逻辑表达式是正确的。
while(!Done)
这个表达式隐含在和0 作比较是正确的,因为这个比较是在一个逻辑表达式里。
数与0 比较。虽然可隐含地把逻辑表达式与0 比较,你却不可以把数字表达式隐含地与0
比较。对于数字,编程:
while(Balance!=0)…
而不可写成
while(Balance)…
把字符与结束符(’/0’)字一样,字符也不是逻辑表达式。因此对字符编程:
while(* CharPtr!=’0’)…
而不能写成:
while (* CharPtr) …
这种说法与常用的c 语言在处理字符数据时的习惯可能有出入,但它强化了这种观点,即
表达式是在处理字符数据,而非逻辑数据。C语言的有些用法并不是基于可读性和或维护而设计
的,比如上例即是。
把指针与Null(空指针)比较。对指针编程:
while(BufferPtr!=Null)…
而不写成:
while(BufferPtr)…
与字符的情形一样,这也不是C 的常用用法,但却增强可读性。
重新编写部分测试条件来简化嵌套的If 语句。
17.7.4 检查表
控制结构方面
· 表达式用True和False而非1 和0?
· 布尔型表达式的值是否隐含地与False比较?
· 是否通过定义中间布尔型变量和布尔型函数及用决策表的方法来简化表达式?
· 布尔型表达式是用肯定形式写出来的吗?
· 在C 中,数值、字符,指针是显式与0比较的吗?
· begin和end能保持平衡吗?
· 为了使程序看起清楚,需要的地方用begin和end对标明了吗?
· 空语句看起来清楚吗?
· 通过诸如重新组合测试条件、转化为if-then-else或case 语句或把嵌套内代码写成子
程序的方法来简化嵌套语句了吗?
· 如果程序的决定点数超过10,有什么正常理由不重新设计它吗?
17.8 小 结
· 使布尔型表达式简单可读性高对代码的质量很有好处。
· 深层嵌套使程序难懂,不过可用相对简单方法避免这样做。
· 结构化编程是一个简化程序的思想,用顺序编程、选择或循环中的一种或几种方法的组
合可编出任何程序。
· 作这种简化程序的思想可提高程序的产量和质量。
· 如果所用语言不支持结构化结构,你能模仿它们。你应该把程序编成某种语言的程序而
不是用某种语言编程的。
· 降低复杂性是编写高质量的代码的关键。
――――――――――――――――以上是 17 章―――――――――――
第1章
第2
第3章
第4章
第5章
第6章
第7章
第8章
第9章
小结
· 恰当的变量名是可读性好的必要条件之一。特殊的变量如循环变量和状态变量要予以
特殊考虑。
· 命名约定可以区分局部、模块和全局变量。同时它还可以区分类型名称,比如可以对
命名常量、枚举类型和变量加以区分。
· 不管你从事的是哪种项目,都应该采用命名约定。所采用的命名约定取决于程序的规
模和从事这一程序的程序员的人数。
· 匈牙利约定是一种非常有效的命名约定,比较适于大规模项目和程序。
· 在现代编程语言中几乎不需要采用缩写技术。
9.8.1 检查表
通用命名约定
· 变量名称是否完全准确地描述了变量代表的是什么?
· 变量名是否指向是客观世界中的问题,而不是关于这问题的用程序语言表达解决方案?
· 变量名称是否是够长,使得你不必破译它?
· 变量名中如果含有计算限定词的话,是否将其放在最后?
· 是否在名称中用Count或Index来代替了Num?
对特殊类型数据的命名
· 循环变量的名称是有意义的吗?(如果循环体较长是嵌套循环的话,应用有含义的名
称来代替i、j、k 之类的名称)
· 是否用更富于含义的名称来代替了被叫作"tempotarg"的临时变量?
· 当逻辑变量的值是"True"时,它的名称是否充分表达了其含义?
· 是否用前缀或后缀来表明了某些枚举类型是一类的?如用Color 来作ColorRed,
ColorGreen,ColorBlue等枚举类型的前缀。
· 命名常量的名称是否是指向它们代表的实体而不是它们所代表的数值的?
命名约定
· 命名约定是否区分了局部、模块和全局数据?
第九章 数据名称 140
· 命名约定是否对类型名称、命名常量、枚举类型和变量进行了区分?
· 在不支持强化仅供子程序输入参数的语言中,命名约定是否对这类参数进行了标识?
· 命名约定是不是与程序语言的标准约定尽可能地相容?
· 对于语言中没有强制的子程序中仅做输入的参数,是否约定将它标识了?
· 是否对名称进行了格式化以增强程序的可读性?
短名称
· 代码是否使用了长名称?(除非有必要使用短名称)
· 是否避免了只省略一个字母的缩写?
· 所有单词保持缩写的连续性了吗?
· 所有的名称都是容易发音的吗?
· 是否避免了会引起错误发音的名称?
· 是否在注释表中对短变量名进行了注释?
避免如下这些常见的命名错误了吗
· 易引起误会的名称
· 含义相似的名称
· 仅有一或两个字母不同的名称
· 发音相似的名称
· 使用数字的名称
· 对单词作改写以使其比较短的名称
· 英语中常拼写错的名称
· 标准库子程序或已定义的变量名又定义了
· 完全是随意的名称
· 含有难以辨识字母的名称
第10章
检查表
使用数据时通常要考虑的一些问题
一般数据
· 是否已经使变量的作用域尽可能地小?
· 是否把对变量的使用集中到了一起?
· 控制结构与数据结构是相对应的吗?
· 每个变量是否有且仅有一个功能?
· 每个变量的含义都是明确的吗?是否保证了每个变量都没有隐含的意义?
· 每一个说明过的变量都被用到了吗?
全局变量
· 是否是在迫不得已的情况下,才使某些变量成为全局的?
· 命名约定是否对局部、模块和全局变量进行了区分?
· 是否说明了所有全局变量?
· 程序中是否不含有伪全局变量——传往各个子程序的庞大而臃肿的数据结构?
· 是否用存取子程序来代替了全局数据?
· 是把存取子程序和数据组织成模块而不是随意归成一堆的吗?
· 存取子程序的抽象层次是否超过了程序语言实现细节?
· 所有相互有联系的存取子程序,其抽象程度都是一致的吗?
10.7 小结
· 尽量减小变量的作用域。把对变量引用集中到一起,应尽量使变量成为局部或模块的,
避免使用全局变量。
· 使每个变量有且仅有一个功能。
· 并不是因为全局数据危险才避免使用它们,之所以避免用它是因为可以用更好的技术
来代替它。
· 如果全局数据确实不可避免的话,应通过存取子程序来对其进行存取操作。存取子程
序不仅具备全局变量和全部功能,而且可以提供更多的功能。
第11章
P154~P161 已看
第12章
第13章
第14章
第15章
第16章
第17章
第18章
第19章
第20章
第21章
P154
第22章
第23章
第24章
第25章
第26章
2008-8-31
不定期发生错误通常是由于未对变量进行初始化或使用了悬挂指针。如果某一数有时错有
时对,这可能是计算中所涉及到的某个变量没有被正确地初始化——大多数情况下此变量初始
值被置为 0。如果你使用了指针,并且所发生的现象是奇怪的和不可预测的,你可能使用了一
个未初始化指针,或对已分配的存储器单元使用了指针。
确定错误位置
简化测试用例的目的是,改变测试用例的任何一方面是否都能引起错误的出现。然后,细
心地改变测试用例,并观察在一定条件下错误的表现形式,这样你才能诊断错误。
确定错误的位置也同样需要使用科学的方法,你可能怀疑错误是由某一特定问题,比如边
界条件错误所引起。你可将你怀疑的常量取不同值——一个低于边界值,一个恰为边界值,另
一个高于边界值——以此来确定你的假想是否正确。
检查表
·调试
发现错误的方法:
· 使用所有数据建立假设
· 求精产生错误的测试用例
· 通过不同的方法再生错误
· 产生更多的数据以生成更多的假设
· 使用否定测试结果
· 提出尽可能多的假设
· 缩小可疑代码区
· 检查最近作过修改的代码
· 扩展可疑代码区
· 逐步集成
· 怀疑以前出过错的子程序
· 耐心检查
· 为迅速的草率的调试设定最大时间
· 检查一般错误
· 使用交谈调试法
· 中断对问题的思考
改正错误的方法:
· 理解问题的实质
· 理解整个程序
· 确诊错误
· 放松情绪
第二十六章调 试 430
· 保存初始源代码
· 修改错误而不是修改症状
· 仅为某种原因修改代码
· 一次作一个修改
· 检查你的工作,验证修改
· 寻找相似错误
调试的一般方法
· 你是否将调试作为学习有关程序、错误、代码质量及解决问题方法的一次机会?
· 你是否避免使用试错法,或避免采用迷信的方法?
· 你是否认为错误是由于你的过错?
· 你是否使用科学方法以固定间歇性错误?
· 你是否使用科学方法发现错误?
· 你是否每次使用不同的方法,而不是只用一种方法发现错误?
· 你是否验证了修改信息是正确的?
· 你是否利用了警告信息、执行剖析程序、建立脚手架方法、交互式调试等?
26.6 小 结
· 调试是软件开发中的问题。最好的方法是使用本书的其他方法避免一开始就发生错误。
你仍需花费时间提高你的调试技能——因为最好和最差的调试效率差别为10:1,甚至
更大。
· 注意你的编译警告信息,并及时改正编译所提示的错误。如果你忽略了明显错误的话,
你就难以改正微妙的错误。
· 发现和改正某错误的关键是,有一个有条理的方法,注重你的测试,这样每次你都能
向前迈进一步。
· 在你改正一个问题之前应理解问题的本质,对错误源的任意猜测和修改只会使你的程
序更为糟糕。
· 调试是软件开发的有力工具。你应能利用调试工具。记住你还应好好动脑筋