第04章控制结构-2014

Download Report

Transcript 第04章控制结构-2014

计算机程序设计
计算机学院613教研室
唐晋韬
第四章 控制结构
本章内容

4.1 程序的基本控制结构

4.2 表达式语句

4.3 顺序结构

4.4 选择结构

4.5 循环结构

4.6 控制转移语句

4.7 结构化程序设计
结构化程序设计方法回顾

结构化程序设计
– 任何程序逻辑都可以用顺序、选择和循环三种
基本结构表示
顺序结构
选择结构
循环结构
4.1 程序的基本控制结构

顺序结构

选择结构:if语句、if-else语句、switch
语句

循环结构:while语句、do-while语句、
for语句

控制转移语句:continue语句、break语
句、goto语句、return语句
4.2 表达式语句

表达式语句:表达式+分号
–
–
–
–
a = a + 3;
x = y = z = 0;
z=i<j?x:x+y;
f1();
#include <math.h>
– x1 = exp(x);
– x2 = pow(x, y);

空语句
– ; //特殊的表达式语句
赋值语句
多重赋值语句
条件表达式语句
函数调用语句
函数表达式语句,计算 ex
函数表达式语句,计算xy
4.3 顺序结构——复合语句

C++程序由若干语句构成
– 大部分语句按它在程序中的位置顺序执行
– 通过复合语句描述顺序结构

复合语句
– <复合语句>
‘{‘<语句序列>’}’
– 复合语句内可以有数据声明
– 复合语句可以嵌套
4.3 顺序结构——复合语句

复合语句的例子
–{
–
–
–
–}
int a=1;
//变量声明
a = a + 3;
// 赋值语句
printf(“now a is %d“, a); // 函数调用
例子:计算圆的周长和面积
#include <iostream.h>
#define PI 3.14
int main() {
double radius, area;
double perimeter;
radius = 3.0 ;
perimeter = PI * 2 * radius;
cout<<"Perimeter is : "<<perimeter<<"\n" ;
语句
语句
语句
area = PI * radius * radius;
语句
cout<<"Area of the circle is : "<<area<<"\n" ;
return 0;
}
语句
顺序结构
课堂练习

食堂煎饼2.5元一个,同时优惠酬宾买二
送一,编写程序,输入用户需要的烧饼个
数,计算并输出客户应付的金额。
顺序结构足够了吗?

生活中到处都是判断和选择
– 如果下午不下雨,我们就跑5000m
– 蚂蚁搬家要下雨,鱼浮水面要下雨
– If I were a boy, I swear I’d be a
better man.
独立思考和独立判断的一般能力,应当始
终放在首位——爱因斯坦
4.4 选择结构

if 语句:实现单路、双路、多路选择
– if (score>=60)
cout<<"Passed!"<<endl;
– if (s == 1)
cout<<"male";
else
cout<<"female";
– if (y == 1)
rate = 0.02;
else if (y == 2)
rate = 0.03;
else rate = 0.01;
4.4 选择结构

语句
if 选择结构的一般形式
if (<条件表达式>) <语句>;
else <语句>;
关系
表达式
真
假
为假时
的语句
语句
流程图
为真时
执行的
语句
4.3 选择结构

一个if分支或else分支有且只能有一条语句

如果某个分支不需要做任何事怎么办?
– 空语句

如果某个分支需要多条语句怎么办?
– 复合语句
(a > b)
ifif(speed<=120)
; //do nothing
{
else
ccout<<“dangerous
= a;
a = b;
bdriving!”
= c;
}
程序风格

if 控制结构的书写规则
– 从语法上来讲,整个 if 语句可以写成一行 —— 但一般
情况下,<语句> 部分要相对于 if 缩进一层,当<语句
> 部分是复合语句时,更应如此
– 当 <语句> 部分是复合语句时,必须使用花括号
int a=3;
if (a<=2)
{
a++;
a++;
}
cout <<a<<endl;
int a=3;
if (a<=2)
a++;
a++;
cout <<a<<endl;
大家的小错误

