4.3  循环控制语句

在现实世界中,有这样一类现象:

只要油箱中的当前油量小于油箱容量100升,就一直往油箱中加油;

一直不断地为祖国辛勤工作,只要我还活着;

公司100000位员工,每个人的工资都增加10000元;

这些现象虽然各不相同,但它们都有一个共同的特点,那就是在某个条件(只要我还活着)下,或者某个范围(所有100000位员工)内,这些动作(辛勤工作、增加10000元工资)都是循环往复重复多次地出现。为了表达这类循环现象,C++提供了循环控制结构。又因为这些循环现象各有特点,为了准确而简便地表达它们,C++有针对性地分别提供了while、do…while…以及for语句。

4.3.1  while循环:只要…就一直…

对于上面的第一个循环现象,我们可以用“只要…就一直…”这样的句式来描述。在现实世界中,这种循环现象非常普遍:

只要天还没黑,就一直在工地干活;

只要硬盘还有剩余空间,就一直往硬盘上面存储文件。

在自然语言中,我们用“只要…就一直…”这样的句式来表达这种在某个条件下某个动作循环发生的循环现象,与之对应地,在C++中,我们用while循环结构来表达这种循环现象。其语法格式如下:

while( 条件表达式 )
{
循环体语句;
}

在条件表达式中,我们对某个条件进行判断,得到表示条件成立与否的true或者false值,以此来表达这个循环是在“某个条件”下进行的。而while结构中的循环体语句,则表示会被循环执行的动作。例如,我们将“只要油箱中的当前油量小于油箱容量100升,就一直往油箱中加油”这个循环现象用while结构表达出来就是:

// 当前油量
int nL = ;
// …
// 循环条件:当前油量小于油箱容积
while(nL < )
{
nL += ; // 循环动作:往油箱中加1升油
}

在执行的时候,while语句首先会计算条件表达式(nL < 100)的值,也就是判断循环条件(当前油量小于油箱容量100升)是否满足。如果其值为true,表示循环条件满足,则进入循环执行循环体语句,完成循环动作(往油箱中加1升油);反之,则表示循环条件不再满足,从而直接结束整个while语句的执行。当循环体语句执行完一次后,会再次计算条件表达式的值,判断循环条件是否仍然满足。如果满足,则继续进入循环执行循环体语句,开始第二次循环。如此不断循环往复,直到条件表达式的值为false,循环条件不再满足,整个循环才结束。可以把while理解成自然语言中的“只要”,只要循环条件满足,就不断执行循环体语句。当循环条件不再满足时,就结束while循环语句。while循环语句的执行流程如图4-3所示。

知道更多:单步调试执行程序,查看代码执行过程

while循环语句的执行过程,要比之前介绍的if条件语句复杂的多,再加上后面我们将要学到的break和continue对执行过程的控制,这样while循环语句的执行过程就更复杂了。稍不留意,就可能导致代码的实际执行过程与我们的设计不符,从而使程序执行得到错误结果。在这种情况下,我们可以利用Visual Studio所提供的单步调试运行功能,查看while循环语句真实的执行过程,从而找到与设计预期不符的地方,进而改正错误,使程序按照正确的过程执行得到正确的执行结果。

所谓的单步调试执行,就是在调试状态下,按照程序的执行流程逐条地依次执行每一条语句,而在这个过程中,我们可以清楚地看到程序的执行过程——哪一条语句先执行,哪一条语句后执行,哪一条语句被跳过而没有得到执行——以此判断代码的执行过程是否与设计预期相符。同时在这个过程中,我们还可以利用Visual Studio提供的“观察”、“变量”等工具窗口,查看各个变量的当前数值,以此判断执行结果是否与设计预期相符。如果执行过程或者执行结果与设计预期不符,那么这就意味着当前执行的代码可能是程序中出现问题的地方。当程序执行出现问题,也就是所谓出现bug的时候,我们通常用这种方式来寻找出现问题的代码位置进而对其进行修正,而这个过程也被称为debug。

要想使用单步调试执行来查看某段代码的执行过程,我们可以先将输入焦点定位在这段代码的开始位置,然后按下F9快捷键在当前代码行设置一个断点。所谓断点,就是在程序调试执行的过程中会暂停的代码位置。设置断点后,按下F5快捷键调试执行程序,当程序执行到之前设置的断点位置就会暂停下来,这时我们可以利用F10快捷键,按键一次就向下执行一条语句,从而可以看到整个代码的执行过程。利用这种方式,我们就可以查看while语句的执行过程,从而对while语句的执行过程有一个更深刻更直观的认识。

4.3.2  do…while循环:一直…只要…

前面介绍的while语句表达的“只要…就一直…”循环现象,是“先判断循环条件后执行循环动作”。然而在现实世界中,还有另外一类循环现象。例如:

一直不断地为祖国辛勤工作,只要我还活着;

一直接受用户输入数据,只要用户输入不为0 。

这类循环现象刚好与while语句表达的循环现象相反,总是先执行循环动作(工作、输入数据)后判断循环条件(还活着,输入不为0)。在自然语言中,我们可以用“一直…只要…”这样的句式来表达这种现象,刚好是”只要…就一直…”的倒置。与之对应地,在C++中,我们也将while语句倒置形成do…while…语句来表达这种循环现象。其语法格式如下:

do
{
循环体语句;
}
while ( 条件表达式 );

在执行的时候,do…while循环语句首先会执行一次循环体语句,然后再利用条件表达式对循环条件进行判断。如果条件表达式的值为true,则意味着循环条件仍然满足,可以再次执行循环体语句,开始下一次循环;反之,则意味着循环条件不再满足,直接结束整个循环。do…while循环语句的执行流程如图4-4所示。

下面来看一个实际的例子。在生活中,精打细算的妈妈们总是喜欢统计每月的收支情况。用自然语言来描述这一统计过程就是:一直不断地输入收支数目并将其累加到收支总数,只要还有剩下的收支数目。在这里,“还有剩下的收支数目”是do…while…的循环条件,我们用输入的收支数目为0表示没有剩余数目,换而言之,循环条件成了“只要收支数目不为0”。而“输入收支数目并将其累加到收支总数”就是这个do…while…循环要反复执行的动作了。这是一个典型的“一直…只要…”循环现象,用do…while…循环结构将其表达出来就是:

// 每月收支统计程序
#include <iostream>
using namespace std; int main()
{
// 输出用户提示
cout << "======每月收支统计程序======" << endl;
cout << "请输入你本月的收入(正数)和支出(负数),0表示输入结束。" << endl; // 收支数目,这里的初始值不是必须的
int nInput = ;
// 收支总数
int nTotal = ;
// 第一次循环,无条件执行循环动作
// 其后的循环,要在循环条件满足的情况下才能执行
do
{
// 接受用户输入的收支数目并保存到nInput
cin>>nInput;
// 对收支进行统计,将其加和到收支总数nTotal
nTotal += nInput;
} while( != nInput ) // 对循环条件进行判断,以决定是否进行下一次循环 // 输出统计结果
cout << "你本月的结余是:" << nTotal << endl; return ;
}

在执行的时候,do…while…语句第一次会无条件地执行一次循环体语句,然后才执行条件判断“while( 0 != nInput )” ,判断收支数目nInput是否为0,也就是判断循环条件是否依然满足,以决定是否进入下一次循环。这时的nInput中已经是用户第一次输入的收支数目了,如果为0,则表示后面没有收支数据了,“0 != nInput”的值为false,循环条件不再满足而直接结束整个do…while…循环语句。反之,则继续进行下一次循环,接受用户输入并将其累加到收支总数,然后再次判断循环条件是否依然满足以决定是否进行下一次循环。这个过程会不断循环往复地进行下去,直到用户输入nInput为0,循环条件不再满足为止。整个过程只需要输入各个收支数目,程序会循环接收这些数据并进行累加统计得到结果,这可比按计算器省事多了。赶紧把这个统计程序拿去献给老妈吧,肯定会得到一番奖赏的。

while和do…while都是用来表达循环现象的结构,且很多时候,两者之间可以相互转换。两者的差别在于,while语句是先判断循环条件后执行循环动作,而do…while…语句却刚好是反过来,先执行循环动作后判断循环条件。这也就意味着,do…while…语句的第一次循环可以无条件地执行,所以它更加适合于表达哪些第一次循环没有初始条件限制的循环现象。比如在收支统计程序中第一次输入收支数目时,任何时候任何情况都可以,没有什么初始条件限制。而while语句的每一次循环动作都要在循环条件满足的前提下执行,所以它更适合于表达哪些每次循环都有前提条件的循环现象。比如,在给汽车加油时,每一次我们都需要判断油箱是否已满,无论是第一次还是最后一次。

