你好,C++(21)只要天还没黑,就一直在工地干活-4.3.1 while循环:只要…就一直…
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 = 0; // … // 循环条件:当前油量小于油箱容积 while(nL < 100) { nL += 1; // 循环动作:往油箱中加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 = 0; // 收支总数 int nTotal = 0; // 第一次循环,无条件执行循环动作 // 其后的循环,要在循环条件满足的情况下才能执行 do { // 接受用户输入的收支数目并保存到nInput cin>>nInput; // 对收支进行统计,将其加和到收支总数nTotal nTotal += nInput; } while( 0 != nInput ) // 对循环条件进行判断,以决定是否进行下一次循环 // 输出统计结果 cout << "你本月的结余是:" << nTotal << endl; return 0; }
在执行的时候,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语句的每一次循环动作都要在循环条件满足的前提下执行,所以它更适合于表达哪些每次循环都有前提条件的循环现象。比如,在给汽车加油时,每一次我们都需要判断油箱是否已满,无论是第一次还是最后一次。