1.4 控制结构
计算机最神奇的地方在于能够按照人指定的方式执行,且高效无误。比如有一组成绩数据,去除最高分和最低分,然后计算平均分,写好算法后,只要输入数据,程序会自动算出结果。算法步骤如下:
(1)将成绩按照高低排序,去除最高分和最低分。
(2)计算剩余成绩的总分数。
(3)总分数除以数目,得到平均分。
分析以上步骤,排序要判断两个成绩的高低,计算总成绩要重复地累加,因此程序需要一种机制来进行逻辑判断和循环计算,C++提供了if/else结构进行逻辑判断,while、for结构进行循环计算,所有复杂的算法都是基于这几种控制结构而成的。
1.4.1 if/else选择结构
if/else选择结构是一种常见的结构,例如:如果(if)周末天气不错,我就出去玩,否则(else)我就在家学习。if表达式判断条件语句是否为真,若为真执行if块内的语句,否则跳转到else块内执行。可以只有一个if语句,也可以有多个else,也可以在if/else里面嵌套多层if/else。
【实例1-13】利用if/else判断语句输出结果。
#include <iostream> using namespace std; int main() { double d1=40; if(d1>=80) //如果大于等于80 cout<<d1<<" 良好"<<endl; else if(d1>=60) //小于80,如果大于等于60 cout<<d1<<" 及格"<<endl; else //小于60 { cout<<d1<<" 不及格"<<endl; //执行{}块内的语句 cout<<"要努力了!"<<endl; } return 0; }
编译运行,结果如图1-15所示。使用多个if/else控制语句时应注意代码的缩进和{}的使用,以便快速查找匹配的if/else。若用{}包括多行语句,执行该块内的语句,否则执行到第一个分号处。
图1-15 if/else结构
1.4.2 while循环结构
重复性计算是计算机程序最实用的功能,随着计算机硬件计算性能的飞速提升,一秒钟能完成上亿次的运算,充分利用其计算能力可以大大提高工作效率。C++提供多种方式实现循环计算,如while、do-while、for循环。
while循环有一个条件语句,在该条件为假之前,循环一直持续下去。若while循环一直持续下去,就会陷入死循环,造成程序瘫痪,需要在循环体里改变变量值,使条件语句在某时刻为假,从而退出循环。或者使用跳出循环体语句break;。
使用while循环时,首先检查条件语句是否成立,若第一次就不成立,则不进入循环体。若要循环体至少执行一次,使用do-while循环,先执行一次循环体,然后判断条件语句是否成立。第一次循环之后,while和do-while没有区别。
【实例1-14】利用while循环计算整数a的素数组合因子,如48的素数组合因子为2、2、2、2、3。
#include <iostream> using namespace std; int main() { int a=48; int i=2; //测试因子(从2到a) cout<<a<<"的因子:"; while(a!=1) //若a已除尽,退出循环 { if(a%i==0) //若a能被i整除 { a=a/i; //除去i后的值,若a为1,则已除尽 cout<<i<<" "; //输出素数因子 } else //若a不能被i整除,因子自增 i++; } cout<<endl; return 0; }
编译运行,结果如图1-16所示。i作为测试因子,从2开始递增测试,若a能够整除i,则将a变为整除后的值,同时输出因子i。反复测试i直到a不能整除i,如a=48,i=2,a/i后,a=24,输出i,再次执行a/i后,a=12,输出i,直到a不能整除i时,i递增为3,依此类推,直到a等于1时退出循环体。
图1-16 while循环
1.4.3 break和continue语句
break语句用于终止循环,例如要查找某用户名对应的密码,当查找到对应密码后即可停止循环。continue语句用于终止本次循环,直接进入下一次循环,例如查找到的用户名不是想要找的用户名,就没必要继续查看对应的密码,直接查找下一个。若有多层嵌套循环,break只退出该语句所在的循环体,continue同理。
【实例1-15】查找2000~3000范围内第一个可被168整除的数。
#include <iostream> using namespace std; int main() { int i=2000; //从2000开始逐个测试 while(i<=3000) //若i小于等于3000,执行循环体 { if(i%168==0) //若i能被168整除 { cout<<i<<" "; //输出i break; //跳出循环体 } i++; //i自增 } return 0; }
编译运行,计算出i为2016。从2000开始逐个数进行判断,若能被168整除,输出值并退出循环体,否则递增值,判断下一个值是否满足条件。若测试值大于3000,则不再执行循环体。
1.4.4 for循环结构
for循环类似于while循环,不同之处在于for循环将初始化、条件判断、变量递增放在一起,如上一节的实例代码中,int i=2000;为初始化,i<=3000为条件判断,i++;为变量递增,用for循环结构表示就是for(int i=2000;i<=3000;i++) ,括号内至少有两个分号,内容可以为空,如for(; ;),其他同while循环。
【实例1-16】计算1~99的累加和。
#include <iostream> using namespace std; int main() { int sum=0; //总和 for(int i=1;i<=99;i++) //从1到99逐个计算 { sum+=i; //将i加到sum中 } cout<<"1+2+…+99 = "<<sum<<endl; //输出累加和 return 0; }
编译运行,计算结果为4950。利用for循环初始化i为1,循环条件为i<=99,每次循环变量i递增1,将1~99中的每个数都加到sum中,得到累加和。
Tips for循环的( )中定义的变量i,在标准C++中规定是局部变量,仅在for循环内部可用。在VC6.0环境中i在for循环体之后仍可使用,相当于int i=0; for(i=0;…){} ,这是VC6.0的自身不规范造成的,Visual Studio 2005等高级版本符合标准C++规范,常用解决方法是把int i=0;提取出来作为一个单独的表达式,放到for循环之前,避免在不同环境下造成混乱。
1.4.5 switch多选结构
switch结构用于多种可能结果的分类操作,例如选择计算类型,若为加法,执行相加运算,若为除法,执行相除运算。若使用if/else结构也可,但不够简练直观。
switch()内的变量或表达式必须是整型值,或者能够自动转换为整型的类型。每种可能结果都是一个case子句,可执行不同的操作,case子句后需要有break语句,否则将继续执行后面的case子句。可有一个默认的default子句,若所有case都不匹配,执行default子句。
【实例1-17】利用switch语句根据运算符类型,执行不同的运算。
#include <iostream> using namespace std; int main() { char ch='*'; //运算类型 int a=120; int b=30; double result=0; //结果 switch(ch) //根据运算类型不同决定计算方式 { case '+': //若为加 result=a+b;break; case '-': //若为减 result=a-b;break; case '*': //若为乘 result=a*b;break; case '/': //若为除 result=(double)a/b;break; } cout<<"运算类型 "<<ch<<" 结果 "<<result<<endl; return 0; }
编译运行,结果如图1-17所示。若在case子句后不使用break语句,则继续执行后面的case子句,直到遇到break语句跳出switch语句块。
图1-17 switch结构