你好,C++(21)只要天还没黑,就一直在工地干活-4.3.1 while循环:只要…就一直…的更多相关文章

  1. php大力力 [013节]mySQL数据库乱码问题我还没解决

    <?php echo"测试<br>"; $sql_connection = mysql_connect("localhost","e ...

  2. 在各方面还没准备好的时候,大家一定要慎用border-box样式!!!!

    这几天,我被一个js问题困扰到癫狂了! 事情是这样的,我之前写了个功能非常复杂的纯jquery代码的前端gridview控件,实现了大量的功能和效果,在一些项目里也用得很好. 最近有个项目,样式做了调 ...

  3. 成功熬了四年还没死?一个IT屌丝创业者的深刻反思

    三个IT屌丝创业的故事 从前有三个屌丝,聚在一起做网络.提供免费的网络服务,砸锅卖铁,通宵达旦,除了卖肾,啥都做了.3年后终于做到了五百万用户.对于年轻人来说,能把五百万人玩弄于鼓掌之间,已经是很牛逼 ...

  4. 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署

    谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...

  5. noi2018还没想好记

    前面说点什么.. 没想到吧 嘴上说着不写的彩笔博主最后还是写了这篇东西.. Day -inf 在雅礼集训,打了四场模拟赛.. 真正说打得好的.. 也就那么一场 身体很差 心态很差 状态很差 虽然有书读 ...

  6. C-Lodop提示“网页还没下载完毕,请稍等一下再操作.”

    该提示在Lodop旧版本中是: 提示"WebSocket没准备好,点确定继续",提示“C-Lodop没准备好”,新版本修改了该提示的描述“网页还没下载完毕,请稍等一下再操作.”,让 ...

  7. web工程启动时,在一个类中延迟加载Bean,因为该Bean类可能还没被JVM加载

     问题描述: (1)javaWeb项目启动中,还没启动完成,在下面这个类加载另一个Bean类, (2)通过getBean方法获取到该Bean,可以获取到,不为null (3)但是,调用该Bean的方法 ...

  8. 趁webpack5还没出,先升级成webpack4吧

    上一次将webpack1升级到3,也仅是 半年前,前端工具发展变化太快了,如今webpack4已经灰常稳定,传说性能提升非常高,值得升级. 一直用着的webpack3越来越慢,一分多钟的编译时间简直不 ...

  9. [转帖]速度快散热好 为什么U.2 SSD还没普及?

    速度快散热好 为什么U.2 SSD还没普及?   经典的影视剧中总有那么几位武林高手,江湖上只闻其名,不见其形.今天我们要聊的这位爷,誓要拳打南山M.2,脚踩北海SATA 3!它就是固态硬盘界久负盛名 ...

随机推荐

  1. Java文件末尾追加字符串

    Java进行文件输出时,有时候想直接向已有文件末尾追加字符,而不是从头开始写,可以采用以下三种方式实现: package test; import java.io.File; import java. ...

  2. Qt 中如何捕获窗口停用和激活的消息

    最近一直在用Qt做一个简单的俄罗斯方块的游戏,由于要实现一个暂停游戏的功能,就是当鼠标移出正在运行的游戏,点击电脑桌面上的其他位置时,这个时候游戏暂停.在这里把实现过程简单的记录一下,作为一个学习笔记 ...

  3. COJ 0343 WZJ的公司(二)

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=313 试题描述: WZJ的公司放假了!为了保证假期期间公司的安全,WZJ决定 ...

  4. HDOJ 1287 破译密码(异或运算)

    Problem Description 有个叫"猪头帮"的国家,采用一种简单的文法加密,他们所用的语言里面只有大写字母,没有其他任何字符:现在还知道他们加密的方法是:只用一个大写字 ...

  5. bzoj2730 [HNOI2012]矿场搭建 (UVAlive5135 Mining Your Own Business)

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1147  Solved: 528[Submit][Statu ...

  6. 利用C++11的function和bind简化类创建线程

    问题引出 当在类中需要创建线程时,总是因为线程函数需要定义成静态成员函数,但是又需要访问非静态数据成员这种需求,来做若干重复性的繁琐工作.比如我以前就经常定义一个静态成员函数,然后定一个结构体,结构体 ...

  7. css实现小三角效果

    <!DOCTYPE html><html><head><meta charset="UTF-8"> <title>新闻标 ...

  8. MySQL定时事件

    1.创建一个测试表 CREATE TABLE aaa (timeline TIMESTAMP); 2.创建一个事件:每秒插入一条记录到数据表 CREATE EVENT e_test_insert SE ...

  9. qt之treeview例子

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.Qt import * from PyQt4. ...

  10. 【safari挖的那些坑】iOS safari 浏览器 时间乱码(ios时间显示NaN) 问题解决

    通常 iOS下时间错误表现形式 问题一: 这个界面运用了大量的日期类型的计算,当我们用JavaScript实例化一个日期对象时,我们可以这样用: var date =new Date(); 上面这段代 ...