循环
while
概述
while 循环的作用:Repeats a block of statements while a condition is True or until a condition becomes True.
while 循环的通用形式:
while (condition) statement
statement 可以是以分号结尾的简单语句, 也可以是用花括号括起来的复合语句.
复合语句和简单语句从语法上来说都算是一条单独语句.
condition 是测试表达式.
while 循环使用的是入口条件的有条件循环, 所谓 "有条件" 指的是语句部分的执行取决于测试表达式描述的条件. 该表达式是一个入口条件, 因为必须满足条件才能进入循环体.
不确定循环是指在测试表达式为假之前, 预先不知道要执行多少次循环.
计数循环是指在执行循环之前就知道要重复执行多少次.
while(a!=0)
等价于while(a)
,while(a==0)
等价于while(!a)
。
程序示例:
用户键入一系列整数, 程序计算这些整数的和并进行输出.
#include<stdio.h> int main(void) { long num; long sum = 0L; int status; printf("Enter an integer to be summed (q to quit): "); while (scanf("%d", &num)) { sum += num; printf("Enter next integer (q to quit): "); } printf("Those integers sum to %ld.\n", sum); return 0; }
结果:
Enter an integer to be summed (q to quit): 3 Enter next integer (q to quit): 4 Enter next integer (q to quit): 5 Enter next integer (q to quit): q Those integers sum to 12.
程序示例:
#include <stdio.h> #define ADJUST 7.31 // 字符常量 int main(void) { const double SCALE = 0.333; // const 常量 double shoe, foot; printf("Shoe size (men's) foot length\n"); shoe = 3.0; while (shoe < 18.5) // while 循环开始 { // 块开始 foot = SCALE * shoe + ADJUST; printf("%10.1f %15.2f inches\n", shoe, foot); shoe=shoe+1.0; } // 块结束 printf("If the shoe fits, wear it.\n"); return 0; }
结果:
Shoe size (men's) foot length 3.0 8.31 inches 4.0 8.64 inches 5.0 8.97 inches 6.0 9.31 inches 7.0 9.64 inches 8.0 9.97 inches 9.0 10.31 inches 10.0 10.64 inches 11.0 10.97 inches 12.0 11.31 inches 13.0 11.64 inches 14.0 11.97 inches 15.0 12.31 inches 16.0 12.64 inches 17.0 12.97 inches 18.0 13.30 inches If the shoe fits, wear it.
程序示例:
#include<stdio.h> int main(void) { const int NUMBER = 10; int count = 1; // 初始化计数器 while (count <= NUMBER) // 计数器和有限值作比较 { printf("Be my valentine!\n"); count++; // 每次循环计数器递增 } return 0; }
结果:
Be my valentine! Be my valentine! Be my valentine! Be my valentine! Be my valentine! Be my valentine! Be my valentine! Be my valentine! Be my valentine! Be my valentine!
这是一个计数循环, 但是定义循环的行为并未组织在一起, 程序的编排不理想.
创建一个计数循环时有三个行为:
-
初始化计数器
-
计数器和有限值作比较
-
每次循环计数器递增
用 while 循环创建计数循环时未能将这三个行为组织在一起.
处理输入行的剩余部分:
while (getchar() != '\n') continue;
continue 在 while 中的使用
如果 continue 在嵌套循环内, 则只会影响包含该语句的内层循环.
continue 后是执行循环头内的测试表达式.
break 在 while 中的使用
如果 break 在嵌套循环内, 则只会影响包含该语句的内层循环.
for
概述
创建一个计数循环时有三个行为:
- 初始化计数器
- 计数器和有限值作比较
- 每次循环计数器递增
用 while 循环创建计数循环时未能将这三个行为组织在一起.
用 for 循环创建计数循环时能将这三个行为组织在一起.
程序示例:
#include<stdio.h> int main(void) { const int NUMBER = 10; int count; for (count = 1; count <= NUMBER; count++) { printf("Be my valentine.\n"); } return 0; }
一般, 建议 for 语句的控制变量的取值范围是前开后闭, 即:
count = 1; count <= NUMBER;
这里的 NUMBER 可以展示出特殊的意义, 如循环的次数, 元素的总的个数等等.
结果:
Be my valentine. Be my valentine. Be my valentine. Be my valentine. Be my valentine. Be my valentine. Be my valentine. Be my valentine. Be my valentine. Be my valentine.
for 循环的格式:
for (expression1 ; expression2 ; expression3) 语句
expression1
是初始化语句, 一般用来初始化计数器. 只在 for 循环刚开始时执行一次.
expression2
是测试条件, 在循环之前对 expression2
求值, 为真则执行 for 循环的语句, 为假则结束 for 循环.
expression3
执行更新, 更新计数器, 使得 expression2
会变成假, 否则出现死循环.
for 的圆括号里的三个表达式也叫做控制表达式, 它们都是完整表达式, 因此每个表达式的副作用都发生在对下一个表达式求值之前.
程序示例:
#include<stdio.h> int main(void) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { printf("ok\n"); } } return 0; }
结果:
ok ok ok ok ok ok ok ok ok
程序示例:
#include<stdio.h> int main(void) { int i = 0, j = 0; for (; i < 3; i++) { for (; j < 3; j++) { printf("ok\n"); } } return 0; }
结果:
ok ok ok
程序示例:
#include<stdio.h> int main(void) { int num; printf(" n n cubed\n"); for (num = 1; num <= 6; num++) { printf("%5d %7d\n", num, num * num * num); } return 0; }
结果:
n n cubed 1 1 2 8 3 27 4 64 5 125 6 216
递减计数器的程序示例:
#include<stdio.h> int main(void) { int secs; for (secs = 5; secs > 0; secs--) { printf("%d seconds!\n", secs); } printf("We have ignition!\n"); return 0; }
结果:
5 seconds! 4 seconds! 3 seconds! 2 seconds! 1 seconds! We have ignition!
计数器每次循环都增加一个较大的值:
#include<stdio.h> int main(void) { int n; for (n = 2; n < 40; n += 13) { printf("n = %d\n", n); } return 0; }
结果:
n = 2 n = 15 n = 28
用字符代替计数:
#include<stdio.h> int main(void) { char ch; for (ch = 'a'; ch <= 'z'; ch++) printf("The ASCII value for %c is %d.\n", ch, ch); return 0; }
结果:
The ASCII value for a is 97. The ASCII value for b is 98. The ASCII value for c is 99. The ASCII value for d is 100. The ASCII value for e is 101. The ASCII value for f is 102. The ASCII value for g is 103. The ASCII value for h is 104. The ASCII value for i is 105. The ASCII value for j is 106. The ASCII value for k is 107. The ASCII value for l is 108. The ASCII value for m is 109. The ASCII value for n is 110. The ASCII value for o is 111. The ASCII value for p is 112. The ASCII value for q is 113. The ASCII value for r is 114. The ASCII value for s is 115. The ASCII value for t is 116. The ASCII value for u is 117. The ASCII value for v is 118. The ASCII value for w is 119. The ASCII value for x is 120. The ASCII value for y is 121. The ASCII value for z is 122.
由于字符在计算机内存中是以整数存储的, 所以该循环实际上仍是用整数来计数的.
测试条件除了可以测试循环的次数, 还可以测试其他条件:
#include<stdio.h> int main(void) { int num; printf(" n n cubed\n"); for (num = 1; num*num*num <= 666; num++) { printf("%5d %7d\n", num, num * num * num); } return 0; }
结果:
n n cubed 1 1 2 8 3 27 4 64 5 125 6 216 7 343 8 512
这里的程序更加关心立方的值不超过一个限度, 而不是关心循环的次数.
让计数器几何增长, 而不是算数增长, 即每次都是乘以一个固定的值, 而不是加上一个固定的值.
#include<stdio.h> int main(void) { double debt; for (debt = 100.0; debt < 150.0; debt = debt * 1.1) { printf("Your debt is now %2.2f.\n", debt); } return 0; }
结果:
Your debt is now 100.00. Your debt is now 110.00. Your debt is now 121.00. Your debt is now 133.10. Your debt is now 146.41.
for 循环三个表达式的省略
三个表达式都可以是任意合法的表达式.
可以省略一个或多个表达式, 但不能省略分号.
省略第二个表达式被视为真.
省略第一个表达式的程序示例:
#include<stdio.h> int main(void) { int i = 0; int j = 0; for (; i < 10; i++) { for (; j < 10; j++) { printf("Hello\n"); } } return 0; }
结果:
Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
从结果可以看出, 只打印了十次, 因为在第一次执行完外层循环后, j 的值为 10, 在第二次外循环时, 执行到内循环时, j 没有被赋值, 所以还是10, 内层循环的条件不成立, 内层循环不执行. 所以除了第一次外层循环外的其余外层循环都不执行, 最终只有 10 次打印.
嵌套循环
嵌套循环常用于按行和列显示数据, 一个循环处理一行中的所有列, 另一个循环处理所有的行.
程序示例:
#include<stdio.h> int main(void) { const int ROW = 6; const int CHAR = 10; int num; char ch; for (num = 0; num < ROW; num++) // 外层循环 (outer loop) { for (ch = 'A'; ch < 'A' + CHAR; ch++) // 内层循环 (inner loop) { printf("%c", ch); } printf("\n"); // 在下一次运行内层循环时将在下一行打印字符 } return 0; }
结果:
ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ
可以用外层循环控制内层循环, 使得每次外层循环迭代时内层循环执行不同的任务:
#include<stdio.h> #define ROW 6 #define CHAR 6 int main(void) { int num; char ch; for (num = 0; num < ROW; num++) { for (ch = 'A' + num; ch < 'A' + CHAR; ch++) // ch 的初始化随外层循环改变, 测试条件不变 { printf("%c", ch); } printf("\n"); } return 0; }
结果:
ABCDEF BCDEF CDEF DEF EF F
不要在循环体内部改变计数器的值.
for 循环和 while 循环内的 continue 的比较
for 循环内的 continue:
#include<stdio.h> int main(void) { int i = 0; for (i = 1; i <= 10; i++) { if (i == 5) continue; printf("%d ", i); } return 0; }
结果:
1 2 3 4 6 7 8 9 10
for 循环里的 continue 执行完了后, 下一步是执行循环头中的表达式 3, 表达式 3 执行完了后执行表达式 2, 即判断表达式.
while 里的 continue:
#include<stdio.h> int main(void) { int i = 0; while (i <= 10) { if (i == 5) continue; printf("%d ", i); i++; } return 0; }
结果: 一个死循环.
while 循环里的 continue 执行完了后执行循环头中的判断条件.
for 循环和 while 循环内的 break 的比较
for 循环中, 执行完 break 语句之后, 执行循环体外的第一条语句, 连循环头内的更新子表达式都不会执行.
do while
while 和 for 循环都是入口条件循环, 即在每次循环开始之前检查测试条件, 有可能根本不执行循环体中的内容.
do...while
是出口条件循环, 在循环的每次迭代之后检测测试条件, 所以至少执行循环体中的内容一次.
do...while
循环的通用形式:
do { statement } while (expression);
statement 可以是一条简单语句或复合语句.
do...while
以分号结尾.
do...while
适合那些至少执行一次的循环.
程序示例:
#include<stdio.h> int main(void) { int i = 0; do { printf("%d\n", i); i++; } while (i < 10); return 0; }
结果:
0 1 2 3 4 5 6 7 8 9
程序示例:
#include<stdio.h> int main(void) { const int SECRET = 10; int secret; do { printf("Enter the secret: "); scanf("%d", &secret); } while (secret != SECRET); printf("You are right!\n"); return 0; }
结果:
Enter the secret: 12 Enter the secret: 11 Enter the secret: 10 You are right!
这个程序非常不安全, 一旦 scanf()
读取失败, 输入的内容会保留着内存中, 下一次还是这个内存中的内容, 还是会读取失败, 所以形成一个死循环.
改写为 while 入口循环:
#include<stdio.h> int main(void) { const int SECRET = 10; int secret; printf("Enter the secret: \n"); scanf("%d", &secret); while (secret != SECRET) { printf("Enter the secret: \n"); scanf("%d", &secret); } printf("You are right!\n"); return 0; }
结果:
Enter the secret: 12 Enter the secret: 11 Enter the secret: 10 You are right!
显然程序要更长一点.
一个死循环:
#include<stdio.h> int main(void) { int i = 1; do { if (i == 5) continue; printf("%d\n", i); i++; } while (i <= 10); return 0; }
打印完 1234 后进入死循环.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术