⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 第11章 循环语句.htm

📁 用非常通俗的语言介绍了C++和C
💻 HTM
📖 第 1 页 / 共 4 页
字号:
      <P>} 
      <P>  
      <P>在上面例子,由于用户的两次输入我们都采用变量 c (char 类型)接收。但如果第一次输入 
      字母‘Y’时,循环需继续,但如果用户是在第二次输入‘Y',则表示是真的不统计了,循环却必须结束;所以,此时while无法仅凭c的值来做出正确判断,但,采用break,正如上面代码,我们在合适的位置安排一个break,从而直观地实现了。 

      <P>  
      <P>当然,这里仅为了讲学方便而举此例,如果你真的在程序中为了一个“是否继续统计”而问了用户两遍,可能会被用户骂做“神经质”。不过,如果是删除某些重要数据(直接删除,不可恢复的情况),多问一次就选得很重要了。(比如句神英语删除用户操作就会在最后多问一句“真的要说再见吗?我们会想你的……”) 

      <P>  
      <P>  
      <P>再举一例,看我们前面关于跑步的例子: 
      <P>  
      <P>while(已跑的圈数 &lt; 3 ) 
      <P>{ 
      <P>&nbsp; 跑一圈……; 
      <P>
      <P>&nbsp; if(我身体感觉不妙) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp; <B>break;</B>&nbsp; 
      <P>} 
      <P>  
      <P>这段代码有点问题,因为判断“我身体感觉不妙”是在跑完一圈之后……很可能我在某一圈刚开始跑时就觉得肚子剧痛,极可能是得阑尾炎啊!按照这段程序,我只有坚持跑完一圈后,才能break了…… 

      <P>要完美解决这个问题,我们将在本章再后讲到,现在先采用一个“通融”的办法,我们允许你每跑100米就检查一次吧: 
      <P>  
      <P>while(已跑完图数 &lt; 3) 
      <P>{ 
      <P>&nbsp; 跑第1个100米; 
      <P>
      <P>&nbsp; if(我身体感觉不妙) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp; <B>break;</B>&nbsp; 
      <P>  
      <P>&nbsp; 跑第2个100米; 
      <P>
      <P>&nbsp; if(我身体感觉不妙) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp; <B>break;</B>&nbsp; 
      <P>  
      <P>&nbsp; 跑第3个100米; 
      <P>
      <P>&nbsp; if(我身体感觉不妙) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp; <B>break;</B>&nbsp; 
      <P>  
      <P>&nbsp; 跑第4个100米; 
      <P>
      <P>&nbsp; if(我身体感觉不妙) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp; <B>break;</B>&nbsp; 
      <P>} 
      <P>代码中,我们将1圈拆为4个100米,每跑完1/4,我们就检查一次是否身体不对。看明白这个例子,我想你对break的用途和用法,可以算是理解了。 

      <P>  
      <H4><A name=11.1.2>11.1.2</A> break 的一个“高级用法”</H4>
      <P>  
      <P>本小节不是很适于没有多少实际编程经历的初学者,所以初学者可以跳过,以后再回头阅读。当然,所谓的“高级用法”的确是应该加对引号的,所谈的内容只是一个高手们常用小小技巧。 

      <P>
      <P>使用do...break...while简化多级条件判断的结构。 
      <P>  
      <P>如果你写过不少代码,那么一定会不时遇到类似下的情况: 
      <P>假设要找到文件A,复制该文件为B;然后打开B文件,然后往B文件内写入一些内容;最后在写入成功后,我们需要再进行一些相关操作。 
      <P>在此过程,遇到以下情况时将放弃后续的操作,认为是操作失败: 
      <P>1、如果A文件不存在; 
      <P>2、如果B文件已经存在,并且询问用户是否覆盖时,用户回答“不”; 
      <P>3、无法复制出B文件; 
      <P>4、无法打开B文件; 
      <P>5、无法写入B文件; 
      <P>6、无法正常关闭B文件。 
      <P>  
      <P>用伪代码写该段程序为: 
      <P>  
      <P>if( A文件存在 ) 
      <P>{ 
      <P>&nbsp;&nbsp;&nbsp; 执行A文件的相关操作; 
      <P>&nbsp;&nbsp;&nbsp; if( B文件不存在 || 用户允许覆盖原有B文件) 
      <P>&nbsp;&nbsp;&nbsp; { 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 复制A文件为B文件; 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(复制文件成功) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  打开B文件; 
      <P>       if(打开文件成功) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      { 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      写入文件; 
      <P>         if(写入成功) 
      <P>         { 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      关闭B文件; 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      if(关闭成成功) 
      <P>           { 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      执行其它必须在一切成功后进行的操作。 
      <P>             ……&nbsp;&nbsp; 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      } 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
       &nbsp; } 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
       }&nbsp;&nbsp;&nbsp;&nbsp; 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } 
      <P>&nbsp;&nbsp;&nbsp; } 
      <P>} 
      <P>  
      <P>可能有些操作和判断可以同时处理,但这个程序的繁琐仍然不可避免,而现实中程序的复杂性往往要远过于此例。从语法上看,这个例子没有任何错误,但它的一层套一层的条件判断却让人难以书写,阅读,调试,在复杂的情况就容易造成人为的错误(比如最马虎的,花括号匹配不对等……)。 

      <P>  
      <P>同样一段代码“程序老鸟”是这样写的: 
      <P>  
      <P>do</P>
      <P>{</P>
      <P>&nbsp;&nbsp; if(A文件不存在)</P>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</P>
      <P>&nbsp;&nbsp; 执行A文件的相关操作; 
      <P>&nbsp;&nbsp;</P>
      <P>&nbsp;&nbsp; if(B文件存在 &amp;&amp; 用户不允许覆盖)</P>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</P>
      <P>&nbsp;&nbsp;&nbsp;</P>
      <P>&nbsp;&nbsp; 复制A文件为B文件;</P>
      <P>&nbsp;&nbsp; if(复制不成功)</P>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</P>
      <P> </P>
      <P>&nbsp;&nbsp; 打开B文件;</P>
      <P>&nbsp;&nbsp; if(打开B文件不成功)</P>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</P>
      <P> </P>
      <P>&nbsp;&nbsp; 写入文件;</P>
      <P>&nbsp;&nbsp; if(写入文件不成功)</P>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</P>
      <P> </P>
      <P>&nbsp;&nbsp; 关闭B文件;</P>
      <P>&nbsp;&nbsp; if(关闭不成功)</P>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</P>
      <P>  
      <P>&nbsp;&nbsp;&nbsp; 执行其它必须在一切成功后进行的操作。 
      <P>  ……&nbsp;&nbsp; 
      <P>}</P>
      <P>while(false);</P>
      <P>  
      <P>看,代码是不是“直”了很多?这里用了do..while,可是根本不是为了循环,而是为了使用它的break功能。每当有操作不成功,就直接用break跳出循环。所以循环条件总是一个“永假” 
      false。 
      <P>在一个程序中,这种结构相当的多,为了更加一步淡化while的原来的循环用途,我们非常值得在代码加入两个共用的宏: 
      <P>#define&nbsp; BEG_DOWHILE do { 
      <P>#define&nbsp; END_DOWHILE } while(false); 
      <P>  
      <P>这里举的是do...while结构,在某些情况下,可以使用while...来实现类似功能。 
      <P>  
      <H4><A name=11.1.3>11.1.3</A> break 在for循环中的一点注意</H4>
      <P>  
      <P>前面举的例子都是do...while或while,break在for循环也一个样。请看下面例题: 
      <P>  
      <P><B>例一:</B>从1开始累加,每次递增1,请问累加到哪个数,累加和超过2000?请输出该数,及当时的累加和。 
      <P>  
      <P><B>分析:</B>和求1~100的累加和类似,只是在发现累加和已经超过2000时,就输出当前累加的数,然后结束循环。 
      <P>  
      <P>for(int i=1,sum=0;;i++) 
      <P>{ 
      <P>&nbsp;&nbsp; sum += i; 
      <P>&nbsp;&nbsp; if(sum &gt; 2000) 
      <P>&nbsp;&nbsp; { 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; i &lt;&lt; "," 
      &lt;&lt; sum &lt;&lt; endl;&nbsp; 
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; 
      <P>&nbsp;&nbsp; } 
      <P>} 
      <P>  
      <P>输出结果为: 
      <P>  
      <P><FONT color=#ffffff><SPAN 
      style="BACKGROUND-COLOR: #000000">63,2016</SPAN></FONT> 
      <P>  
      <P>关于这段例子,需要注意三点:1、循环条件初始的位置,我们同时声明两个变量;2、没有循环条件。为了解这两点注意,请看下面放大图: 
      <P><IMG height=244 src="第11章 循环语句.files/ls11.h2.gif" width=662 border=0> 
      <P>  
      <P>最后一点注意是关于break和“条件因子变化”的注意。我们知道,for每执行一遍循环体后,都将执行一次“条件因子变化”语句(见上图③)。现在需要注意的是: 

      <P><B>在for循环中,执行break后,“条件因子变化”语句同样被跳过,没有被执行循环就被中断。</B> 
      <P>(完整代码请见lz1.bpr) 
      <P>  
      <P>至此,break 在 
      while,do...while,for中的用法我们都已见过。不过,你还记得吗,我们最早学到break是在哪里?在讲条件分支语句中switch里。如果你有点忘了那里的break是起什么作用,现在就去看看吧。 

      <P>  
      <H4><A name=11.1.4>11.1.4</A> 多层循环中的break</H4>
      <P>  
      <P>break 只能跳出当前层的循环,所以,如果有多层循环,则在内层的break跳出循环后,外层的循环还将继续。 
      <P>  
      <P>前面说跑步的例子,一圈400米,我们每跑100检查一下是否肚子疼什么的,如果疼得利害就break,不跑了。这和现实不符,我们应该每跑一步就检查一次是否肚子疼最合理。 

      <P>一圈得分成几步呢?显然不能再像上面分成四次检查那样写代码了。我们加一层循环,也就是把跑一圈的工作用一个循环来实现: 
      <P>  
      <P>while(一圈未结束) 
      <P>{ 
      <P>&nbsp; 跑一步; 
      <P>} 
      <P>  
      <P>然后,我们在每跑完一步时加入一个判断: 
      <P>  
      <P>while(一圈未完) 
      <P>{ 
      <P>&nbsp; 跑一步; 
      <P>&nbsp;&nbsp; 
      <P>&nbsp; if(我身体感觉不妙) 
      <P>&nbsp;&nbsp;&nbsp;&nbsp; <B>break;</B>&nbsp; 
      <P>} 
      <P>  
      <P>把这跑一圈的代码加入外层循环: 
      <P>  
      <P>while(已跑完图数 &lt; 3) 
      <P>{ 
      <P>&nbsp;&nbsp;&nbsp; while(一圈未完) 
      <P>&nbsp;&nbsp;&nbsp; { 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -