Skip to content

L1-14 while循环

while循环语句

格式

c++
while(表达式)
{
    循环体
}

以上为 while 循环的一般格式。再来看一个实际的例子:

c++
int i = 0;
 
while(i < 10)
{
    cout << "Hello world" << endl;
    i++;
}

执行这段程序,同之前的 for 程序相同,会输出 10 行 Hello world 。

这段 while 程序与上面的 for 程序,有着完全相同的执行流程。

i<10 为循环表达式。

cout<<"Hello world"<<endl 为循环体。

循环条件表达式

while 循环中的“表达式”就是循环条件,注意:这个表达式不可为空,当表达式为非 0 值或永真式时, while 循环陷入死循环。

循环体

循环体一般在 while 后用花括号括起来。可以是语句,代码段,或者新的循环。可以为空语句,可以是一个简单表达式。当循环体为一个表达式或者空语句时,可以省略花括号。

循环流程

while 循环的流程图如下:

单选题

for循环和while循环都是先判断表达式,后执行循环体

A. 错误

B. 正确

题解

B

for循环和while循环都是先判断表达式,后执行循环体

单选题

下面两个 while 循环,输入同样的 n(大于 0),哪一个执行的次数更多?

程序1

c++
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    while (n > 0)
        n--;

    return 0;
}

程序2

c++
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    while (n)
        n--;

    return 0;
}

A. 程序1更多

B. 程序2更多

C. 一样多

题解

C

while(n) 是判断 n 不等于 0。当 n 是正整数时,和 while(n>0) 的功能相同。

while循环实例

我们先来用 while 循环,实现一个 1−100 的累加:

c++
#include<bits/stdc++.h>
using namespace std;
int main() {
    int i = 1, sum = 0;
    
    while(i <= 100)
    {
        sum += i;
        i++;
        cout << sum << endl;
    }
}

以上这段代码将会输出:

text
1
3
6
10
....
4950
5050

除了处理一些基础的运算,循环结构还可以用来帮我们处理更多的输入。

c++
#include<bits/stdc++.h>
using namespace std;
int main() {
    int i = 0, sum = 0, value;
    
    while(i < 5)
    {
        cin >> value;
        sum += value;
        i++;
    }
            
    cout << sum << endl;
}

这段程序将对我们输入的 5 个数进行求和。如果输入: 1 8 6 4 7 ,将会输出 26 。

如果我们希望程序不只能处理 5 个数,而是按照我们输入的一个数字 k ,然后对后面 k 个数进行求和,那么程序可以这样写:

c++
#include<bits/stdc++.h>
using namespace std;
int main() {
    int i = 0, sum = 0, value, k;
    cin >> k;
    
    while(i < k)
    {
        cin >> value;
        sum += value;
        i++;
    }
            
    cout << sum << endl;
}

我们还可以配合之前学过的 if ,来处理更多的计算。下面这段程序,将会要求用户先输入一个数 k ,然后再输入 k 个数,程序会对所有输入的数字中, 5 的倍数进行求和。

c++
#include<bits/stdc++.h>
using namespace std;
int main() {
    int i = 0, sum = 0, value, k;
    cin >> k;
    
    while(i < k)
    {
        cin >> value;
        
        if(value % 5 == 0)
            sum += value;
        
        i++;
    }
            
    cout << sum << endl;
}

do...while循环语句

格式

c++
do{
    循环体
}while(表达式);

以上为 do...while 循环的一般格式。再来看一个实际的例子:

c++
int i = 0;
do{
    cout << "Hello!" << endl;
    i++;
}while(i < 10);

循环表达式

do...while 循环中的“表达式”就是循环条件,注意:这个表达式不可为空,当表达式为非0值或永真式时, do...while 循环陷入死循环,需要在循环体内部用 break 语句跳出(也可用 goto 语句跳到程序体中,但是不推荐) 。当它为 0 值或永假式时,循环不运行。

循环体

与 while 语句中的循环体相同,但是需要注意的是: do … while 语句中是先无条件执行一遍循环体, 再进入循环表达式的判断, 直到表达式为 0 退出循环。 而 while 语句每次执行循环体内容都需要先进行一次循环表达式的判断。

循环流程

do … while 循环的流程图如右图所示

do … while 循环在实际应用中,并不是很常见,大家更习惯于用 for 和 while 来解决问题,因此在这里不做更多实例分析。

单选题

while 循环是(),do−while 循环是()

  1. 先判断条件,再执行循环体
  2. 先执行循环体,再判断条件

A. 1 1

B. 1 2

C. 2 1

D. 2 2

题解

B

while 循环:先判断条件,再执行循环体 do−while 循环:先执行循环体,再判断条件

单选题

执行下面的程序,会输出()?

text
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n = 123456;
    while(n) {
        cout << n % 10;
        n /= 10;
    }

    return 0;
}

A. 123456

B. 654321

C. 12345

D. 65432

题解

B

1、从程序可知,这个题目的循环部分是取余除10,依次从最低位输出,输出123456输出654321

