C++入门很轻松(微课超值版)
上QQ阅读APP看书,第一时间看更新

5.3 循环结构

微视频

在实际应用中,往往会遇到一行或几行代码需要执行多次的情况,这就是代码的循环。几乎所有的程序都包含循环,循环是重复执行的指令,重复次数由条件决定,这个条件称为循环条件,反复执行的程序段称为循环体。一个正常的循环程序具有4个基本要素,分别是循环变量初始化、循环条件、循环体和改变循环变量的值。典型的循环结构流程图如图5-16所示。

图5-16 循环结构流程图

5.3.1 循环结构类型

在C++语言中,为用户提供了4种循环结构类型,分别为while循环、do…while循环、for循环、嵌套循环,具体介绍如表5-2所示。

表5-2 循环结构类型

1.while循环

while循环根据循环条件的返回值来判断执行零次或多次循环体。当逻辑条件成立时,重复执行循环体,直到条件不成立时终止。while循环的语法格式如下:

    while(表达式)
    {
         语句块;
    }

在这里,语句块可以是一个单独的语句,也可以是几个语句组成的代码块。表达式可以是任意的表达式,表达式的值非零时条件取值为true,执行循环;否则,退出循环,程序流将继续执行紧接着循环的下一条语句。

while循环语句的执行流程图如图5-17所示。当遇到while循环时,首先计算表达式的返回值,当表达式的返回值为true时,执行一次循环体中的语句块;循环体中的语句块执行完后,将重新查看是否符合条件,若表达式的值还返回true将再次执行相同的代码,否则跳出循环。while循环的特点:先判断条件,后执行语句。

图5-17 while循环语句的执行流程图

【实例5.8】编写程序,实现100以内自然数的求和,即1+2+3+…+100,最后输出计算结果(源代码\ch05\5.8.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
          /* 定义变量并初始化 */
          int i=1,sum=0;
          cout <<"100以内自然数求和:"<<endl;
          /* while 循环语句 */
          while(i<=100)
          {
                 sum+=i;
                 i                             /* 自增运算 */
          }
          cout <<"1+2+3+…+100="<<sum<<endl;
    }

程序运行结果如图5-18所示。

图5-18 例5.8的程序运行结果

使用while循环语句时要注意以下几点。

(1)while语句中的表达式一般是关系表达式或逻辑表达式,只要表达式的值为真(非0)即可继续循环。

(2)循环体包含一条以上语句时,应用“{}”括起来,以复合语句的形式出现;否则,它只认为while后面的第1条语句是循环体。

(3)循环前,必须给循环控制变量赋初值,如上例中的“i=1;”。

(4)循环体中,必须有改变循环控制变量值的语句(使循环趋向结束的语句),如上例中的“i++;”,否则循环永远不结束,形成所谓的“死循环”。例如以下代码:

    int i=1;
    while(i<10)
       printf("while语句注意事项");

因为i的值始终是1,也就是说,永远满足循环条件i<10,所以,程序将不断地输出“while语句注意事项”。要使循环不陷入死循环,必须要给出循环终止条件。

while循环之所以被称为有条件循环,是因为语句部分的执行要依赖于判断表达式中的条件。之所以说其是入口条件,是因为在进入循环体前必须满足这个条件。如果在第一次进入循环体时条件就没有被满足,程序将永远不会进入循环体。例如以下代码:

    int i=11;
    while(i<10)
       printf("while语句注意事项");

因为i一开始就被赋值为11,不符合循环条件i<10,所以不会执行后面的输出语句。要使程序能够进入循环,必须给i赋比10小的初值。

【实例5.9】编写程序,求数列1/2、2/3、3/4……前20项的和,最后输出计算结果(源代码\ ch05\5.9.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {     int i;                          /*定义整型变量i用于存放整型数据*/
          double sum=0;                   /*定义浮点型变量sum用于存放累加和*/
          i=1;                            /*循环变量赋初值*/
          while(i<=20)                    /*循环的终止条件是i<=20*/
          {
               sum=sum+i/(i+1.0);         /*每次把新值加到sum中*/
               i++;                       /*循环变量增值,此语句一定要有*/
          }
          cout <<"该数列前20项的和为:"<<sum<<endl;
    }

程序运行结果如图5-19所示。本实例的数列可以写成通项式:n/(n+1),n=1,2,…,20,n从1循环到20,计算每次得到当前项的值,然后加到sum中即可求出结果。

图5-19 例5.9的程序运行结果

☆大牛提醒☆

while后面不能直接加“;”。如果直接在while语句后面加了分号“;”,系统会认为循环体是空体,什么也不做。后面用“{}”括起来的部分将认为是while语句后面的下一条语句。

2.do…while循环

在C++语言中,do…while循环是在循环的尾部检查它的条件。do…while循环与while循环类似,但是也有区别。do…while循环和while循环的最主要区别如下。

(1)do…while循环是先执行循环体后判断循环条件,while循环是先判断循环条件后执行循环体。

(2)do…while循环的最小执行次数为1次,while循环的最小执行次数为0次。

do…while循环的语法格式如下:

    do
    {
             语句块;
    }
    while(表达式);

这里的条件表达式出现在循环的尾部,所以循环中的语句块会在条件被测试前至少执行一次。如果条件为真,控制流会跳转回上面的do,然后重新执行循环中的语句块,直到给定条件变为假为止。do…while循环语句的执行流程图如图5-20所示。

图5-20 do…while循环语句的执行流程图

程序遇到关键字do会执行大括号内的语句块,语句块执行完毕,执行while关键字后的布尔表达式,如果表达式的返回值为true,则向上执行语句块,否则结束循环,开始执行while关键字后的程序代码。

使用do…while循环语句应注意以下几点。

do…while循环语句是先执行循环体语句,后判断循环终止条件,与while循环语句不同。两者的区别在于:当while后面表达式开始的值为0(假)时,while语句的循环体一次也不执行,而do…while语句的循环体至少要执行一次。

(1)在书写格式上,循环体部分要用“{}”括起来,即使只有一条语句也如此;do…while循环语句最后以分号结束。

(2)通常情况下,do…while循环语句是从后面控制表达式退出循环。但它也可以构成无限循环,此时要利用break语句或return语句直接从循环体内跳出循环。

【实例5.10】编写程序,实现100以内自然数的求和,即1+2+3+…+100,最后输出计算结果(源代码\ch05\5.10.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
          /* 定义变量 */
          int i=1,sum=0;
          cout<<"100以内自然数求和:"<<endl;
          /* do…while循环语句 */
          do
          {
               sum+=i;
               i++;
          }
          while(i<=100);
          cout<<"1+2+3+…+100="<<sum<<endl;
    }

程序运行结果如图5-21所示。

图5-21 例5.10的程序运行结果

【实例5.11】编写程序,根据输入的两个数,计算两个数的最大公约数(源代码\ch05\5.11.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
          int m,n,r,t;
          int m1,n1;
          cout<<"请输入第1个数:"<<endl;
          cin>>m;                      /*由用户输入第1个数*/
          cout<<"请输入第2个数:" <<endl;
          cin>>n;                      /*由用户输入第2个数*/
          m1=m;n1=n;                   /*保存原始数据供输出使用*/
          if(m<n)
          {t=m;m=n;n=t;}               /*m和n交换值,m存放大值,n存放小值*/
          do                           /*使用辗转相除法求得最大公约数*/
          {
               r=m%n;
               m=n;
               n=r;
          }while(r!=0);
          cout<<m1<<"和"<<n1<<"的最大公约数是"<<m<<endl;
    }

保存并运行程序,从键盘上输入任意两个数,按Enter键,即可计算它们的最大公约数。程序运行结果如图5-22所示。

图5-22 例5.11的程序运行结果

在本实例中,求两个数最大公约数的具体方法如下。

(1)比较两数,并使m大于n。

(2)将m作为被除数,n作为除数,两数相除后,余数为r。

(3)将m←n,n←r。

(4)若r=0,则m为最大公约数,结束循环。若r≠0,执行步骤(2)和步骤(3)。

由于在求解过程中m和n已经发生了变化,因此要将它们保存在另外两个变量m1和n1中,以便输出时可以显示这两个原始数据。

如果要求两个数的最小公倍数,只需要将两个数相乘再除以最大公约数,即m1×n1/m即可。

3.for循环

for循环和while循环、do…while循环一样,可以循环重复执行一个语句块,直到指定的循环条件返回值为假。for循环的语法格式如下:

    for(表达式1;表达式2;表达式3)
    {
       语句块;
    }

其主要参数说明如下。

(1)表达式1为赋值语句,如果有多个赋值语句可以用逗号隔开,形成逗号表达式。此为循环四要素中的循环变量初始化。

(2)表达式2返回一个布尔值,用于检测循环条件是否成立。此为循环四要素中的循环条件。

(3)表达式3为赋值表达式,用来更新循环控制变量,以保证循环能正常终止,循环四要素中的改变循环变量的值。

for循环的执行过程如下。

(1)计算表达式1,为循环变量赋初值。

(2)计算表达式2,检查循环控制条件,若表达式2的值为true,则执行一次循环体语句;若为false,终止循环。

(3)执行完一次循环体语句后,计算表达式3,对循环变量进行增量或减量操作,再重复第2步操作,进行判断是否要继续循环。

使用for循环语句应注意以下几点。

(1)表达式1先被执行,且只会执行一次。这一步允许用户声明并初始化任何循环控制变量。用户也可以不在这里写任何语句,只要有一个分号出现即可。

(2)判断表达式2。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着for循环的下一条语句。

(3)在执行完for循环主体后,控制流会跳回表达式3语句。该语句允许用户更新循环控制变量,可以留空,只要在条件后有一个分号出现即可。

(4)最后条件再次被判断。如果为真,则执行循环,这个过程(循环主体,然后增加步值,再重新判断条件)会不断重复。在条件变为假时,for循环终止。

for循环语句的执行流程图如图5-23所示。

图5-23 for循环的语句的执行流程图

☆大牛提醒☆

C++语言不允许省略for语句中的3个表达式,否则会出现死循环现象。

【实例5.12】编写程序,实现100以内自然数的求和,并输出结果(源代码\ch05\5.12.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
         /* 定义变量 */
         int i,sum=0;
         cout<<"100以内自然数求和:"<<endl;
         /* for循环语句 */
         for(i=1;i<=100;i++)
         {
                   sum+=i;
         }
         cout<<"1+2+3+…+100="<<sum<<endl;
    }

程序运行结果如图5-24所示。

图5-24 例5.12的程序运行结果

☆大牛提醒☆

通过上述实例可以发现,while循环、do…while循环和for循环有很多相似之处,这三种循环都可以互换。

如果条件永远不为假,则循环将变成无限循环。for循环在传统意义上可用于实现无限循环。若构成for循环的三个表达式中任何一个都不是必需的,用户可以将某些条件表达式留空来构成一个无限循环。例如,下面一段代码。

    #include <iostream>
    using namespace std;
    int main()
    {
         for( ; ; )
         {
              cout<<"该循环会永远执行下去!";
         }
    }

当条件表达式不存在时,它被假设为真。用户也可以设置一个初始值和增量表达式,但是一般情况下,C++程序员偏向于使用for( ; ; )结构来表示一个无限循环。

☆大牛提醒☆

按Ctrl+C键可以终止一个无限循环。

4.嵌套循环

在一个循环体内又包含另一个循环结构,称为嵌套循环。如果内嵌的循环中还包含循环语句,这种称为多层循环。while循环、do…while循环和for循环语句之间可以相互嵌套。

1)嵌套for循环

