2.4.语句和控制结构

语句

一般的编程语言通常都以语句为基本单位,程序由多条语句构成。PHP中,分号标记了一个语句的结束,并且一条语句必须以分号作为结束。

任何具有意义的程序代码都可以作为一条语句。例如之前提到的表达式

倘若在后面加上一个分号,就成了一条语句。

$c=$a+$b;

正常情况下,PHP程序是从上到下按照语句的排列顺序来执行,如果想要完成更复杂的业务逻辑,则需要借助控制结构。和其他的编程语言相同,PHP也具有选择结构和循环结构。

控制结构可以改变语句的执行顺序,使得原本单调的顺序结构得以扩展,让程序可以解决更复杂的问题。

##语句块 语句块由多个语句组成,包含在花括号中。语句块通常表示一组功能上有关联的代码,通常在选择结构、循环结构、函数上使用。

选择结构

选择结构会使程序流程增加分支,程序运行到分支处时,会根据选择条件的判断结果来决定执行哪一个分支。如果你在数学课上学习过程序框图的话,这张图你一定不会陌生:

上图是一个最简单的if选择结构。通过多个if结构堆叠起来,可以实现更多分支的选择结构,例如:

但是在编写代码的过程中,这样写是非常冗余的,而且也不利于维护。如果想要表达一个平行的多分支选择结构,通常会是这个样子

上述三种结构,都是很常见的选择结构。下面我们将介绍如何使用代码来表达这三种结构。

if-else选择结构

结构实现的是单条件选择,通常的形式是这样的:

if($cond){

//do something

}else{

//or do another thing

}

$cond可以是一个值,也可以是一个变量,更常见的是一个逻辑表达式。当$cond的值为true时,执行if下面花括号中的语句块,否则执行else中的语句。例如下面一段代码。

//choose.php

$a=$_GET['a'];

if($a>){

echo'a大于0';

}else{

echo'a不大于0';

}

是PHP自带的超全局变量,可以用来获取get方式传过来的变量值。这部分内容会在后面进行详细讲解。这里可以理解为是获取一个值,这个值来自你访问的url。

运行这段代码。首先访问,得到的结果是

修改访问的url,访问,得到的结果是

在这段程序中,首先我们从get参数中获取到了$a的值,并根据$a的值的不同情况,分别给出不同的处理。

当业务逻辑复杂起来,需要我们处理更多种情况的时候,可以叠加使用if-else结构。我们接下来看一个具体的问题。

某小学成绩和成绩等级对应如下表:

现需要编写程序,输入成绩等级,程序会给出对应的成绩区间。

如果使用if-else结构,我们这样编写代码:

//scoreAndRank.php

$rank=$_GET['rank'];

if($rank=='A'){

echo'该同学的成绩区间是:100~80';

}elseif($rank=='B'){

echo'该同学的成绩区间是:79~60';

}elseif($rank=='C'){

echo'该同学的成绩区间是:59~40';

}elseif($rank=='D'){

echo'该同学的成绩区间是:39~20';

}elseif($rank=='E'){

echo'该同学的成绩区间是:19~0';

}else{

echo'输入的成绩等级不合法';

}

尝试运行代码

我们看到,当分支情况复杂起来的时候,if结构也会变得异常复杂。上面的例子只是简单的叠加情况,代码就冗余成这种程度。通常当我们需要处理一系列平级的选择条件时,通常会使用switch结构。

switch结构

switch结构是选择结构的另一种方式,通常用来处理具有多个平行条件的选择结构。switch结构通常的形式是这样的:

switch($value){

case$value1: do_something_1();break;

case$value2: do_something_2();break;

case$value3: do_something_3();break;

...

default: do_default_thing();

}

程序会将value与下面每一个case后面的value比较,执行值互相匹配的case后面的语句。会使程序在执行完对应的功能之后退出switch结构。关于的作用会在循环结构中详细讲解。

case匹配之后执行的语句可以是一条,也可以是一个语句块。case后面的结构也可以是这个样子:

switch($value){

case$value1: {

do_something_1_1();

do_something_1_2();

}break;

...

}

如果没有任何一个case与value相匹配,则执行default后面的语句。如果没有default情况,则直接跳出switch结构。

如果使用switch结构处理刚才“成绩-等级”的问题,可以改写成如下代码:

//scoreAndRank.php

switch($rank){

case'A':echo'该同学的成绩区间是:100~80';break;

case'B':echo'该同学的成绩区间是:79~60';break;

case'C':echo'该同学的成绩区间是:59~40';break;

case'D':echo'该同学的成绩区间是:39~20';break;

case'E':echo'该同学的成绩区间是:19~0';break;

default:echo'输入的成绩等级不合法';

}

default情况不是必须的,但是通常具有一定经验的程序员,都会在switch结构中补齐default情况。这样可以使程序结构和逻辑更加完整,而且可以避免出现一些不可预料的情况。

switch结构也有一定的缺陷和局限性。switch结构只能处理“等于”的情况。思考一下,如果将上述问题改为“输入成绩,输出成绩等级”,这时switch结构就没有办法应付这个问题。

if和switch两种结构各有各的优势和劣势,在实际编程中应灵活变通。选择最适合的语句结构,程序才会有最优的效率。

循环结构

除了选择结构外,另一种结构就是循环结构。通常我们会用循环结构来处理“需要反复处理”的问题。循环结构会让程序在运行过程中的某几步之间往复进行,当满足某一些条件的时候再跳出循环结构。用框图表示一个最普通的循环结构如下图所示:

