1. Chapter8 语句和控制结构

1.1. 语句

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

任何具有意义的程序代码都可以作为一条语句。例如之前提到的表达式$c = $a + $b,倘若在后面加上一个分号,就成了一条语句。

$c = $a + $b;

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

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

1.2. 语句块

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

1.3. 选择结构

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

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

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

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

1.3.1. if-else选择结构

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

if($cond){
    //do something
}else{
    //or do another thing
}

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

<?php
//choose.php
    $a = $_GET['a'];
    if($a > 0){
        echo 'a大于0';
    }else{
        echo 'a不大于0';
    }

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

运行这段代码。首先访问/code/choose.php?a=2,得到的结果是 修改访问的url,访问/code/choose.php?a=-1,得到的结果是

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

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

某小学成绩和成绩等级对应如下表: |等级|成绩| |:--:|:--:| |A|100~80| |B|79~60| |C|59~40| |D|39~20| |E|19~0|

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

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

<?php
//scoreAndRank.php
    $rank = $_GET['rank'];
    if($rank == 'A'){
        echo '该同学的成绩区间是:100~80';
    }else if($rank == 'B'){
        echo '该同学的成绩区间是:79~60';
    }else if($rank == 'C'){
        echo '该同学的成绩区间是:59~40';
    }else if($rank == 'D'){
        echo '该同学的成绩区间是:39~20';
    }else if($rank == 'E'){
        echo '该同学的成绩区间是:19~0';
    }else{
        echo '输入的成绩等级不合法';
    }

尝试运行代码

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

1.3.2. 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后面的语句。break会使程序在执行完对应的功能之后退出switch结构。关于break的作用会在循环结构中详细讲解。

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.4. 循环结构

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

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

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

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

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

1.4.1. while结构

while结构的一般形式是:

while($cond){
    //do something
}

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

<?php
//sum.php
    $a = 0;
    $sum = 0;
    while($a <= 100){
        $sum += $a;
        $a ++;
    }

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

这里的$sum += $a;$a ++;可以写成$sum += $a++;

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

1.4.2. do-while结构

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

do{
    //do something
}while($cond)

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

1.4.3. for结构

for结构的一般形式是:

for(语句1; 语句2; 语句3);{
    //do something
}

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

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

<?php
//sum.php
    for($i = 0,$sum = 0;$i <= 100;$i ++;){
        $sum += $i;
    }

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

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

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

1.5. 改变循环状态

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

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

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

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

1.5.1. continue语句

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

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

<?php
//sum2.php
    for($i = 1,$sum = 0;$i <= 1000;$i ++){
        if($i % 2 == 0){
            //两数相除,余数是0则为可以整除
            //一个数如果能被2整除,则这个数是偶数
            $sum += $i;
        }else{
            continue;
        }
    }

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

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

echo $i.'被跳过了。<br/>';

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

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

1.5.2. break语句

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

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

<?php
//sum3.php
    $i = 0;
    $sum = 0;
    while(true){
        $sum += $i;
        if($i > 500 && $i % 3 == 0){
            break;
        }
        $i ++;
    }

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

这段代码的运行结果是

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

1.6. goto语句

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

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

//标号
flag:

//跳转
goto flag;

我们看这样一段代码。

<?php
//goto.php
    $f = true;
flag:
    echo '程序开始啦~<br/>';
    echo '我也不知道接下来会发生什么。<br/>';
    echo 'goto来啦!<br/>';
    if($f){
        echo '回到开始!<br/>';
        $f = false;
        goto flag;
    }else{
        echo '程序结束!<br/>如果不设置分支,程序会死循环。<br/>';
    }

这段代码的运行结果是

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

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

这本书是xt写的/上次修改: 2019-04-17 14:57:44

results matching ""

    No results matching ""