在C++语言中,嵌套for循环的语法格式如下:

    for (表达式1;表达式2;表达式3)
    {
         语句块;
         for (表达式1;表达式2;表达式3)
         {
              语句块;
              …
         }
         …
    }

嵌套for循环语句的执行流程图如图5-25所示。

图5-25 嵌套for循环语句的执行流程图

【实例5.13】编写程序,在屏幕上输出九九乘法表(源代码\ch05\5.13.txt)。

    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
       int i, j;
       /* 外层循环,每循环1次,输出一行 */
       for(i = 1; i <= 9; i++)
       {
            /* 内层循环,循环次数取决于i*/
            for(j = 1; j <= i;j++)
            {
                  cout << setw(2) << j << "*" << i << "=" <<setw(2) << i * j ;
            }
            cout << endl;
       }
    }

程序运行结果如图5-26所示。

图5-26 例5.13的程序运行结果

2)嵌套while循环

在C++语言中,嵌套while循环的语法格式如下:

    while(条件1)
    {
         语句块;
         while;(条件2)
         {
              语句块;
              …
         }
         …
    }

嵌套while循环语句的执行流程图如图5-27所示。

图5-27 嵌套while循环语句的执行流程图

【实例5.14】编写程序,在屏幕上输出由*组成的形状(源代码\ch05\5.14.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
         int i = 1, j;
         while (i <= 5)
         {
              j = 1;
              while (j <= i)
              {
                    cout <<"*" ;
                    j++;
              }
              cout << endl;
              i++;
         }
    }

