布尔表达式
用 True 和 False做布尔判断:
来表示布尔表达式的结果,如果所用语言不支持这种类型,用预定义宏或全局变量的方法来创造一个。 用隐式地比较布尔值与true和false:while(a>b)而不是写成while((a>b)==true)
简化复杂的表达式
1、拆分复杂的判断并引入新的布尔类型变量
2、把复杂的表达式做布尔函数:如果测试条件要经常重复用到或很分散,把这部分代码写成函数,这样在阅读主流程代码时,就无须再去读哪个复杂的判断了;并且新函数名为程序引入了一个抽象,可以清晰地在代码中说明该逻辑判断的目的。
3、用决策表代替复杂的条件
编写肯定形式的布尔表达式
1、在 if 语句中,把条件从否定形式转化为肯定形式,再把 if 和 else 语句后跟着的代码对换。
if(!statusOk){
//do something
}else{
//do something
}
改写成:
if(statusOk){
//do something
}else{
//do something
}
2、用狄摩根定理简化否定的布尔判断:
if(!displayOk || !printerOk)
改写成
if(!(displayOk && printerOk))
狄摩根定理逻辑转换法则:
用括号使布尔表达式更清晰
if ( a< b = = c = =d )改写成if((a<b)= =(c= =d))…
布尔表达式全部括在括号里面,增强代码的可读性,用一种简单的计数技巧使括号对称:开始时置“0”。沿着表达式从左到右,遇到一个开括号置“1”,每次遇到一个开括号把数加 1,每遇到一个闭括号把数减 1,如果最后数目回到“0”,则括号数保持平衡。
理解布尔表达式是如何求值的
利用短路求值判断:
if ( (denominator != 0) && ((item/denominator) > MIN_VALUE) )
当 denominator 等于 0 时,整个表达式计算会出现被 0 除错误。但既然当第一部分为真(不等 0)时第二部分才被计算,因而不会出现 Denominator 被零除的情形,也就不会出被零除的错误。如果&变为&&就会出现除零操作
按照数轴的顺序编写数值表达式
按数轴的顺序组织数字运算,i放在判断成功之后的位置,如下面例子:
MinElmts <= i and i<= MaxElmts //判断i在最小值和最大值之间,所以就放在中间
i < MinElmts or MaxElmts < i //判断i是否在两端,所以放在两边
while(i<inElmts) //判断i小于inElmts,所以放在左边
while(minElmts<i) //判断i大于minElmts
与0比较的指导原则
while(!done) //只有逻辑变量才使用隐式的比较
while( balance != 0) //把数和0进行比较的正确方式,不要使用隐式比较
while( *charPtr != '\0') //比较字符的格式
while( bufferePtr != NULL) //把指针和NULL进行比较
布尔表达式的常见问题
应该把常量写在等号的左侧,判断的变量写在编译器的右侧,防止出现将’==‘写成’='的情况
复合语句(语句块)
'复合语句’或‘语句块’指的是一组语句,该组语句被视为一条单一的语句,用于控制程序流程:(1)把括号一起写出(2)用括号把条件表达清楚,即便是一条一句也需要加代码块{}
空语句
1、小心使用空语句:分号自占一行,缩进,加上空括号
2、为空语句创建一个DoNothing()预处理宏或者内联函数
3、尽量不要使用非空循环体
驯服危险的深层嵌套
避免使用3到4层的嵌套,下面给出一些用于避免深层嵌套的方法:
1、通过重复检测条件中的某一部分来简化嵌套的if语句:
糟糕的深层嵌套代码:
if(Error==None) {
/*lots of code*/
if( PrinterRoutine!= NULL){
/*lots of code*/
if(SetupPage()){
/*lots of code*/
if(AllocMem(&PrintData)){
/*lots of code*/
}/* if AllocMem()*/
}/* if SetupPage()*/
}/* if PrinterRountine*/
}/* if Error * /
利用重复检测的非嵌套代码:
if( Error==None){
/*lots of code*/
if( PrinterRoutine!= NULL){
/*lots of code*/
}
}
if(Error== None && PrinterRoutine!= NULL && SetupPage()){
/*lots of code*/
if(AllocMem(&PrintData)){
/*lots of code*/
}
}
2、用break块来简化嵌套if
优化之后代码:
do{
if(Error!=None)
break;
/*lots of code*/
if( PrinterRoutine!= NULL)
break;
/*lots of code*/
if(SetupPage())
break;
/*lots of code*/
if(AllocMem(&PrintData))
break;
/*lots of code*/
}while(false)
3、把嵌套if转换成一组i-then-else语句
茂盛的决策树:
if(10<quantity){
if(100<quantity){
if(1000<quantity){
discount = 0.10;
}else{
discount = 0.05;
}
}else{
discount = 0.025;
}
}else{
discount = 0.0;
}
将嵌套的if语句转换为一组if-then-else语句:
if(1000<quantity){
discount = 0.10;
}else if(100<quantity){
discount = 0.05;
}else if(10<quantity){
discount = 0.025;
}else{
discount = 0.0;
}
4、把嵌套if转换成case语句: 使用在if-else if-else判断整数的时候
5、把深层嵌套的代码抽取出来放到一个子程序 新的子程序只是从原来的子程序中提取出来,形成新的子程序。简化了原来子程序的嵌套。将嵌套转移到子程序, 更方便阅读代码。
对减少嵌套层次的技术总结:
(1)重新判读一部分代码。
(2)转换成if-then-else
(3)使用break来简化嵌套if
(4)转化成case语句
(5)把深层嵌套的代码提取成单独的子程序
(6)添加中间状态重写代码
(7)完全重写设计深层嵌套的代码
编程基础:结构化编程
结构化编程的核心基于这样一种简单思想,即程序总是单入单出的结构,即程序只能从一个地方开始且也只能从一个地方退出的代码块,没有其它的进口与出口。单入单出的控制结构指的就是一个代码块,它只能从一个位置开始执行,并且只能结束于一个位置。
结构化编程的中心论点是,任何一种控制流都可以由顺序、选择(if)和迭代(循环)这三种结构生成。在使用break,continue,return时,都要持一种批判的态度。
控制结构与复杂度
如何度量复杂度:
if (( ( Status = Success ) and Done ) or (not Done and ( NumLines >= MaxLines)) ) then…
在这个程序中,从 1 算起,遇到“if”得 2,遇到“and”得 3,遇到“or”得 4,又遇到一个“and”得 5,这样程序总共含有 5 个决定点
如何处理复杂度ude度量结果:
0~5 程序可能很好
6~10 得想办法简化程序
10 以上 得把部分代码写成子程序并在原程序调用
要点
1、使用布尔表达式简单可读,将非常有助于提高你的代码的质量。
2、深层次的嵌套使得程序变得难以理解,所幸的是可以相对容易地避免这么做。
3、结构化编程是一种简单并且仍然适用的思想:你可以把顺序、选择和循环三者组合起来而开发出任何程序。
4、将复杂度降低到最低水平是编程高质量代码的哦关键。