个问题
– 第一要实现功能“如果 a>3 ,则将 b 的值增
加1” 这个功能:
int a=2, b=1;
if (a>3) ;
b++;
cout << b << endl;
– 猜猜会输出多少?
大家的小错误

第二个问题
– 看下面的程序:
– 猜猜会输出多少?
int a = 1;
if (a=3)
a++;
cout << a << endl;
4.4 选择结构-课堂练习


输入 3 个数,按照从大到小的顺序输出它们
的值
算法设计
①
②
③
④

提示输入三个数值,存放在num1、num2、num3 中
通过比较/交换,将最大的值放在 num1 中
通过比较/交换,将次大的值放在 num2 中
按照 num1、num2、num3 的次序输出即可
如何实现步骤 2 ?
1)
2)
比较 num1 和 num2,若 num1<num2 则交换二者
的值
比较 num1 和 num3 若 num1<num3则交换二者的
值
4.4 选择结构-课堂练习

如何实现步骤 3 ?
– 比较 num2 和 num3 若 num2<num3则交换二者的值

如何交换两个变量的值(以 num1、num2 为例)?
{
int tmp = num1;
num1 = num2;
num2 = tmp;
}

现在,写出整个程序
4.4 选择结构-课堂练习

输入一个百分制(0-100)的考试成绩,请
输出一个五级制(A-E)的分数等级评定
– 输入:一个0-100之间的整数,代表分数
– 输出:A (90-100)、B、C、D、E(0-59)五个等级
– 算法设计:
① 判断输入成绩是否小于60,如果是则输出E
② 否则,判断输入成绩是否小于70,如果是则输出D
③ 否则,判断…. (同步骤2,输出C和B)
④ 否则,输出A
请实现这个程序!
是不是感觉有点别扭?
4.4 选择结构-Switch结构

switch 选择结构
– 如果需要对多于两
种可能(相对)的情
况进行处理,使用
嵌套的 if-else 处理
并不自然
– C++ 中提供了一种
多分支选择结构 —
switch 结构
switch (<条件表达式>)
{
case <常量表达式1>:
<语句序列1>;
…
case <常量表达式n>:
<语句序列n>;
default :
<语句序列n+1>;
}
4.4 选择结构

注意事项
– <条件表达式> 可以是任意兼容整型(字符型、整
型)的表达式
– <常量表达式 1>, ⋯, <常量表达式n> 中必须不含
变量和函数调用
– <常量表达式 1>, ⋯, <常量表达式n> 后面跟的是
冒号,不是分号
– <语句序列 1> ,⋯,<语句序列 n+1>,如果多于一
条语句,可以不用花括号
– default 分支只能有一个,并且必须出现在最后
– switch (<条件表达式>) 之后,必须用一对花括号
将整个分支结构括起来
switch 结构的执行
计算<条件表达式>的值 v
v==<常量表达式1>?
T
语句序列 1
T
语句序列 2
F
v==<常量表达式2>?
…
…
F
v==<常量表达式n>?
F
T
语句序列 n
语句序列 n+1
int a =4;
switch(a)
{
case 3:
a++;
cout <<a <<endl;
case 4:
a++;
case 5:
a--;
case 6:
a+=2;
default:
cout<<a<<endl;
}
4.4 选择结构-Switch

在 switch 结构中,若首先匹配的是 <常量表达
式k>,那么 <语句序列 k> 得以执行

执行完 <语句序列 k> 后,<语句序列 k+1> 、
<语句序列 k+2> ⋯⋯ <语句序列 n+1> 会依次
被执行

现在的问题是,如果只想执行 <语句序列 k>
应当怎么做?

