3、循环结构

目标:掌握循环的结构语法,掌握循环的实际运用

概念

循环结构:指通过某种条件的限定,然后某个代码块进行可控的重复的执行

  • 循环结构一般包含以下几个部分

    • 循环条件:判定循环是否执行
    • 循环变量变化:让条件持续改变
    • 循环体:要重复执行的代码块
    • 循环控制:内部对循环的控制
  • PHP中循环结构有以下几个

    • while循环:不确定条件的重复执行
    • for循环:一般指定次数的重复执行
    • foreach循环:专门遍历数组
    • do-while循环:了解
  • 循环控制:内部控制循环的执行

步骤

1、根据循环条件确定要重复的内容,选择合适的循环结构

2、确定循环条件的边界

3、确定循环条件的变更方式

4、确定循环体(要重复执行的代码块)

5、确定循环内部控制(不一定要)

小结

1、循环结构是一种让代码在可控范围内执行N次的流程结构(重复执行)

2、循环结构包含多种

  • while循环
  • for循环
  • foreach循环
  • do-while循环

3、循环也可以在内部进行循环控制

3.1、while循环

目标:掌握while循环的基本语法,熟练运用while循环实现内容重复执行

提问:想输出1-10可不可以不是10次echo呢?

回答:可以,1到10是有规矩,找一个东西从1变到10就好

概念

while循环:在指定边界条件下,持续执行代码的一种循环

  • while循环需要边界条件(也可以没有)
  • while条件需要在内部控制循环变量
  • while循环多用来实现一些条件不大明确的循环
  • 语法结构
while(条件表达式){
    循环体;
    循环条件变更;
}

步骤

1、通常会在循环开始前定义一个循环变量的初始值

2、确定循环条件的边界条件

3、确认循环体(循环要干嘛)

4、变更循环条件

示例

#输出1-10

#1、确定循环变量初始值:可以是1,也可以是10
$i = 1;

#2、确定循环边界条件:10
while($i <= 10){
    #3、确定循环体:输出1-10
    echo $i;                #$i代表1
    
    #4、变更循环条件
    $i++;
}

流程图解析

以上图输出1-10的整数为例

graph LR
A(执行开始)-->B[确定循环变量初始值<br/>$i = 1]
B-->C{while条件判定<br/>$i <= 10}
C-->|TRUE|D[进入循环体<br/>循环变量变更<br/>$i++]
D-->C
C-->|FALSE|E((循环结束))

小结

1、while循环是一种利用外部循环条件实现代码重复执行的循环

2、while循环基本逻辑

  • 定义循环条件初始值:1次执行
  • 在while(条件表达式)中确定循环的边界条件:N + 1次执行
  • 在循环内部实现循环体:N次执行
  • 在循环内部实现循环变量的变更:N次执行

3.2、for循环

目标:掌握for循环的语法结构,熟练使用for循环实现代码重复执行

概念

for循环:一种将循环初始条件、循环边界条件和循环条件变更都可以放到循环结构里(不是循环体)的循环

  • for循环需要循环初始化条件,但可以在循环结构里
  • for循环需要边界条件,也可以放在循环结构里
  • for循环进行循环条件变更,也可以放到结构里
  • for循环一般用来实现一些固定起始、边界和步长(条件变化的规律)的循环,多与数字有关
  • for语法结构
for(初始化条件表达式;边界判定表达式;条件变更表达式){
    循环体
}

步骤

1、确定循环初始化条件

2、确定边界条件

3、确定变化规则(步长)

4、确定循环体

示例

输出1-100之间的所有奇数

#确定初始条件:1:$i = 1;
#确定边界条件:100:$i <= 100;
#确定条件变化规则:1-100的整数:$i++
#确定循环体:输出变化中的$i:奇数:$i % 2 == 1

for($i = 1;$i <= 100;$i++){
    #循环体:找到奇数
    if($i % 2 == 1){
        #说明是奇数
        echo $i;
    }
}

循环嵌套:打印九九乘法表

#打印九九乘法表:一个循环要么打印一行1,2,3,4,5,要么打印一列(<br/>)
#而九九乘法表是一个表格,有行有列:所以单个循环肯定无法完成,需要多个循环共同完成

#分析
#1、确定一个循环:能够打印9行
for($i = 1;$i <= 9;$i++){
    #9行其实就是一个换行符代表换一行
    echo '<br/>';
}

#2、确定一个循环:能够输出9列
for($j = 1;$j <= 9;$j++){
    echo $j;
}

#3、以上两个是独立的循环,彼此没有交集:我们需要一行里就有9列,而不是只有一列:将能够输出9列的循环移入到能输出行的循环中
for($i = 1;$i <= 9;$i++){
    #将打印9列的循环移入到能打印行的循环中:实现9行9列输出
    for($j = 1;$j <= 9;$j++){
        echo $j;
    }
    #9行其实就是一个换行符代表换一行
    echo '<br/>';
}