循环结构对比

while 循环与 for 循环可以相互替代,一般来说, while 语句和 do … while 语句适合事先不知道循环次数的循环, for 循环适合已知循环次数的循环。

结构上看, while 语句和 for 语句的循环体都需要判断后执行,而 do...while 语句第一次循环体执行的循环却不需要判断。因此,循环体至少执行一次适合使用 do...while 语句。

本质上来说,三种循环可以互相转换,没有本质上的区别,因此使用上可以凭借自己喜好,代码简洁,清晰一目了然即可。

习题

课堂练习:启蒙练习-2的幂整除

给一个正整数n,计算它最多能被2的多少次幂整除

输入格式

输入一个数n

输出格式

输出一个数

输入样例

text
896

输出样例

text
7
c++
#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, cnt = 0;
  cin >> n;
  while(n) {
    if (n % 2 == 0) {
      cnt++;
      n /= 2;
    } else {
      break;
    }
  }
  cout << cnt << endl;
  return 0;
}

题解 1

一个数能够被 2 整除,那么它就是偶数。

能被 4 ( 2 的平方) 整除,那么它除以二以后还是个偶数

………

依此类推,当一个数一直除以二直到他变成奇数,它除以二的次数就是所求的答案。

如果要计算一个数能被 3 的多少次幂整除,代码要怎么修改?

课后作业:角谷猜想

角谷猜想的内容是:“对任意的正整数n,若为偶数,则把它除以2;若为奇数,则把它乘以3加1 。经过如此有限次运算后,总可以得到正整数值1 。“ 请你编一个程序,根据输入的正整数n,输出每一步运算结果。

输入格式

输入一个正整数n。

输出格式

输出若干行,每行一个算式表示计算过程。

输入样例

text
3

输出样例

text
10 
5
16
8
4
2
1

数据范围

对于20%的数据,2≤n≤10; 对于100%的数据,2≤n≤100;

c++
#include <bits/stdc++.h>
using namespace std;
int main() {
  int n;
  cin >> n;
  while(n != 1) {
    if (n % 2 == 0) {
      n /= 2;
      cout << n << endl;
    } else {
      n = n * 3 + 1;
      cout << n << endl;
    }
  }
  return 0;
}

题解 1

由于不清楚循环的次数,所以想到用 while 循环来解决问题,按照题目的要求,如果是偶数则 n−>n/2 ,如果是奇数则 n=3n+1 ,直到 n 的值变为 1 为止。

进阶习题:空瓶换饮料

某饮料公司最近推出了一个“空瓶换饮料”的活动:如果你拥有3个空瓶就可以兑换一瓶饮料,初始你有 n 瓶饮料,喝完后的空瓶可以继续用来兑换饮料。问总共可以喝到多少瓶饮料。

输入格式

一行,1个整数n,表示初始饮料的数量(1 <= n <= 10^9)。

输出格式

一行,对应答案

输入样例

text
10

输出样例

text
14
c++
#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, cnt = 0;
  cin >> n;
  int a = n;
  while(n > 2) {
    cnt += n / 3;
    n = n / 3 + n % 3;
  }
  cout << a + cnt << endl;
  return 0;
}
  • 题解 1

用 while 循环模拟兑换过程,同时用个变量 sum 做喝过饮料的计数,用一个 t 做剩余瓶盖的计数。

初始 sum=n ,表示喝了最初的 n 瓶。

之后 t=n%3 ,即当前 n 个瓶盖经过兑换,剩余的瓶盖。

n=n/3 ,即当前 n 个瓶盖可以兑换多少瓶饮料。

再下一轮兑换时,先进行计数,即 sum=sum+n ,再把剩余的 t 个瓶盖,加到 n 当中,模拟兑换过程。

直到 n 等于 0 为止。

头脑风暴

过桥问题

在漆黑的夜里,四位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时通过。如果各自单独过桥的话,四人所需要的时间分别是 1,2,5,8 分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,你如何设计一个方案,让用的时间最少。

如果四个人的时间是 1,8,9,10 的话呢?

如果是 N 个人的话呢?

设这四个人叫做 A,B,C,D,他们所需要的时间分别是 1,2,5,8 分钟。

第一步: A 和 B 过桥,花费 2 分钟。

第二步: A 回来,花费 1 分钟。

第三步: C 和 D 过桥,花费 8 分钟。

第四步: B 回来,花费 2 分钟。

第五步: A 和 B 过桥,花费 2 分钟。

这样只要花费 2+1+8+2+2=15 分钟

下面再来考虑 A,B,C,D 四个人所需要的时间分别是 1,8,9,10 分钟。

第一步: A 和 B 过桥,花费 8 分钟。

第二步: A 回来,花费 1 分钟。

第三步: A 和 C 过桥,花费 9 分钟。

第四步: A 回来,花费 1 分钟。

第五步: A 和 D 过桥,花费 10 分钟。

总共花费: 29 分钟。如果仍按照上面的方法来做,需要花费: 8+1+10+8+8=35 分钟。