可以配合 break 语句完成!
switch + break
switch (<条件表达式>)
{
case <常量表达式1>:
<语句序列1>;
break;
…
case <常量表达式n>:
<语句序列n>;
break;
default :
<语句序列n+1>;
}
计算<条件表达式>的值 v
v==<常量表达式1>?
T
语句序列 1
F
T
语句序列 2
v==<常量表达式2>?
F
…
T
v==<常量表达式n>?
F
语句序列 n+1
语句序列 n
int a =4;
switch(a)
{
case 3:
a++;
cout <<a <<endl;
case 4:
a++;
break;
case 5:
a--;
default:
cout<<a<<endl;
}
4.4 选择结构-课堂练习
#include <iostream>
输入一个百分制(0-100)的考试成绩,请
using namespace
std;
输出一个五级制(A-E)的分数等级评定
int main()
{
– 如何用switch结构实现?
int grade;
– 80-89的数字有什么特点?
cout<<"Input
a grade:";
cin>>grade;
– 除以10,结果都为8
switch (grade/10)
{
case 10:
case 9:
cout<<'A'<<endl;
break;
case 8:
cout<<'B'<<endl;
break;
case 7:
cout<<'C'<<endl;
4.4 选择结构-研讨

什么时候使用if-else?什么时候使用
switch?
– 热量传输,A的温度>B的温度,则从A传到B,
小于则从B到A……
– 水的状态,温度>100,为气态……
– 处理交通违章,乱停扣3分、罚200……
– 根据距离和费用选择交通工具……
– 汽车根据速度选择档位,大于25进2档……

有什么规律吗?
4.4 选择结构-研讨

顺序结构+选择结构足够了吗?
– 现在,不仅一门课需要从百分制改成五
级制输出,每位同学的五门课都要改成
五级制,请修改程序,使其可以接受5
个(0-100)的整数输入,并输出相应
的五级制评分
Switch选择结构需要重复五遍!
如果我们1000位同学的成绩
都要这样修改呢?
4.5 循环结构

生活中到处是循环
–
–
–
–
起床、出门、上班、回家、入睡
周日到周六
春夏秋冬是一年,自转、公转
{幼儿、孩童、少年、青年、中年、老年} 换代
4.5 循环结构

循环的意义
– “以有穷建模无穷”
– 程序代码必定是有穷的,但是,程序运行可以
是无穷的。
– 自然语言如何以有穷描述无穷?
从前有座山,山上有座庙,庙里有个老和尚,
一天老和尚对小和尚讲故事,从前有座山,
山上有座庙。。。
虽我之死,有子存焉;子又生孙,孙又生子;
子又有子,子又有孙;子子孙孙无穷匮也
循环如何表示和控制?

如何表示
– 圆、圈
– 头尾相连、封闭
– 往返
西汉龙形玉环

每次循环时,有不变的,也有变的值

如何控制?
– 通过变的值控制
– 控制循环的入口
– 控制循环的出口
程序中如何表示循环?

程序缺省是顺序执行

如何表达循环?
语句
语句
语句
跳出循环?
语句
语句
程序中如何控制循环?

在需要时在任何位置均可跳出

循环入口控制,必须满足一定条件才能进
入循环

循环出口控制,跳出前必须满足一定条件

跳出只能达到指定位置
从入口控制:while 结构

while 循环的一般形式
while (<条件表达式>) <语句>;

执行框图
条件表达式
T
语句
F
4.5 循环结构: while 语句

执行顺序的语言描述:
1.
2.
3.
4.
5.

计算 <条件表达式> 的值
若该值不为 0 (false) 转 3, 否则转 5
执行 <语句> (以后称其为“循环体”)
转1
while 循环结束
风格提示
–
–
–
书写 while 语句时,while 语句及其测试
表达式单独一行
循环体语句要缩进一层
当循环体语句为复合语句时,记得使用花
括号
4.5 循环结构: while 语句

示例:设计一个程序,该程序能够从键盘
上接收任意个非负数(以负数作为输入结
束标记),并计算这些数据的和

算法设计
– 待求和数据的可能有若干个,利用循环
入口控制
– 循环条件 : 输入的数据 i >=0
条件
– 循环体,将输入的 i 的值累加到变量 sum 上

注意
– 在进行循环前,必须要将 sum 初始化为 0
课堂练习

利用如下公式求π的值并输出,直到最后
一项绝对值小于10-7
– 求π的公式:
π = (1-1/3+1/5-1/7+1/9…)×4

算法设计

变量:不断增长的整数a,结果π

计算方法:循环使用公式: 𝜋 = 𝜋

循环终止条件: 1/a < 10-7
4
±
2𝑎+1
4.5 循环结构: 出口控制

do-while 循环的语法
do <语句> while (<条件表达式>);

执行框图
语句
条件表达式
F
T
4.5 循环结构:do-while 循环结构

执行框图语言描述
1. 执行<语句> (循环体)
2. 计算<表达式语句>的值,若该值为真(非
0),转1,否则,转 3
3. 结束该循环结构

风格提示
–
–
–
书写 do-while 语句时,do 单独占一行
循环体缩进一层,若是复合语句应用花括
号括起
do 和 while 应当对齐
课堂练习

请将求π的程序调整成do-while结构
是否更加自然?
循环调控与决策分离问题
初始化
int iCount = 1;
while (iCount <= 5) {
控制决策
cout << "Loop#" << iCount << endl;
iCount++;
参数调控
}
初始化
do {
cout << "输入-1和1之间的x: ";
cin >> x;
参数调控
}while ( x>1 || x<-1 );
控制决策
4.5 循环结构:for循环

初始化

(参数)调控

(跳出)决策
初始化
集中管控
决策
调控
for (i
(初始化;
条件判断;
= 1; i
<= 10; 步进控制)
i++ )
{
{
语句序列;
只有一个语句时,
cout << "Hello!"
<< endl;
}
}
可以不要 { }
4.5 循环结构:for循环

执行过程
1.
2.
3.
4.
5.
执行 <初始化语句>
计算 <条件表达式>
的值,若其值为真,
转 3, 否则,转 5
执行 <语句>
执行 <增量表达式>,
转2
退出 for 循环结构
初始化语句
增量表达式
语句
条件表达式
T
F
4.5 循环结构:for循环
1.
将变量 i 从 1 变到 100, 增量为1
for (i=1; i<=100; i++)
2.
将变量 i 从 100 变到 1, 增量为 -1
for (i=100; i>=100; i--)
3.
将变量 i 和 j 分别从 1 变到 99, 从 2 变到 100,
增量均为 2
for (i=1, j=2; (i<=99 && j<=100); i+=2, j+=2)
4.5 循环结构:for循环

课堂练习:编程实现求和

算法设计
Sum 
– 变量:自增数n,和sum
– 循环体:sum+=n3
– 循环控制,自增参数n<=20,for循环实现最自然
20
n

n
1
3
4.5 循环结构:for循环

课堂练习,判断下面循环的次数
for (int a=1; a<=15; a+=2) … ;
for (int a=12; a>=-12; a--) … ;
for (int a=12; a>=12;--a)… ;
for (int a=-20; a<=20; a+=4) … ;
for (int a=4; a<=17; a+=4) … ;
for (int a=1; a<=120; a*=2) … ;
4.5 循环结构:多重循环
for (初始化; 条件判断; 步进控制)
 多重循环的例子
{ – 1小时=60分钟,1分钟=60秒
–语句序列;
将每位同学的各科分数从百分制转换成5级制
}

程序如何表示多重循环?
for,while,do等循环语句也可是
其中之一
while(条件表达式)
{
语句序列;
}
do
{
语句序列;
}while(条件表达式)
4.5 循环结构:多重循环

多重循环的循环次数
int count1 = 0, count2 = 0, count3 = 0;
for (int i = 5; i > = 0; i--){
count1++;
for (int j = 1; j <= 10; j++){
count2++;
for (int k = 1; k <= 10; k++)
count3++;
}
}
count1、count2、count3有什么关系?
多重循环:课堂练习

要求:在显示器输出如下图所示的“V”字图形,
其中,行数(大于等于1)由用户输入

算法设计
**
**
– 输入输出:用户输入行数line,输出为 **
**
line行*号和空格组成的字符串。
** **
– 图案和行数的关系?
****
1) 第k行打印(k-1)个空格,然后打印**
**
2) 第k行打印(line-k-1)个双空格” ”
3) 除最后一行外,再打印**
4.5 循环结构:无限循环
//监控报警
 //时钟显示