程序运行结果如图5-28所示。

图5-28 例5.14的程序运行结果

3)嵌套do…while循环

在C++语言中,嵌套do…while循环的语法格式如下:

    do
    {
         语句块;
         do
         {
              语句块;
              …
         }while (条件2);
         …
    }while (条件1);

嵌套do…while循环语句的执行流程图如图5-29所示。

图5-29 嵌套do…while循环语句的执行流程图

【实例5.15】编写程序,在屏幕上输出由*组成的形状(源代码\ch05\5.15.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
          int i=1,j;
          do
          {
                j=1;
                do
                {
                      cout<<"*";
                      j++;
                }while(j <= i);
                i++;
                cout <<endl;
       }while(i <= 5);
    }

程序运行结果如图5-30所示。

图5-30 例5.15的程序运行结果

5.3.2 循环控制语句

循环控制语句可以改变代码的执行顺序,编程时利用这些语句可以实现代码的跳转。C++语言提供的循环控制语句有break语句、continue语句和goto语句等,如表5-3所示。

表5-3 C++语言中的循环控制语句

1.break语句

break语句只能应用在switch语句和循环语句中,如果出现在其他位置会引起编译错误。C++语言中break语句有以下两种用法。

(1)当break语句出现在一个循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句。

(2)break语句可用于终止switch语句中的一个case。

☆大牛提醒☆

如果用户使用的是嵌套循环(即一个循环内嵌套另一个循环),break语句会停止执行最内层的循环,然后开始执行该语句块后的下一行代码。

C++语言中break语句的语法结构如下:

    break;

break语句在程序中的应用流程图如图5-31所示。

图5-31 break语句应用流程图

break语句用在循环语句循环体内的作用是终止当前的循环语句。例如:

(1)无break语句

    int sum=0, number;
    cin>>number;
    while (number !=0){
            sum+=number;
            cin>>number;
    }

(2)有break语句

    int sum=0, number;
    while (1) {
          cin>>number;
          if(number==0)
               break;
          sum+=number;
    }

以上这两段程序产生的效果是一样的。需要注意的是,break语句只是跳出当前的循环语句。对于嵌套的循环语句,break语句的功能是从内层循环跳到外层循环。例如:

    int i=0, j, sum=0;
    while(i<10) {
          for( j=0; j<10; j++) {
               sum+=i+j;
               if(j==i) break;
          }
          i++;
    }

本例中的break语句执行后,程序立即终止for循环语句,并转向for循环语句的下一个语句(即while循环体中的i++语句),继续执行while循环语句。

【实例5.16】编写程序,使用while循环输出10~20的整数变量a。注意在内循环中,当输出到15时,使用break语句跳出循环(源代码\ch05\5.16.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
          /*局部变量定义*/
          int a =10;
          /*while循环执行*/
          while(a<20)
          {
                cout<<"a的值:"<<a<<endl;
                a++;
                if(a>15)
                {
                     /*使用break语句终止循环*/
                     break;
                }
          }
    }

程序运行结果如图5-32所示。

图5-32 例5.16的程序运行结果

☆大牛提醒☆

在嵌套循环中,break语句只能跳出离自己最近的那一层循环。

2.continue语句

