跳转到内容

第 4 章 循环结构程序设计

  • 4.1 while 语句
  • 4.2 do-while 语句
  • 4.3 for 语句
  • 4.4 goto 语句
  • 4.5 循环嵌套
  • 4.6 break 语句
  • 4.7 continue 语句
  • 4.8 编程实战

学完这一章,你应该能做到:

  • 理解循环的本质是“重复执行”。
  • 会写 whiledo-whilefor
  • 会分析循环变量的变化过程。
  • 知道 goto 的基本写法和使用场景。
  • 会写简单的循环嵌套。
  • 会使用 breakcontinue
  • 能独立解决求和、阶乘、素数、图形输出等题目。

循环就是让一段代码重复执行多次。

循环最重要的是三件事:

  • 初值
  • 条件
  • 变化

如果这三件事没有想清楚,循环题一般都会出错。

先判断条件,再决定执不执行。

while (条件)
{
语句;
}

示例:输出 1 到 5。

#include <stdio.h>
int main(void)
{
int i = 1;
while (i <= 5)
{
printf("%d ", i);
i++;
}
return 0;
}

先执行一次,再判断条件。

do
{
语句;
} while (条件);

它的特点是至少执行一次。

当循环次数比较明确时,for 最好用。

for (初值; 条件; 变化)
{
语句;
}

示例:求 1 到 100 的和。

#include <stdio.h>
int main(void)
{
int i, sum = 0;
for (i = 1; i <= 100; i++)
{
sum += i;
}
printf("%d\n", sum);
return 0;
}

goto 的作用是让程序直接跳转到某个指定位置继续执行。

基本写法:

goto 标签名;
标签名:
语句;

先看一个最简单的例子:

#include <stdio.h>
int main(void)
{
int i = 1;
start:
if (i > 5)
goto end;
printf("%d ", i);
i++;
goto start;
end:
return 0;
}

这个程序也能输出 1 2 3 4 5,但它其实是在“手动跳来跳去”模拟循环。

所以要记住:

  • goto 能用,但一般不推荐乱用。
  • 如果能用 whileforbreakcontinue 解决,就优先不用 goto
  • goto 用多了,程序流程会很乱,不容易看懂,也不容易排错。

在循环里,goto 偶尔会用于“直接跳出多层循环”。

例如:

#include <stdio.h>
int main(void)
{
int i, j;
for (i = 1; i <= 3; i++)
{
for (j = 1; j <= 3; j++)
{
if (i == 2 && j == 2)
goto finish;
printf("(%d, %d)\n", i, j);
}
}
finish:
printf("循环结束\n");
return 0;
}

i == 2 && j == 2 时,程序会直接跳到 finish:,外层和内层循环都会一起结束。

立即结束整个循环。

跳过本次循环后面的语句,直接进入下一轮。

示例:

for (i = 1; i <= 5; i++)
{
if (i == 3) {
continue;
}
printf("%d ", i);
}

输出为:

1 2 4 5

循环里再套循环,常用于:

  • 九九乘法表
  • 图形输出
  • 二维数组遍历

示例:输出一个 3 行 4 列的星号矩形。

#include <stdio.h>
int main(void)
{
int i, j;
for (i = 1; i <= 3; i++)
{
for (j = 1; j <= 4; j++)
{
printf("*");
}
printf("\n");
}
return 0;
}
sum = 0;
for (i = 1; i <= n; i++)
{
sum += i;
}
fact = 1;
for (i = 1; i <= n; i++)
{
fact *= i;
}
count = 0;
for (i = 1; i <= n; i++)
{
if (条件成立)
count++;
}
max = 第一个值;
for (后续每个值)
{
if (当前值 > max)
max = 当前值;
}
  • 少循环一次或多循环一次。
  • 忘记更新循环变量,导致死循环。
  • goto 当成普通循环工具,结果流程越来越乱。
  • breakcontinue 用反。
  • 循环嵌套时弄混内层和外层变量。
  • 在处理数字拆位时,没有注意循环什么时候结束。
  1. 写出下面程序的输出结果。
#include <stdio.h>
int main(void)
{
int i;
for (i = 1; i <= 5; i++)
{
if (i == 3)
continue;
printf("%d ", i);
}
return 0;
}
  1. 写出下面程序的输出结果。
#include <stdio.h>
int main(void)
{
int i;
for (i = 1; i <= 5; i++)
{
if (i == 3)
break;
printf("%d ", i);
}
return 0;
}
  1. while1 + 2 + ... + 100
  2. for 输出 1100 中所有奇数。
  3. 输入一个正整数 n,求 n!
  4. 输入一个正整数,求它有几位数。
  5. 输入一个整数,逆序输出它的每一位。
  6. 判断一个正整数是否为素数。
  7. 输出 100999 之间所有水仙花数。
  8. 输出九九乘法表。
  9. 输出下列图形:
*
**
***
****
*****
  1. 输入 n,求 1 + 1/2 + 1/3 + ... + 1/n
  2. 求两个整数的最大公约数。
  3. 输入若干个成绩,直到输入负数为止,统计及格人数。
  4. 输出 1 到 100 中所有能被 3 整除但不能被 5 整除的数。
  1. 输出一个等腰三角形。
  2. 求斐波那契数列前 n 项。
  3. 统计一个整数中数字 0 出现的次数。
  • 我能说清楚 whiledo-whilefor 的区别。
  • 我会写求和、求阶乘、统计个数这几类基础循环题。
  • 我能独立分析循环变量如何变化。
  • 我知道 goto 能跳转到标签,但平时不会乱用。
  • 我会使用 breakcontinue
  • 我能写简单的循环嵌套程序。
  • 循环题不要急着写代码,先把“从哪开始,到哪结束,每次怎么变”写在纸上。
  • 如果输出不对,就把每次循环里变量的值都列出来。
  • 第 4 章是后面数组、函数、指针的基础,一定要练熟。

学完这一章后,你就能解决大量“重复处理”的问题了。