当一个循环的条件表达式永远为真时,循环
体将无限运行下去
do {
while
(1) {
if (报警条件为真)
等待1秒;
do 大家容易犯的错误
显示当前时间;
k=1; while(k=1) k++; 发出报警声音;
{ – 书写错误:int
– 逻辑错误:while(π!=3.14)
𝜋 = }while
𝜋 ± 4/𝑎; (1); 死循环
}
//loop
code
} while
(1/a>1.0E-15);
无限循环是有用的
//
– 四季交替:年年岁岁花相似
售货机
– 月圆月缺:月有阴晴圆缺
for(;;)
unsigned
int i{ ;
等待输入;
for(i=1;i!=0;i++)
 伪死循环
{
– 接收选择、收钱并释放货品;
一个循环看似不会退出,但只是一个运行很长时间,最后
仍会退出的循环
找钱;
/* loop
code */
} }
4.6 控制转移语句

控制转移语句的作用
– 控制转移语句可以改变程序的执行顺序
– 早期的程序通过 goto 语句来达到这个目的
– 为了避免滥用 goto 语句造成代码混乱,C++ 中引入
了若干特定的控制转移语句

C++ 中的控制转移语句
–
–
–
–
break 语句
continue 语句
goto 语句
return 语句
4.6 控制转移语句:break 语句