#4、确定每一个单元的输出:九九乘法表并非一直输出,输出逻辑是:列数不大于行数,从第一列开始输出,第1个数为列号,第二个乘数为行号
/*
 1 * 1 = 1
 1 * 2 = 2    2 * 2 = 4    #第一个数1,2为列数,第二个数2位行数
*/
for($i = 1;$i <= 9;$i++){
    #将打印9列的循环移入到能打印行的循环中:实现9行9列输出
    for($j = 1;$j <= 9;$j++){
        #输出:确保列数不能大于行数
        if($j <= $i){
             #有效输出位置:列号在前,行号在后
            echo "$j * $i = " . $j * $i . ' ';    #输出带一个空格
            #"$j * $i = "是一个字符串只会解析变量,$j * $i是一个乘法表达式,会得出结果
        }
    }
    #9行其实就是一个换行符代表换一行
    echo '<br/>';
}

流程图解析

以上图输出1-100之间的奇数为例

graph LR
A(循环开始)-->B[初始化条件<br/>$i = 1]
B-->C{条件判定<br/>$i <= 100}
C-->|FALSE|F((循环结束))
C-->|TRUE|D[进入循环体<br/>执行循环体]
D-->G[条件变更<br/>$i++]
G-->C{条件判定<br/>$i <= 100}

小结

1、for循环是可以所有循环参与条件都在for循环结构内部的循环

2、for循环结构如下

for(表达式1;表达式2;表达式3){
   循环体   
}

3、for循环执行流程

  • 表达式1:用来初始化条件(只执行一次)

    • 如果初始化条件在外部,该位置可以空出
    • 如果有多个条件需要初始化,该位置可以使用逗号分隔
  • 表达式2:用来验证条件(起始到边界总次数+1次【最后一次失败循环退出】)

    • 验证通过:进入循环体
    • 验证失败:结束循环
  • 循环体:执行重复内容(起始到边界总次数)
  • 表达式3:变更循环条件(起始到边界总次数)

4、for循环实际通常用来做一些明确次数的循环

3.3、foreach循环

目标:掌握foreach的语法结构,了解foreach原理,灵活使用foreach进行数组遍历

概念

foreach循环:PHP中专门进行数组遍历的循环

  • foreach循环专门遍历数组
  • foreach循环可以解析数组的下标和值
  • foreach语法
foreach(数组变量 as [下标变量 =>] 值变量){
    通过下标变量读取数组中每个元素的下标(可以没有)
    通过值变量读取数组中每个元素的值
}

步骤

1、确定要遍历的数组

2、确定是否需要用到下标

3、确定下标变量和值变量(名字自取:$k|$key,$v|$value)

4、确定循环体

示例

输出个人的全部信息

#定义数组
$info = array('name' => '鸣人','skill' => '螺旋丸');

#1、确定要遍历的数组$info
#2、确定是否需要下标:需要
#3、确定相关变量:下标使用$key保存,值使用$value保存
foreach($info as $key => $value){
    #4、确定循环体:输出信息
    echo $key . ' : ' . $value . '<br/>';
}

流程图解析

以上述案例为例:数组有一个元素指针,默认指向第一个元素

graph LR
A(循环开始)-->B[重置数组指针<br/>$info]
B-->C{当前指针所指元素<br/>是否有效}
C-->|无效|E((循环结束))
C-->|有效|D[取出元素<br/>下标赋值给$key<br/>值赋值给$value<br/>数组指针下移]
D-->F[进入循环体]
F-->C

小结

1、foreach是专门用来进行数组遍历的

2、foreach是根据数组指针所在的位置挨个取出元素的

  • 重置指针:执行一次
  • 判定指针有效性

    • 指针有效:取出数组元素

      • 下标赋值给下标变量(如果提供了下标变量)
      • 值赋值给值变量
      • 指针下移
    • 指针无效:循环结束
  • 进入循环体

3、foreach可以不获取数组元素的下标

4、foreach极少对一维数组进行遍历,通常是二维数组(多维)

3.4、do-while循环

目标:了解do-while的基本语法以及执行原理,了解do-while与while的区别

概念

do-while循环:是一种先执行循环体(do)然后再考虑条件的循环

  • do-while循环需要边界条件
  • do-while循环在内部变更循环条件
  • do-while用来处理不明确条件的循环
  • do-while语法
do{
    循环体
    循环条件变更
}while(循环条件判定);

步骤

1、通常会在循环开始前定义一个循环变量的初始值

2、确认循环体(循环要干嘛)

3、变更循环条件

4、确定循环条件的边界条件

示例

输出1-10

#定义条件初始变量
$i = 1;

#循环开始
do{
    #输出
    echo $i;
    #循环条件变更
    $i++;
}while($i <= 10);        #注意:需要分号结尾

流程图解析

graph LR
A(循环开始)-->B[初始化循环条件<br>$i = 1]
B-->C[进入循环体<br>执行循环体]
C-->D[循环条件变更<br>$i++]
D-->E{循环条件判定<br>$i <= 10}
E-->|TRUE|C
E-->|FALSE|F((循环结束))

小结

1、do-while也是一种利用外部循环条件实现的内部代码重复执行的循环

2、do-while循环的语法

