while循环:为什么你的程序会卡死?
你有没有遇到过这种情况?运行一个程序后,终端像发了疯一样往下刷屏,按什么键都没反应,最后只能强制关闭。别急着怪电脑,这多半是你写了一个“永远停不下来”的循环——while循环的无限循环。
while就是“只要……就一直……”
while循环的规则很简单:只要条件为真,就重复执行花括号里的代码。它像你和朋友玩“石头剪刀布”——只要没分出胜负就一直玩。区别在于,while循环不会自动喊停,需要你自己在循环体里“改变局势”。
比如想从1数到5:
int i = 1;
while (i <= 5) {
cout << i << " ";
i = i + 1;
}
关键是那一行 i = i + 1。没有它,i 永远是1,条件永远成立,电脑就会无限输出。这就像玩石头剪刀布时,如果每次都出一样的,游戏永远结束不了——但现实中你们可以停下来,电脑只知道条件,不知道累。
先判断,再行动
while循环的执行流程是“先检查条件,再执行循环体”。执行完再回来检查,直到条件为假。这有个重要的推论:如果一开始条件就为假,循环体一次都不会执行。比如:
int i = 10;
while (i < 5) {
cout << "不会输出";
}
这跟“每天写作业前先问妈妈能不能看电视”一样:如果妈妈一开始就说不行,你连一次电视也看不上。
有个经典题目恰好考了这个流程:执行下面的代码,循环体执行几次?
int i = 0;
while (i < 5) {
i++;
}
很多人数成4次,理由是“最后一个数到5就不算了”。但实际上i从0到4,共5个值满足条件,所以循环体执行5次。容易错的地方在于:当i变成5时,循环体已经执行完第5次了,然后才去判断5<5为假。理解“先判断后执行”的顺序,这类题就不会做错。
新手最容易踩的三个“坑”
第一,忘记更新变量。这是最经典的死循环源。写 while (i <= 5) 却忘了 i++,程序就在那儿空转。
第二,在while条件后加了个分号。比如:
int i = 1;
while (i <= 5); // 分号!循环体是空语句
{
cout << i << " ";
i++;
}
这个分号让循环体变成了一个什么都不做的空语句,程序永远卡在 i <= 5 的判断上,后面的花括号里的代码根本执行不到。有些编译器不会报错,因为分号本身就是一个合法语句,这就是最阴险的地方。
第三,初始化位置不对。比如把 int i = 1; 写进循环体,每次循环i都被重置为1,又变成死循环。
什么时候用while最合适?
while擅长的是“不知道要循环多少次”的场景。比如猜数字游戏,用户可能猜3次,也可能猜100次,用for就不方便,因为次数不确定。而while只需要一个“猜对了吗”的条件:
int secret = 7;
int guess;
cin >> guess;
while (guess != secret) {
cout << "再猜一次:";
cin >> guess;
}
另外有一道经典题目很能体现while的“条件驱动”思路:已知1949年国庆节是星期六,输入一个年份n,求n年10月1日是星期几。你可以用while把年份从1949逐年累加到n,每过一年累计365天,遇到闰年多加1天:
int year = 1949;
int totalDays = 0;
while (year < n) {
totalDays += 365;
if (isLeap(year)) totalDays += 1;
year++;
}
这里 year++ 就是循环的“推进器”。算出总天数后,用 (6 + totalDays) % 7 就能得到星期几(注意把星期日映射为0)。这个题用while很自然,因为你是在“重复直到达到目标年份”,而不是预先数好循环次数。
什么时候应该用for?
如果你明确知道要循环多少次,比如输出0到4,那用for更简洁:
for (int i = 0; i < 5; i++) {
...
}
for把初始化、条件、更新都集中在括号里,不容易漏掉 i++。而while需要你自己在循环体里更新,一旦忘了就死循环。
再比如“输出所有长度为5的01串”这种题,总共32个,循环次数确定,用for嵌套会比while清晰得多。如果非要用while,你得自己维护五个变量,很容易出错。所以我的建议是:知道次数用for,不知道次数用while——这不是死规定,但能帮你少踩坑。
最后的话
while循环看起来简单,但真正的问题不在语法,而在“控制条件”。写while时,问问自己:循环体里有没有改变条件变量的语句?条件会不会有机会变成假?如果不会,那程序多半会卡死。理解了这个,你就掌握了while的精髓。
进阶的方向有两个:一个是do-while,它先执行一次再判断条件,适合“至少要做一次”的场景;另一个是break和continue,它们能在循环内部改变流程。学会它们之后,你能写出更灵活的程序。
关于作者
我是赵老师,持有 NOI 信息学奥赛教练证书,拥有 15 年以上的软件开发经验,从事信息学少儿编程教学已有 8 年时间。
这些年累计帮助 多名 学生通过编程特长升入自己心仪的目标学校。
如果你在编程学习上有任何疑问,欢迎联系我:18620372957(微信同号)