break 语句的应用环境:
– switch 语句
– while 循环、do-while 循环、for 循环

用法
break;;


作用
–
–
–
–
在 switch 语句中,直接跳转至该语句结尾
在循环语句中,用以跳出该循环语句
在多重循环中,只跳出最内层循环
通常与 if 语句配合使用
Break使用示例

判断一个正整数 n 是否素数 [例4-14]
– 问题分析:素数的因子仅包含1和自身
–…
算法设计:
① 输入无符号整数n
② 变量i从2自增到n/2,循环计算n是否能被i整除
for(int i=2; i<=n/2; i++)
③ 如能整除,证明n不是素数,跳出循环,输出结论
if (n%i==0)
④ 循环结束,证明n为素数
{
如何根据条件,在
循环体中跳出循环?
isPrime = false;
break;
}
…
4.6 控制转移语句: continue

continue 语句的应用环境
– while 循环、do-while 循环、for 循环

用法
continue;

作用
– 跳过循环体的其余语句,开始下一次循环,通常与 if
语句配合使用
– 在 while/ do-while 结构中,遇到 continue 会结束本
次循环,转去测试<条件语句>
– 在 for 循环中,遇到 continue 会先执行<增量语句>,
而后转去测试<条件语句>
continue 语句的使用示例

…
输出1~10 中除 5 外的数字 [4-15]
int x=1;
while (x<=10)
{
if (x==5)
{
x++;
// 想想这句话的作用
continue;
}
cout << x<<“ ”;
x++;
}
…
4.6 控制转移语句:goto

goto 语句的用法
goto <标号>;

if (a>=3)
goto语句的作用
goto add;
– 用于无条件跳转,其中 <标号>,是加在跳转目标语句
a++;
之前的一个标识符
add: b=a+2;
举例

避免大量使用 goto 语句

– 大量的使用 goto 语句,会降低代码的结构化以及可读
性,因此应当尽量少用或者不用 goto 语句
4.6 控制转移语句:return

return 语句
–
–
–
–
return <返回值>;
用法:
作用:用以结束当前的函数,返回调用函数
主函数遇到 return,程序就会结束
在后面一章中,我们将会详细介绍函数的返回
4.7 结构化程序设计:方法

