在程序设计语言中,流程控制语句用于确定程序的执行顺序。C++语言提供了三种基本控制 结构。顺序结构是指按先后顺序依次执行程序中的语句;分支结构是指根据给定的条件有选择地 执行程序中的语句;循环结构是指按给定规则重复地执行程序中的语句。本章对C++语言的程序 流程控制语句进行详细讲解。 3.程序流程描述的方法 1 .............................. 1.程序流程的描述方式 3.1 在C++语言中有五种常用的程序流程描述方式:自然语言、传统流程图、N-S流程图、伪代码 和程序设计语言。 1. 自然语言 在1.计算机程序是为了完成某项任务、计算 1节我们讲过什么是计算机程序, 解决某个问题, 机要执行的一系列指令(步骤)。如果操作步骤都是顺序执行的,那么用自然语言描述通俗易懂, 比较直观且容易理解。比如案例3中计算泳池栏杆造价用自然语言描述为:先输入泳池的半径, 计算泳池的周长,然后用栏杆单价乘以泳池的周长,计算出泳池周围栏杆的造价,最后输出计算结 果。显然,自然语言可以把操作步骤说明得很清晰,但是,如果程序中包含了分支结构和循环结 构,并且执行步骤较多时,使用自然语言描述就会显得不那么清晰明了。 2. 传统流程图 1所示)、 行步骤,控制语句的执行顺序,是程序分析和过程描述的基本方式。这种方法能够克服复杂程序 用自然语言描述不直观的缺点。 程序传统流程图是用一系列特定图形符号(如表3.流向线和文字说明描述程序的执 表3.传统流程图常用的特定图形符号 1 序号图形符号名称含义 1 起止框程序的开始或结束 2 处理框数据的各种处理和运算操作过程 3 输入/输出框数据的输入和结果的输出 4 注释框添加程序注释 5 流向线程序的执行路径 6 判断框根据条件的不同,选择不同的操作 7 连接点转向流程图的其他位置或从其他位置转入 三种基本程序流程结构为:顺序结构、分支结构(单分支、二分支、多分支)和循环结构。循环 结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序段称为循环体。三种基本 结构可以用传统流程图明晰地表达,如图3.6所示。 1~图3. 图3.1 顺序结构图3.图3. 2 单分支结构3 二分支结构 88 图3. 4 多分支结构 图3.5 当型循环结构图3. 6 直到型循环结构 当型循环结构是指若条件满足时执行循环体语句;若条件不满足时,退出循环,执行循环体后 面的语句。直到型循环结构是指先执行循环体语句块,如果条件满足,就继续执行循环体语句块, 直到条件不满足的时候退出循环。 3.N-S流程图 N-S流程图又叫盒图,是美国学者I.Nasi和B.Shneiderman提出的一种在流程图中完全去 掉流向线的图,将全部程序写在一个矩形框内,从而避免在描述大型复杂算法时,图中的流向线较 多,影响了用户对程序的阅读和理解。N-S流程图使用矩形框来表达各种处理步骤。顺序结构、分 支结构及循环结构的NS流程图如图3.12所示。 -7~图3. 图3.7 顺序结构图3.图3. 8 单分支结构9 二分支结构 图3. 10 多分支结构 图3.11 当型循环结构图3. 12 直到型循环结构 89 4. 伪代码 伪代码是在更简洁的自然语言描述中,用程序设计语言的流程控制结构来表示处理步骤的执 行流程,用自然语言和各种符号来表示所进行的各种处理及所涉及的数据。它是介于程序代码和 自然语言之间的一种描述方法。这样描述的程序书写紧凑、自由,在表达分支结构和循环结构时 易于理解,同时也更有利于流程向程序的转换。顺序结构、分支结构及循环结构的伪代码描述形 式如图3.~图3. 1318 所示。 图3.13 顺序结构图3.图3. 14 单分支结构15 二分支结构 图3.16 多分支结构图3.图3. 17 当型循环结构18 直到型循环结构 5. 程序设计语言 程序最终是需要在计算机上运行的,因此程序设计语言是程序的最终描述形式。无论用何种 方法描述,都是为了将其更方便地转化为计算机程序。 3.2 判断素数的程序流程描述 1. 1. 素数的定义 素数也称为质数,指的是在大于数字1的自然数中,除了可以被数字1以及该数字本身整除之 外,再也不能够被其他任何自然数整除的数。如果还可以被其他自然数整除,则称该自然数为 合数。 2. 自然语言描 述 【例3.判断一个自然数n是否是素数(有如下步骤 。 步骤11 : 】 输入n的值。 n>=2) , 90 91 步骤2:设置变量i的值为2。 步骤3:求解r=n%i;若r=0转向步骤6,否则执行步骤4。 步骤4:变量i的值自加1。 步骤5:判断i=2),如图3.19所示。 4.用N-S流程图描述 判断一个数n是否是素数(n>=2),如图3.20所示。 图3.19 判断素数的传统流程图 图3.20 判断素数N-S流程图 5.用伪代码描述 判断自然数n是否为素数的伪代码描述如下: input n; i 置为2; while(i using namespace std; int main() { int n,i,r; cout<<"输入大于或等于2 的自然数n:"; cin>>n; //输入n i=2; while(i using namespace std; int main() { const float price1=5.0; //第一阶梯单价 const float price2=6.75; //第二阶梯单价 const float price3=12; //第三阶梯单价 float bound1=120*price1; //第二阶梯用水量的基数 float bound2=120*price1+(180-120) *price2; //第三阶梯用水量的基数 float cons; //年度用水量 float total; //缴费金额 cout<<"请输入本年度用水量: "; cin>>cons; if(cons<=120) //如果小于或等于120 立方米 total=price1*cons; //第一阶梯单价×用水量 //120 立方米以内的单价属于第一阶梯单价,超出部分为第二阶梯单价 else if(cons<=180) //用水量在第二阶段 total=bound1+(cons-120)*price2; //120 立方米以内的单价属于第一阶梯单价,120~180 立方米的单价属于第二阶梯单价 //超出180 立方米的属于第三阶梯单价 else total=bound2+(cons-180)*price3; cout<<"您本年度需要缴费: "< using namespace std; int main() { double n; cout<<"输入数据n:"; cin>>n; if(n<0) n=-n; cout< using namespace std; int main() { int n; cout<<"请输入一个整数:"; cin>>n; for(int i=1;i<=n;i++) if(n%i==0) cout< #include using namespace std; int main() { char userName[30]; //用户名 char pass[30]; //密码 cout<<"请输入用户名: "; cin>>userName; //输入用户名 cout<<"请输入密码: "; cin>>pass; //输入密码 //下面判断如果用户名是"Feng"并且密码是"PPNN13mod" if(!strcmp(userName,"Feng")&&!strcmp(pass,"PPNN13mod")) cout<<"登录成功!"; else //任何一个不正确 97 cout<<"用户名或密码错误!"; return 0; } 因为根据上面程序的条件不能确切知道到底是用户名错误还是密码错误,现在对该代码进行 修改。在二分支语句中嵌套了二分支语句,首先判断用户名是否正确,如果用户名正确,再看密码 是否正确,只有二者都正确的情况下,才会提示“登录成功!”。 if(!strcmp(userName,"Feng")) //用户名正确 if(!strcmp(pass,"PPNN13mod")) //密码正确 cout<<"登录成功!"; else //密码不正确 cout<<"用户密码错误!"; else //用户名不正确 cout<<"用户名错误!"; 分支嵌套说明:在分支嵌套中需要注意else子句如何与if子句的匹配问题。 【例3.5】 if子句和else子句的匹配问题。 if(x>0) if(x < 50) cout<<"OK!\n"; else cout<<"NOT OK!\n"; 阅读本段代码,else子句前面有两个if子句,如果把else子句看成和第一个if子句匹配,那么 就是一个二分支结构中嵌套了一个单分支结构;如果把else子句看成和第二个if子句匹配,那么 就是一个单分支结构中嵌套了一个二分支结构。这样对于给定的x值,输出结果就不一样了。比 如x的值是-100,如果把else子句理解为和第一个if子句匹配,那么输出“NOT OK!”;如果把 else子句理解为和第二个if子句匹配,那么什么也不输出。同理,如果x的值是80,如果把else子 句理解为和第一个if子句匹配,那么什么也不会输出;如果else子句和第二个if子句匹配,那么就 会输出“NOTOK!”。程序在相同的输入情况下,不可能输出不同的结果。那么在出现这样语句 的情况下,else子句到底与哪个if子句匹配呢? 记住else子句从属于最近的if子句,本案例中else 子句和第二个if子句匹配。如果想让else子句与第一个if子句匹配,应用加花括号{}来实现,修 改如下: if(x>0) { if(x < 50) cout<<" x is OK\n"; }e lse cout<<" x is not OK\n"; 4.多分支 多分支结构的传统流程图如图3.4所示。多分支语句里至少有一个elseif关键字,是在同一 个表达式可能有多个选择的情况下,根据条件选择执行不同的语句块。案例7就是根据用水量的 98 多少,有三种计算缴费的标准,所以这是三分支语句,有时候可能有更多的分支。 【例3.6】 输入一个百分制的学生成绩score,请把百分制成绩转换成五分制的字符,转换规则 如下:如 果输入的成绩不是0~100分,则输出“成绩无效”;否则,若成绩在60分以下输出“E”;若成 绩大于或等于60分且小于70分输出“D”;若成绩大于或等于70分且小于80分输出“C”;若成绩 大于或等于80分且小于90分输出“B”;若成绩大于或等于90分且小于或等于100分输出“A”。 程序传统流程图如图3.24所示。 图3.24 百分制转换五分制流程图 根据画好的传统流程图,再写程序代码就会感觉简单多了,代码如下: #include using namespace std; int main() { int score; //声明成绩变量 cout<<"请输入学生成绩[0~100]"; //提示信息 cin>>score; //输入语句 if(score<0||score>100) cout<<"成绩无效! \n"; else if(score<60) cout<<"E\n"; else if(score<70) cout<<"D\n"; else if(score<80) cout<<"C\n"; else if(score<90) cout<<"B\n"; else cout<<"A\n"; return 0; } 多分支语句中含有多个elseif子句,从代码上看程序的可读性较差,通常多分支语句可以转 99 换成开关语句,即用switch语句完成。 3.2.3 上机练习 【上机目的】 ● 熟悉分支结构中条件语句的用法。 ● 掌握条件语句的三种分支语句的格式。 ● 掌握条件语句的嵌套和多分支语句之间的区别。 1.上机调试阶梯水价案例,要求先把收费标准中每个阶段水价及水量标准从键盘输入,再输 入用户的用水量,计算用户的缴费金额。这样程序就可以适用于不同年份、不同地区有阶段水价 或水量标准调整的情况。 2.用户登录的案例中,第一种方法可以“提示用户名或密码不正确”,第二种方法用if嵌套语 句实现时,可以提示“用户名错误”或“密码错误”。请修改程序,完成当用户名和密码都错误时给 出“用户名且密码错误”的提示信息。 3.一元二次方程ax2+bx+c=0,a是二次项系数,b是一次项系数,c是常数项。编写程序要 求从键盘输入a、b、c三个数,如果a为0,输出“不是一元二次方程!”,否则求出一元二次方程的 解。若判别式大于0,有两个不等实数根,输出两个不等实数根的值;若判别式等于0,有两个相等 的实数根,输出相等实数根的值;若判别式小于0,有两个共轭复数根,输出两个共轭复数根。 4.编写程序完成从键盘上输入一个字符,输出这个字符是字母、数字、空格还是其他字符。 【思考与练习】 1.简答题 (1)else子句如何与if子句相匹配? (2)分别用单分支结构、二分支结构和多分支结构写一个程序。 2.单选题 (1)有语句 int a=1,b=2,c=3; if(a>c) b=a; a=c; c=b; 则c的值为( )。 A.1 B.2 C.3 D.不一定 (2)条件语句的格式: if(条件表达式) 语句块1; else 语句块2; 其中“条件表达式”为( )。 A.是关系表达式 B.必须是逻辑表达式 C.必须是关系表达式或逻辑表达式 D.可以是任何合法的表达式 3.程序分析 (1)写出运行结果。 1 00 int a=4,b=3,c=5,t=0; if(a using namespace std; int main() { char vlpn[10]; //车牌号码 cout<<"请输入车牌号码:"; //提示信息 1 01 cin>>vlpn; char letter; //第一个字母 letter=vlpn[0]; switch(letter) { case 'A': cout<<"石家庄市\n"; break; case 'B': cout<<"唐山市\n"; break; case 'C': cout<<"秦皇岛市\n"; break; case 'D': cout<<"邯郸市\n"; break; case 'E': cout<<"邢台市\n"; break; case 'F': cout<<"保定市\n"; break; case 'G': cout<<"张家口市\n"; break; case 'H': cout<<"承德市\n"; break; case 'J': cout<<"沧州市\n"; break; case 'R': cout<<"廊坊市\n"; break; case 'T': cout<<"衡水市\n"; break; default: cout<<"不是河北省的车辆! \n"; } return 0; } 3.程序分析及运行结果 本程序案例同样是属于多分支,是根据车牌号码首字母的不同,执行不同的输出语句。如果 使用条件语句,也完全能够实现此功能,但是会有很多项elseif子句,程序的可读性较差,这里使 用了开关语句,即switch语句,程序代码就很清晰,一目了然。下面介绍开关语句的语法格式及其 注意事项。 3.3.2 开关语句 1.开关语句的语法格式 开关语句具有如下一般格式: switch(整数表达式) { case 整常量表达式1: 语句序列1; break; case 整常量表达式2: 语句序列2; break; case 整常量表达式3: 语句序列3; break; …… case 整常量表达式n: 语句序列n; break; default: 语句序列n+1; } 等价于条件语句: if(整数表达式==整常量表达式1) 语句序列1; else if(整数表达式==整常量表达式2) 语句序列2; 1 02 else if(整数表达式==整常量表达式3) 语句序列3; …… else if(整数表达式==整常量表达式n) 语句序列n; else 语句序列n+1; 开关语句的流程图如图3.25所示。 图3.25 switch语句流程图 根据本案例的问题描述和switch语句的流程图,画出本案例流程图如图3.26所示。 图3.26 车牌查询程序流程图 2.开关语句的几点说明 ● switch后面的表达式是整型表达式,一定要含有变量,而case后面的表达式必须是整型常 量表达式,不允许出现变量,字符常量也是整型常量,因为字符类型是整型的子集。 ● 开关语句可以嵌套使用。 ● break是转向语句,在case子句中既可以使用break语句跳出switch语句,也可以没有 break语句。如果有break就结束switch语句;如果没有break语句就接着执行下一个 case子句。 ● default子句既可以有,也可以没有,并且可以放在switch语句的任何位置。 3.开关语句的应用案例 【例3.7】 使用开关语句编程实现输入年、月、日,输出这一天是本年度的第多少天。 #include using namespace std; int main() { 1 03 int year,month,day; //年、月、日 int sumdays; //本月前过了多少天 int days; //本年度的第多少天 cout<<"输入年月日: "; //提示信息 cin>>year>>month>>day; //输入年月日 if(year<0||month<1||month>12||day<0||day>31) //判断日期的有效性 { cout<<"无效日期! \n"; return 0; } else switch(month) { case 1:sumdays=0; break; //输入的月份是1 月份 case 2:sumdays=31; break; //2 月份 case 3:sumdays=59; break; //3 月份,先按平年计算 case 4:sumdays=90; break; //4 月份 case 5:sumdays=120; break; //5 月份 case 6:sumdays=151; break; //6 月份 case 7:sumdays=181; break; //7 月份 case 8:sumdays=212; break; //8 月份 case 9:sumdays=243; break; //9 月份 case 10:sumdays=273; break; //10 月份 case 11:sumdays=304; break; //11 月份 case 12:sumdays=334; //12 月份最后一个语句不需要break; } //本月前的天数+日期的日 days=sumdays+day; //下面判断是否闰年,月份是否在3 月以后, //如果是闰年并且月份在3 月以后,总天数加1 //闰年条件: 400 的整数倍或不是整百的数时是4 的整数倍 if(year%400==0||(year%100!=0&&year%4==0)) //如果是闰年 if(month>2) //如果月份是2 月以后日期 days++; //天数加1 cout< using namespace std; void main() { int a(1),b(6),c(4),d(2); switch(a++) { case 1:c++;d++; case 2:switch(++b) { case 7:c++; case 8:d++; } case 3:c++;d++; 1 05 break; case 4:c++;d++; } cout< #include using namespace std; int main() { srand(time(0)); //设置随机种子 //生成一个随机数 int n=rand()%20+1; //闭区间[1,20] int m; //声明猜数变量 int count=1; //计数器 cout<<"输入一个1~20 的整数:"; cin>>m; //输入数据 while(m!=n) //猜数不正确 { //花括号里是循环体 if(m>m; //接着猜数 count++; //计数器增1 } if(count<4) //猜数少于4 次 cout<<"太棒了! 只用了"<