循环条件初始化
do{
    循环体
    循环条件变更
}while(循环条件判定);

3、do-while与while循环的区别

  • while是先判定条件后执行,do-while是先执行后判定条件
  • do-while一定会保证循环体至少循环一次,而while未必会执行循环体

4、在PHP中do-while基本不使用(了解一下这个原理)

3.5、循环控制

目标:掌握循环控制的基本原理和实际需求,利用循环控制实现循环内部控制

提问:如果在循环执行过程中出现了某些异常或者某些不符合条件的,能怎么办?

回答:循环控制

概念

循环控制:即循环体内通过代码对控制循环如何执行

  • 循环体内控制代码的执行方向
  • 循环控制是为了增加程序的健壮性,让开发者可以在循环内部把握循环的正确执行
  • 根据需求(条件)进行控制

    • 终止单次循环体执行:continue [层级],层级默认1(直接进行下一次循环)
    • 终止循环(循环结束):break [层级],层级默认1

步骤

1、循环开始

2、循环体内是否需要判定条件

  • 条件满足:选择控制

    • 确定控制层级(单层循环不需要)
  • 条件不满足:不需要控制

示例

求出1-100之间所有非3的倍数的和

#定义初始变量(使用while循环)
$i = 1;
$sum = 0;    #记录和

while($i <= 100){
    #确定当前变量$i是否是3的倍数
    if($i % 3 == 0){
        #是3的倍数:这个值不记录:但是后续的代码不用再执行(注意条件要变化)
        $i++;
        continue;        #continue之后的循环体不执行
    }
    
    #求和:同时变更变量
    $sum += $i++;        #等价于:$sum = $sum + $i++(后置自操作,先使用原值,后自操作)
}

求出1-100之间所有的数的和

#定义初始变量
$i = 1;
$sum = 0;

#开始循环:条件永远为真
while(TRUE){
    #外部没有进行条件控制:说明循环是死循环,我们要在内部保证循环不会一直执行
    if($i > 100){
        #已经不满足需求:循环没有必要继续
        break;
    }
    
    #如果前面条件不满足:说明当前是满足循环要求的,继续执行
    $sum += $i++;
}

九九乘法表优化

#原九九乘法表
for($i = 1;$i <= 9;$i++){
    #将打印9列的循环移入到能打印行的循环中:实现9行9列输出
    for($j = 1;$j <= 9;$j++){
        #输出:确保列数不能大于行数
        if($j <= $i){
             #有效输出位置:列号在前,行号在后
            echo "$j * $i = " . $j * $i . ' ';    #输出带一个空格
            #"$j * $i = "是一个字符串只会解析变量,$j * $i是一个乘法表达式,会得出结果
        }
    }
    #9行其实就是一个换行符代表换一行
    echo '<br/>';
}

#问题:当内存循环$j > $i之后,虽然不会输出,但是内层for循环会一直执行直到$j > 9,这部分是无效执行:所以应当优化,即内存循环$j > $i之后已经没有执行的意义了(结束循环)
for($i = 1;$i <= 9;$i++){
    #将打印9列的循环移入到能打印行的循环中:实现9行9列输出
    for($j = 1;$j <= 9;$j++){
        #输出:确保列数不能大于行数
        if($j <= $i){
             #有效输出位置:列号在前,行号在后
            echo "$j * $i = " . $j * $i . ' ';    #输出带一个空格
            #"$j * $i = "是一个字符串只会解析变量,$j * $i是一个乘法表达式,会得出结果
        }else{
            #循环控制:进入else说明$j > $i,已经失去意义了
            break;    #当前break是控制所属循环(j循环),所以终止也是当前j循环,进入到i循环执行<br>
        }
    }
    #9行其实就是一个换行符代表换一行
    echo '<br/>';
}

流程图示例

continue流程控制

graph LR
A(循环开始)-->B{循环条件判定<br>大条件}
B-->|不满足条件|D((循环结束))
B-->|满足条件|C[执行循环体]
C-->E{内部条件判定<br>后续代码是否需要执行<br>continue}
E-->|需要|F[后续代码继续执行]
E-->|不需要|B
F-->B

break流程控制

graph LR
A(循环开始)-->B{循环条件判定<br>大条件}
B-->|不满足条件|D((循环结束))
B-->|满足条件|C[执行循环体]
C-->E{内部条件判定<br>循环是否需要继续}
E-->|需要|F[后续代码继续执行]
E-->|不需要|D
F-->B

小结

1、循环控制是在循环内部提供了一种可以控制循环的机制

  • 内部控制,给开发者提供灵活性
  • 内部控制,给开发者提供优化空间(省去不必要的循环)

2、循环控制分为两种

  • 终止单次循环:continue
  • 终止整个循环:break

3、循环控制有层级,如果在多层循环中需要控制到不同的层级,可以使用层级数

  • continue [N]:回到N层循环继续下一次循环开始
  • break [N]:跳出到N+1层循环,如果没有N+1层循环,循环结束
  • N如果为1,那么可以省去
Last modification:February 11th, 2020 at 07:05 pm