我们来看一个具体的问题。

使用程序求1~100自然数的和。

这个问题在数学中再简单不过了,使用数学上的求和符号,一步就算出了结果。

使用程序解决这个问题,实际上和求和符号的原理相同,都是用了“循环”的思想。PHP有三种方式来描述选择结构,接下来我们将借助这个简单的求和问题来一一认识它们。

while结构

while结构的一般形式是:

while($cond){

//do something

}

当$cond成立,就一直执行花括号内的语句块。使用while解决上面的求和问题,代码可以这样写:

//sum.php

$a=;$sum=;

while($a

$sum+=$a;

$a++;

}

echo'1~100的和是:'.$sum;

这里的可以写成

在程序中,当系统读到时,会先读取a的值来进行相关运算,之后再将a的值增加1。相反地,如果使用,则会先将a的值增加1,再读取加1后的值来进行相关运算。和同理。

do-while结构

do-while结构的一般形式是:

do{

//do something

}while($cond)

do-while会先执行语句块,再判断$cond是否成立,如果成立则重复语句块的内容。与while结构相比,do-while会先执行后判断。在这二者中,需要根据具体的情形来选择需要使用哪一个结构。二者都是循环结构,在本质上并无太大区别,只是有时候使用do-while会比使用while更容易思考问题。

for结构

for结构的一般形式是:

for(语句1; 语句2; 语句3;){

//do something

}

for结构的运行流程是这样的。

for结构是最常用的循环结构。上面的求和问题如果改写成for结构的话,代码可以改写成:

//sum.php

for($i=,$sum=;$i

$sum+=$i;

}

echo'1~100的和是:'.$sum;

for结构的强大之处在于,上面所说的三条语句,可以理解为“程序的三个时刻”,并不一定要局限于三条语句。第一个位置通常被称为“初始状态”,第二个位置被称为“循环条件”,第三个位置则是每次循环过后需要处理的内容。

如上面的代码所示,初始状态中我们为$i和$sum赋了初始值,这里用逗号连接了两条语句。而第三个位置中的$i++,实际上也可以写在语句块之内。

改变循环状态

为了体现编程不是那么简单的,我们不能用一个求和的问题来来回回算了好多遍。那现在我们来考虑另外几个循环的问题。

问题8.1:计算自然数1~1000中,全部偶数的和。

问题8.2:自然数中,从1开始计算总和,直到遇到500以后的第一个3的倍数。

基于上述两个问题,我们来介绍continue和break语句。

continue语句

在循环体内使用continue语句时,会跳过本次循环,直接开始下一次循环。用流程图表示的话是这个样子的:

考虑上面的问题8.1。如果要计算全部偶数的和,那我们就循环1~1000,遇到奇数跳过(continue)就可以了。下面我们编写代码。

//sum2.php

for($i=1,$sum=;$i

if($i%2==){

//两数相除,余数是0则为可以整除

//一个数如果能被2整除,则这个数是偶数

$sum+=$i;

}else{

continue;

}

}

echo'自然数1~1000中,全部偶数的和是:'.$sum;

为了让continue的效果更直观,我们在else中加一句

echo$i.'被跳过了。

';

运行这段代码,我们看到结果是

在运行结果中看到,所有的奇数都被跳过,所有的偶数都被加入了总和中。在continue语句的帮助下,这个问题就解决了。

break语句

与continue相比,break就显得很绝情。在循环体内使用break语句时,会使当前循环直接结束。break语句在流程图中是这样的:

考虑问题8.2。从1开始循环自然数,先不用决定在哪里停下,因为在解决问题之前谁也不知道500后面的第一个3的倍数是什么。当判断当前的数字大于500并且是3的倍数,就停止循环。在这之前,所有的数字都要加入加和之中。问题构思好了,我们来编写代码。

//sum3.php

$i=;

$sum=;

while(true){

$sum+=$i;

if($i>500&&$i%3==){

break;

}

$i++;

}

echo'遇到500之后的第3的倍数时自然数的总和是:'.$sum.',这个3的倍数是:'.$i;

这段代码的运行结果是

可以看到,在判断条件成立时,break语句使while循环结构直接中断,使程序流程跳转到了循环之外。

goto语句

与选择结构、循环结构相比而言,至少前两者都还是有规律可循的。选择结构会按照判断的条件来使程序进入不同的分支,循环结构则会按照判断条件使程序进行某种往复的工作。但goto语句与二者都不同。作为可以控制程序流程的一条语句,它没有任何规律。goto语句会使程序直接跳转到某一个特定的位置。

goto语句通常与标号同时使用。标号和goto语句通常形式是这样的:

//标号

flag:

//跳转

gotoflag;

我们看这样一段代码。

//goto.php

$f=true;

flag:

echo'程序开始啦~

';

echo'我也不知道接下来会发生什么。

';

echo'goto来啦!

';

if($f){

echo'回到开始!

';

$f=false;

gotoflag;

}else{

echo'程序结束!

如果不设置分支,程序会死循环。

';

}

这段代码的运行结果是

这段代码体现了goto语句标号和跳转的使用方法。

经验丰富的前辈们往往指出,goto语句具有很大的不可控因素,在编程中不推荐使用。但要这样考虑,goto语句作为编程语言中的一部分,一定有它存在的意义。编程过程中一定要按照自己的意愿去做,也就是“把真实的你讲给计算机听”。goto是一把利刃,是一把锋利的双刃剑。善用它,往往会事半功倍。

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20190202G12YBA00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券