循环语句
概述
循环语句是编程中用于重复执行代码块的控制结构。当需要多次执行相同或类似的操作时,循环语句可以大大简化代码,提高效率。PHP提供了几种循环结构:
for循环 - 计数器循环,适用于已知循环次数的场景while循环 - 条件循环,当条件为真时重复执行do-while循环 - 后测试循环,至少执行一次foreach循环 - 数组遍历循环,专门用于遍历数组
for 循环
基本语法
for (初始化表达式; 条件表达式; 递增表达式) {
// 循环体代码
}
语法说明
- 初始化表达式:在循环开始前执行一次,通常用于初始化计数器
- 条件表达式:在每次循环开始前求值,如果为 true 则继续执行循环体
- 递增表达式:在每次循环结束后执行,通常用于更新计数器
- 执行顺序:初始化 → 条件判断 → 循环体 → 递增 → 条件判断 → ...
基础示例
<?php
// 基础的 for 循环
echo "=== 基础 for 循环示例 ===<br>";
for ($i = 1; $i <= 5; $i++) {
echo "第 $i 次循环<br>";
}
// 输出:第 1 次循环、第 2 次循环...第 5 次循环
// 倒序循环
echo "<br>=== 倒序循环 ===<br>";
for ($i = 10; $i >= 1; $i--) {
echo "$i ";
}
// 输出:10 9 8 7 6 5 4 3 2 1
// 步长为 2 的循环
echo "<br><br>=== 步长为 2 的循环 ===<br>";
for ($i = 0; $i <= 10; $i += 2) {
echo "$i ";
}
// 输出:0 2 4 6 8 10
// 多个变量的 for 循环
echo "<br><br>=== 多变量初始化 ===<br>";
for ($i = 0, $j = 10; $i < $j; $i++, $j--) {
echo "i=$i, j=$j<br>";
}
?>
实际应用示例
<?php
// 1. 生成乘法表
echo "=== 九九乘法表 ===<br>";
echo "<table border='1'>";
for ($i = 1; $i <= 9; $i++) {
echo "<tr>";
for ($j = 1; $j <= 9; $j++) {
$product = $i * $j;
echo "<td>$i × $j = $product</td>";
}
echo "</tr>";
}
echo "</table><br>";
// 2. 数组元素处理
$numbers = [1, 2, 3, 4, 5];
$sum = 0;
$factorial = 1;
echo "=== 数组处理 ===<br>";
for ($i = 0; $i < count($numbers); $i++) {
$sum += $numbers[$i];
$factorial *= $numbers[$i];
echo "索引 $i: 值 {$numbers[$i]}, 累计和: $sum<br>";
}
echo "总和: $sum<br>";
echo "阶乘: $factorial<br><br>";
// 3. 字符串处理
$text = "Hello World!";
$reversed = "";
for ($i = strlen($text) - 1; $i >= 0; $i--) {
$reversed .= $text[$i];
}
echo "原字符串: $text<br>";
echo "反转字符串: $reversed<br><br>";
// 4. 图形输出
echo "=== 星形图案 ===<br>";
for ($i = 1; $i <= 5; $i++) {
for ($j = 1; $j <= $i; $j++) {
echo "* ";
}
echo "<br>";
}
// 金字塔图案
echo "<br>=== 金字塔图案 ===<br>";
for ($i = 1; $i <= 5; $i++) {
// 打印空格
for ($j = 1; $j <= 5 - $i; $j++) {
echo " ";
}
// 打印星号
for ($j = 1; $j <= 2 * $i - 1; $j++) {
echo "*";
}
echo "<br>";
}
?>
while 循环
基本语法
while (条件表达式) {
// 循环体代码
}
语法说明
- 条件表达式:在每次循环开始前求值
- 执行流程:检查条件 → 如果为 true 执行循环体 → 重新检查条件
- 适用场景:当循环次数不确定,只知道循环条件时使用
基础示例
<?php
// 基础的 while 循环
echo "=== 基础 while 循环 ===<br>";
$count = 1;
while ($count <= 5) {
echo "计数: $count<br>";
$count++;
}
// 读取文件内容(模拟)
echo "<br>=== 模拟文件读取 ===<br>";
$lines = ["第一行内容", "第二行内容", "第三行内容"];
$index = 0;
while ($index < count($lines)) {
echo "读取第 " . ($index + 1) . " 行: {$lines[$index]}<br>";
$index++;
}
// 用户输入验证(模拟)
echo "<br>=== 用户输入验证 ===<br>";
$attempts = 0;
$maxAttempts = 3;
$correctPassword = "123456";
$userInput = "wrong"; // 模拟错误输入
while ($attempts < $maxAttempts && $userInput !== $correctPassword) {
$attempts++;
echo "第 $attempts 次尝试,密码错误<br>";
// 在实际应用中,这里会提示用户重新输入
$userInput = ($attempts === 3) ? "123456" : "wrong";
}
if ($userInput === $correctPassword) {
echo "登录成功!<br>";
} else {
echo "尝试次数过多,登录失败!<br>";
}
?>
实际应用示例
<?php
// 1. 数据库查询结果处理(模拟)
echo "=== 数据库查询结果处理 ===<br>";
// 模拟数据库查询结果
$databaseResults = [
['id' => 1, 'name' => '张三', 'score' => 85],
['id' => 2, 'name' => '李四', 'score' => 92],
['id' => 3, 'name' => '王五', 'score' => 78],
['id' => 4, 'name' => '赵六', 'score' => 88],
['id' => 5, 'name' => '钱七', 'score' => 95]
];
$index = 0;
$totalScore = 0;
$passedCount = 0;
while ($index < count($databaseResults)) {
$student = $databaseResults[$index];
$totalScore += $student['score'];
if ($student['score'] >= 60) {
$passedCount++;
echo "✅ {$student['name']}: {$student['score']} 分 (及格)<br>";
} else {
echo "❌ {$student['name']}: {$student['score']} 分 (不及格)<br>";
}
$index++;
}
$averageScore = $totalScore / count($databaseResults);
$passRate = ($passedCount / count($databaseResults)) * 100;
echo "<br>统计结果:<br>";
echo "平均分: " . round($averageScore, 2) . "<br>";
echo "及格率: " . round($passRate, 2) . "%<br>";
// 2. 质数判断
echo "<br>=== 质数判断 ===<br>";
function isPrime($number) {
if ($number < 2) return false;
$divisor = 2;
while ($divisor * $divisor <= $number) {
if ($number % $divisor == 0) {
return false;
}
$divisor++;
}
return true;
}
$testNumbers = [2, 3, 4, 5, 16, 17, 19, 20, 23, 25];
foreach ($testNumbers as $num) {
if (isPrime($num)) {
echo "$num 是质数<br>";
} else {
echo "$num 不是质数<br>";
}
}
// 3. 数字反转
echo "<br>=== 数字反转 ===<br>";
function reverseNumber($number) {
$reversed = 0;
$original = $number;
while ($number > 0) {
$digit = $number % 10; // 取最后一位
$reversed = $reversed * 10 + $digit; // 构建反转数
$number = (int)($number / 10); // 去掉最后一位
}
return $reversed;
}
$numbersToReverse = [123, 4567, 89, 1001];
foreach ($numbersToReverse as $num) {
$reversed = reverseNumber($num);
echo "原数: $num, 反转: $reversed<br>";
}
?>
do-while 循环
基本语法
do {
// 循环体代码
} while (条件表达式);
语法说明
- 执行特点:先执行循环体,后检查条件
- 至少执行一次:即使条件为 false,循环体也会执行一次
- 适用场景:需要至少执行一次的操作,如用户输入、菜单显示等
基础示例
<?php
// 基础的 do-while 循环
echo "=== 基础 do-while 循环 ===<br>";
$count = 1;
do {
echo "第 $count 次执行<br>";
$count++;
} while ($count <= 3);
// 条件不满足的情况
echo "<br>=== 条件不满足的情况 ===<br>";
$count = 5;
do {
echo "至少执行一次,当前值: $count<br>";
} while ($count <= 3);
// 用户输入验证(模拟)
echo "<br>=== 用户输入验证 ===<br>";
$attempts = 0;
$maxAttempts = 3;
do {
$attempts++;
echo "请输入密码 (第 $attempts 次尝试):<br>";
// 模拟用户输入
$input = ($attempts === 2) ? "correct" : "wrong";
if ($input === "correct") {
echo "密码正确!<br>";
break;
}
} while ($attempts < $maxAttempts);
if ($attempts >= $maxAttempts) {
echo "尝试次数过多!<br>";
}
// 菜单系统
echo "<br>=== 简单菜单系统 ===<br>";
$choice = '';
do {
echo "==== 主菜单 ===<br>";
echo "1. 查看信息<br>";
echo "2. 修改设置<br>";
echo "3. 退出<br>";
echo "请选择 (1-3): ";
// 模拟用户选择
$choice = '3';
echo "$choice<br>";
switch ($choice) {
case '1':
echo "显示用户信息<br>";
break;
case '2':
echo "进入设置页面<br>";
break;
case '3':
echo "感谢使用,再见!<br>";
break;
default:
echo "无效选择,请重新输入<br>";
}
} while ($choice !== '3');
?>
foreach 循环
基本语法
// 遍历数组的值
foreach (数组 as 值) {
// 循环体代码
}
// 遍历数组的键和值
foreach (数组 as 键 => 值) {
// 循环体代码
}
语法说明
- 专门用于数组:foreach 是 PHP 中专门用于遍历数组的循环结构
- 键值对:可以同时获取数组的键和值
- 简化操作:相比 for 循环,foreach 更简洁且不易出错
- 适用场景:数组遍历、对象属性遍历等
基础示例
<?php
// 基础的 foreach 循环
echo "=== 基础 foreach 循环 ===<br>";
// 简单索引数组
$fruits = ['苹果', '香蕉', '橙子', '葡萄'];
foreach ($fruits as $fruit) {
echo "水果: $fruit<br>";
}
// 关联数组
echo "<br>=== 关联数组遍历 ===<br>";
$student = [
'name' => '张三',
'age' => 20,
'major' => '计算机科学',
'gpa' => 3.8
];
foreach ($student as $key => $value) {
echo "$key: $value<br>";
}
// 多维数组
echo "<br>=== 多维数组遍历 ===<br>";
$students = [
[
'name' => '张三',
'scores' => ['数学' => 85, '英语' => 92, '编程' => 95]
],
[
'name' => '李四',
'scores' => ['数学' => 78, '英语' => 88, '编程' => 82]
]
];
foreach ($students as $index => $student) {
echo "学生 " . ($index + 1) . ": {$student['name']}<br>";
foreach ($student['scores'] as $subject => $score) {
echo " $subject: $score 分<br>";
}
echo "<br>";
}
// 数组修改(引用传递)
echo "<br>=== 数组修改 ===<br>";
$numbers = [1, 2, 3, 4, 5];
echo "原数组: " . implode(', ', $numbers) . "<br>";
foreach ($numbers as &$value) {
$value = $value * 2;
}
unset($value); // 解除引用
echo "修改后数组: " . implode(', ', $numbers) . "<br>";
?>
实际应用示例
<?php
// 1. 电商购物车处理
echo "=== 购物车价格计算 ===<br>";
$cartItems = [
['name' => 'iPhone 14', 'price' => 6999, 'quantity' => 1],
['name' => 'AirPods', 'price' => 1299, 'quantity' => 2],
['name' => '手机壳', 'price' => 99, 'quantity' => 3]
];
$subtotal = 0;
$itemCount = 0;
foreach ($cartItems as $item) {
$itemTotal = $item['price'] * $item['quantity'];
$subtotal += $itemTotal;
$itemCount += $item['quantity'];
echo "{$item['name']}: {$item['quantity']} × ¥{$item['price']} = ¥$itemTotal<br>";
}
$tax = $subtotal * 0.1; // 10% 税费
$shipping = ($subtotal >= 100) ? 0 : 10; // 满100免运费
$total = $subtotal + $tax + $shipping;
echo "<br>商品小计: ¥$subtotal<br>";
echo "税费 (10%): ¥$tax<br>";
echo "运费: ¥$shipping<br>";
echo "总计: ¥$total<br>";
echo "商品数量: $itemCount 件<br>";
// 2. 配置文件处理
echo "<br><br>=== 配置文件处理 ===<br>";
$config = [
'database' => [
'host' => 'localhost',
'port' => 3306,
'username' => 'admin'
],
'app' => [
'name' => 'MyApp',
'version' => '1.0.0',
'debug' => true
]
];
foreach ($config as $section => $settings) {
echo "配置段: [$section]<br>";
if (is_array($settings)) {
foreach ($settings as $key => $value) {
echo " $key: $value<br>";
}
} else {
echo " $settings<br>";
}
echo "<br>";
}
?>
循环控制
break 语句
break 用于立即跳出当前循环:
<?php
// break 示例
echo "=== break 语句示例 ===<br>";
for ($i = 1; $i <= 10; $i++) {
if ($i === 6) {
echo "遇到 $i,跳出循环<br>";
break;
}
echo "$i ";
}
// 输出: 1 2 3 4 5
// 查找数组中的特定元素
echo "<br><br>=== 查找特定元素 ===<br>";
$numbers = [10, 23, 45, 67, 89, 12, 34];
$target = 67;
$foundIndex = -1;
foreach ($numbers as $index => $number) {
echo "检查索引 $index: 值 $number<br>";
if ($number === $target) {
$foundIndex = $index;
echo "找到目标值 $target 在索引 $index,停止搜索<br>";
break;
}
}
if ($foundIndex !== -1) {
echo "目标值 $target 的位置: $foundIndex<br>";
} else {
echo "未找到目标值 $target<br>";
}
?>
continue 语句
continue 用于跳过当前循环的剩余代码,开始下一次循环:
<?php
// continue 示例
echo "=== continue 语句示例 ===<br>";
for ($i = 1; $i <= 10; $i++) {
if ($i % 2 === 0) {
continue; // 跳过偶数
}
echo "$i "; // 只输出奇数
}
// 输出: 1 3 5 7 9
// 过滤数组中的空值
echo "<br><br>=== 过滤空值 ===<br>";
$data = ['apple', '', 'banana', null, 'cherry', false, 'date'];
$filteredData = [];
foreach ($data as $index => $value) {
if (empty($value)) {
echo "索引 $index: 空值,跳过<br>";
continue;
}
$filteredData[] = $value;
echo "索引 $index: 保留值 '$value'<br>";
}
echo "<br>过滤后的数组: " . implode(', ', $filteredData) . "<br>";
?>
循环最佳实践
1. 选择合适的循环类型
<?php
// 什么时候使用哪种循环
// ✅ 推荐:已知循环次数使用 for
echo "=== 使用 for 循环的情况 ===<br>";
for ($i = 0; $i < 10; $i++) {
echo "处理第 " . ($i + 1) . " 个项目<br>";
}
// ✅ 推荐:未知循环次数,只知道条件使用 while
echo "<br>=== 使用 while 循环的情况 ===<br>";
$remaining = 100;
while ($remaining > 0) {
$consumed = rand(10, 30);
$remaining = max(0, $remaining - $consumed);
echo "消耗 $consumed,剩余 $remaining<br>";
}
// ✅ 推荐:必须至少执行一次使用 do-while
echo "<br>=== 使用 do-while 循环的情况 ===<br>";
$temperature = 25;
do {
echo "当前温度: $temperature°C<br>";
$temperature += rand(-2, 3);
} while ($temperature < 30);
// ✅ 推荐:数组遍历使用 foreach
echo "<br>=== 使用 foreach 循环的情况 ===<br>";
$users = ['Alice', 'Bob', 'Charlie'];
foreach ($users as $index => $user) {
echo "用户 " . ($index + 1) . ": $user<br>";
}
?>
2. 性能优化建议
<?php
// 循环性能优化
// ✅ 推荐:将函数调用结果缓存到变量
echo "=== 性能优化示例 ===<br>";
$array = range(1, 1000);
// 优化前:每次循环都调用 count()
$start = microtime(true);
for ($i = 0; $i < count($array); $i++) {
// 处理数组元素
}
$slowTime = microtime(true) - $start;
// 优化后:缓存 count() 结果
$start = microtime(true);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
// 处理数组元素
}
$fastTime = microtime(true) - $start;
echo "优化前时间: " . number_format($slowTime * 1000, 4) . "ms<br>";
echo "优化后时间: " . number_format($fastTime * 1000, 4) . "ms<br>";
?>
常见错误和解决方案
1. 无限循环
<?php
// 常见的无限循环问题
// ❌ 错误:忘记更新循环变量
// $i = 0;
// while ($i < 10) {
// echo $i; // $i 永远不会增加,无限循环
// }
// ✅ 正确:记得更新循环变量
$i = 0;
while ($i < 10) {
echo $i . " ";
$i++; // 更新循环变量
}
?>
2. foreach 中的引用问题
<?php
// foreach 引用问题
$array = [1, 2, 3, 4, 5];
// ✅ 正确:使用引用后及时解除
foreach ($array as &$value) {
$value = $value * 2;
}
unset($value); // 解除引用
echo "处理后的数组: " . implode(', ', $array) . "<br>";
?>
练习题
基础练习
-
数字求和
<?php // 练习:计算1到100的和 $sum = 0; // 使用 for 循环计算1到100的和 for ($i = 1; $i <= 100; $i++) { $sum += $i; } echo "1到100的和是: $sum"; ?> -
数组元素遍历
<?php // 练习:遍历数组并计算平均值 $numbers = [85, 92, 78, 95, 88, 76, 89, 94]; $total = 0; foreach ($numbers as $score) { $total += $score; } $average = $total / count($numbers); echo "平均分: " . round($average, 2); ?> -
九九乘法表
<?php // 练习:使用嵌套循环生成九九乘法表 echo "<table border='1'>"; for ($i = 1; $i <= 9; $i++) { echo "<tr>"; for ($j = 1; $j <= 9; $j++) { $product = $i * $j; echo "<td>$i × $j = $product</td>"; } echo "</tr>"; } echo "</table>"; ?>
进阶练习
-
质数生成器
<?php // 练习:生成指定范围内的所有质数 function generatePrimes($start, $end) { $primes = []; for ($number = $start; $number <= $end; $number++) { if ($number < 2) continue; $isPrime = true; for ($divisor = 2; $divisor * $divisor <= $number; $divisor++) { if ($number % $divisor == 0) { $isPrime = false; break; } } if ($isPrime) { $primes[] = $number; } } return $primes; } $primes = generatePrimes(1, 100); echo "1-100之间的质数: " . implode(', ', $primes); ?> -
斐波那契数列
<?php // 练习:生成斐波那契数列 function fibonacci($n) { $sequence = [0, 1]; for ($i = 2; $i < $n; $i++) { $sequence[$i] = $sequence[$i-1] + $sequence[$i-2]; } return $sequence; } $fib = fibonacci(10); echo "斐波那契数列: " . implode(', ', $fib); ?>
总结
循环语句是PHP编程中最重要的控制结构之一,掌握好循环对于编写高效、简洁的代码至关重要。以下是关键要点:
核心概念
- for 循环:适用于已知循环次数的场景
- while 循环:适用于条件控制的场景
- do-while 循环:至少执行一次的后测试循环
- foreach 循环:专门用于数组遍历
选择建议
- 固定次数:使用
for循环 - 条件控制:使用
while循环 - 至少一次:使用
do-while循环 - 数组遍历:使用
foreach循环
最佳实践
- 选择合适的循环类型
- 避免无限循环
- 注意循环性能优化
- 使用有意义的变量名
- 及时解除引用
- 为复杂循环添加注释
常见陷阱
- 忘记更新循环变量导致无限循环
- 在循环中修改数组结构
- foreach 中的引用问题
- 循环变量的作用域问题
通过大量的练习和实际应用,您将能够熟练运用各种循环结构来解决复杂的编程问题。循环是程序设计中最重要的概念之一,掌握好它将大大提高您的编程能力。