一般控制问题

布尔表达式

用 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、将复杂度降低到最低水平是编程高质量代码的哦关键。

猜你喜欢

转载自blog.csdn.net/weixin_37921201/article/details/88832124
今日推荐