C++语言中的continue语句有点像break语句。但它不是强制终止,continue会跳过当前循环中的代码,强迫开始下一次循环。对于for循环,continue语句执行后自增语句仍然会执行。对于while循环和do…while循环,continue语句重新执行条件判断语句。

C++语言中continue语句的语法结构如下:

    continue;

continue语句在程序中的应用流程图如图5-33所示。

图5-33 continue语句应用流程图

通常情况下,continue语句总是与if语句联系在一起,用来加速循环。假设continue语句用于while循环语句,要求在某个条件下跳出本次循环,一般形式如下:

    while(表达式1) {
         …
         if(表达式2) {
               continue;
         }
         …
    }

这种形式和前面介绍的break语句用于循环的形式十分相似,两者的区别是:continue只终止本次循环,继续执行下一次循环,而不是终止整个循环;break语句则是终止整个循环过程,不会再去判断循环条件是否还满足。在循环体中,continue语句被执行后,其后面的语句均不再执行。

【实例5.17】编写程序,输出100~120所有不能被3和7同时整除的整数(源代码\ch05\ 5.17.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {     int i,n=0;               /*n计数*/
          for(i=100;i<=120;i++)
          {
               if(i%3==0&&i%7==0)  /*如果能同时整除3和7,不打印*/
               {
                     continue;     /*结束本次循环未执行的语句,继续下次判断*/
               }
               cout <<"\t" << i;
               n++;
               if(n%5==0)          /*5个数输出一行*/
               cout <<endl;
          }
    }

程序运行结果如图5-34所示。可以看出,输出的这些数值不能同时被3和7整除,并且每5个数输出一行。

图5-34 例5.17的程序运行结果

在本实例中,只有当i的值能同时被3和7整除时,才执行continue语句,跳过后面的语句,直接判断循环条件i<=120,再进行下一次循环;只有当i的值不能同时被3和7整除时,才执行后面的语句。

一般来说,它的功能可以用单个的if语句代替。如本例可改为:

    if(i%3==0&&i%7==0)  /*如果能同时整除3和7,不打印*/
    {
       printf("%d\t",i);
    }

这样编写比用continue语句更清晰,又不用增加嵌套深度。因此,如果能用if语句,就尽量不要用continue语句。

3.goto语句

C++语言中的goto语句允许程序无条件地转移到同一函数体内被标记的语句。goto是“跳转到”的意思,也就是说,使用它可以跳转到另一个加上指定标签的语句。goto语句的语法结构如下:

    goto [标签];
    …
    [标签]:语句块;

在这里,标签可以是任何除C++关键字以外的纯文本,可以设置在程序中goto语句的前面或者后面。例如,使用goto语句实现跳转到指定语句的代码如下。

    int i = 0;
    goto a;
    i = 1;
    a : printf("%d",i);

以上代码的含义是,第一行定义变量i,第二行跳转到标签为a的语句,接下来就输出i的结果。可以看出,第三行是无意义的,因为没有被执行,跳过去了,所以输出的值是0,而不是1。

goto语句在程序中的应用流程图如图5-35所示。

图5-35 goto语句应用流程图

☆大牛提醒☆

goto语句并不是一定要跳转到后面的语句,也就是说,goto语句还可以跳到前面去执行。

【实例5.18】编写程序,实现100以内自然数的求和,即1+2+3+…+100,最后输出计算结果(源代码\ch05\5.18.txt)。

    #include <iostream>
    using namespace std;
    int main()
    {
         int i,sum=0;
         i=1;
         loop: if(i<=100)       /*标记loop标签*/
         {
               sum=sum+i;
               i++;
               goto loop;      /*如果i的值不大于100,则转到loop标签处开始执行程序*/
         }
         cout<<"1+2+3+…+100="<<sum<<endl;
    }

程序运行结果如图5-36所示,即可显示1~100整数之和。

图5-36 例5.18的程序运行结果

☆大牛提醒☆

在任何编程语言中,都不建议使用goto语句。因为它会使程序的控制流难以跟踪,使程序难以理解和难以修改,所以原使用goto语句的程序尽量改写成不需要使用goto语句的方式。