if
基本上所有的程序语言,程序结构都分为:顺序结构、选择结构、循环结构这三种类型。顺序结构:代码从上自下执行,注意一下每行语句的依赖关系。(有的时候,可以适当的调整位置,提前某个变量的定义、某条语句的位置,然后后面代码可以共用这个代码的福利)。选择结构,便是本文的重点对象,进行分支选择。正是因为它的存在,让代码有了可变,让每次的执行,都不太一样。循环结构,然某个重复单元重复执行。
选择结构:常用的有if,swith,也有一些利用and or进行短路处理。或者用字典来做选择。
程序出口。一定要注意,每个分支都要有一个出口。如果相同的处理,可以利用技巧共用。
if
最简单的结构
$age = 1;
if($a){
$age = 2;
}
或者
if($a){
$age = 2;
}else{
$age = 1;
}
多分支结构
if($a>90){
echo '优秀!';
}else if($a>80){
echo '还不错';
}else if($a > 60){
echo '及格';
}else{
echo '成绩不合格,需加油啊!';
}
现实中上上面这样简单的判断(没有什么好讲,关键在于里面的条件都不同。)。
嵌套分支。
if($a > 0 ){
if($b){
return ''; // 第1个return
}else{
//not return
}
}else{
//do somethin and contuine;
}
// do something common
return '';//第2个return
堆叠
if($a==90){
echo '优秀!';
}
if($a==80){
echo '还不错';
}
if($a == 60){
echo '及格';
}
上面的堆叠,虽然,只能进入其中一个入口。但是用上多分支,只有其中一个执行,可能更好。
一些常用的思想,如例子:
function getData($b){
if($自己并没有使例化){
//好吧,先实例化
}
return $实例话的变量。
}
swith
and、or
重复判断
代码大全里讲,通过重复判断,能降低嵌套层次。
下面的原本是,这样
if( $target_prot){
$urls['step4'] = "http://localhost:$target_prot/";
if($top_url){
$urls['step4'] = "http://localhost:$target_prot". self::getUri($top_url);
}
}
改为扁平的结构:
if($top_url && $target_prot){
$urls['step4'] = "http://localhost:$target_prot". self::getUri($top_url);
}else if( $target_prot ){
$urls['step4'] = "http://localhost:$target_prot/";
}
卫语句
if虽然非常好用,但是滥用,会造成代码非常难理解。
逻辑转换与有优化
示例1
需求是:倒计时,如果超过60秒,则,每60秒提醒一次。1分钟内,则希望60、30、20、10,这几个时间点进行提醒。对于这种对于同一个切面的分类,按顺序处理:超过60秒,则intval为60,针对60、30这个点,则intval为30,少于30,则为10。所以便有如下代码。
Sub sleep(n)
Dim intv = 60 ' 每隔一段时间提醒一次
Dim left
For i = 1 To n
Delay 1000
left = n - i
If left > 60 Then
intv = 60
Else If left > 30 Then
int = 30
Else
int = 10
End If
If i Mod intv = 0 Then
TracePrint "等待"&(n-i)& "秒"
End If
Next
End Sub
' 上面的代码,看起来很复杂。由于intv默认值已经给了,所以第1个分支,其实是多余的。所以,我们考虑反序。
' 反序后,我们发现,第3个分支,包含了第2个分支,所以,intval实际上取两个值就行。10跟60。
' 所以代码如下:代码一下见解了很多。
Sub sleep(n)
Dim intv = 60 ' 每隔一段时间提醒一次
Dim left
For i = 1 To n
Delay 1000
left = n - i
If left <= 30 Then
int = 10
End If
If i Mod intv = 0 Then
TracePrint "等待"&(n-i)& "秒"
End If
Next
End Sub
' 如果只是合并2跟3分支,则如下
Sub sleep(n)
Dim intv = 60 ' 每隔一段时间提醒一次
Dim left
For i = 1 To n
Delay 1000
left = n - i
If left >= 60 Then
intv = 60
Else If left <= 30 Then
int = 10
End If
If i Mod intv = 0 Then
TracePrint "等待"&(n-i)& "秒"
End If
Next
End Sub
总结:针对上面类似的优化,对于同一个逻辑切面,而又有默认的值,那么我们考虑,两种顺序的逻辑如何写。另外,能减少分支,尽量减少分支的处理。比如,intv只有10跟60两种情况,已经满足我们的需求,那么,我们就没有必要10、30、60这3种情况了。
切分
示例
示例1
if(strpos($msg,$error)!==false){
//直接使用 shell 完成编码纠正。
exec("iconv -f UTF-8 -t UTF-8 -c -o {$newfile} {$filename};");
//再次尝试导入修正后的文件
safe_import($newfile,$try_times+1);
}elseif($table ==='th_gpsdata' && (strpos($msg,$error2)!==false || strpos($msg,$error3) !==false ) ){ //csv gps中demical格式错误 ,高度超高,只针对th_gpsdata 表
check_num($filename,$newfile);
safe_import($newfile,$try_times+1);
}else{
throw new Exception($msg, 1);
}
第2个条件非常复杂。拆分的话:
if($table ==='th_gpsdata' ){ //csv gps中demical格式错误 ,高度超高,只针对th_gpsdata 表
if(strpos($msg,$error2)!==false || strpos($msg,$error3) !==false){
check_num($filename,$newfile);
safe_import($newfile,$try_times+1);
}
// else 分支,没有办法交给后续的分支
}
怎么理解上面这种情况呢?
示例2
场景:从首页到签到页,再到娱乐中心页。不确定当前是哪一页。比如,如果当前是首页,则需要经过2个页面的操作,才能到达第3页。
所以,下面简单的叠加场景,正适合不确定当前是哪一页的判断。如果下面的If判断,反过来,则不成立。
'判断当前页面
If is_index() Then
TracePrint "应该不会到主页"
TracePrint "进入主界面,等待10秒"
Touch 380,75,500
Delay 10000
End If
If findText("签到") Then
TracePrint "选择领取3g流量,等待10秒"
Touch 96,508,200
Delay 10000
End If
If findText("娱乐中心") Then
If get_top() > -1 Then
TracePrint "找到了顶部"
adjust_top
End If
' 水平滑动几次
For page-1
TracePrint "水平滑动"
huadong (4)
Delay 2000
Next
End If
示例3
锁结构代码、标识代码。
$flag = false
if (!$flag) {
//当前没有其他人操作,则先操作,再释放锁。
//todo 操作
$flag = false
}
c语言防止头文件重复加载,原理是类似的:
#ifndef _STDIO_H
#define _STDIO_H
/* 声明部分 */
#endif