结构化程序的构成
– 从结构化的观点来看,任何程序都应该由若干
仅含顺序、选择、循环结构的模块组成
– 每个模块和结构只有一个出口和一个入口

结构化程序形成规则
1)从“最简单流程图”开始,进行如下迭代
2)将某个矩形框换成两个顺序矩形框(堆栈规则)
3)将某个矩形框换成某个控制结构(嵌套规则)
4)按照任何顺序重复规则 2) 或规则 3),直至每
个矩形框都对应于一条确定的语句
4.7 结构化程序设计:原则

自顶向下,逐步求精
– 先考虑总体,再考虑细节
– 先考虑全局,再考虑局部目标

模块化
– 对一个复杂的问题来说,必然由若干稍简单的
问题构成;
– 为解决复杂问题,而将其分解为若干简单部分
(称为模块)的过程就叫“模块化”

限制使用 goto 语句
结构化程序设计举例

打印下面的图形
*
***
打印上部分图形
*****
*******
*****
***
*
打印下部分图形
打印第1行
cout<<“*”<<endl;
打印第2行
cout<<“***”<<endl;
打印第3行
cout<<“*****”<<endl;
打印第4行
cout<<“*******”<<endl;
打印第5行
cout<<“*****”<<endl;
打印上半部分图形
打印下部分图形
打印第6行
cout<<“***”<<endl;
打印第7行
cout<<“*”<<endl;
i =1
打印第1行
i<=4
F
int i=1;
while (i<=4)
{
打印第2行T
打印第 i 行
打印第 i 行
打印第3行
i++;
}
i++
打印第4行
F
打印第5行
i<=7
while (i<=7)
{
T
打印第 i 行
打印第6行
打印第 i 行
打印第7行
i++
i++;
}
int i=1;
while
for (int(i<=4)
i=1; i<=4; i++)
{
打印 2*i-1
打印第
i 行个‘*’
cout << endl;
i++;
}
for
(i=5;
i<=7; i++)
while
(i<=7)
{{
打印 15-2*i
打印第
i 行 个‘*’
cout << endl;
i++;
}}
#include <iostream>
using namespace std;
int main()
{
for (int i=1;i<=4;i++)
{
for (int j=1;j<=2*i-1;j++)
cout << ‘*’;
cout << endl;
}
for(i=5; i<=7;i++)
{
for (int j=1;j<=15-2*i;j++)
cout << ‘*’;
cout << endl;
}
return 0;
}
提高实践

刑侦大队对涉及6个嫌疑人的一桩疑案进行分析:
–
–
–
–
–
–

1.A和B至少有一人作案
2.A、E、F三人中至少有2人参与作案
3.A、D不可能是同案犯
4.B、C或同时作案,或与本案无关
5.C、D有且仅有一人作案
6.如果D没有参与作案,则E也不可能参与作案
试编一程序,将作案人找出来。
算法设计

条件的逻辑表示
1. A和B至少有一人作案 :
A||B
2. A、E、F三人中至少有2人参与作案:
(A&&E)||(A&&F)||(E&&F)
3. A、D不可能是同案犯:
!(A&&D)
4. B、C或同时作案,或与本案无关:
(B&&C)||(!B&&!C)
5. C、D有且仅有一人作案:
(C&&!D)||(D&&!C)
6. 如果D没有参与作案,则E也不可能参与作案:
(D||!E)
算法设计(续)

定义6个整型变量(布尔型也可)a、b、c、d、e、
f分别表示六个嫌疑人。变量值为0表示不是作案
人,为1表示是作案人。
– 每个人都有作案和没作案两种可能,共有64种可能。

穷举法
– 将64种情况一一去试,看哪一种情况符合破案的所有
六个条件。

算法实现:Exp5.cpp
课后作业
4.9、4.10~4.14、4.17、
4.22~4.23、4.29
进一步完善计算器:通过
选择结构实现四则运算,
并通过循环结构描述不考
虑优先级的连续运算,用
户输入等号为结束
THE END