Part2:程序控制结构
2.1 结构化程序设计基础
- 定义
程序的控制结构就是一个黑箱子。单入口单出口的控制结构易于理解 - 三种基本控制结构
1.顺序结构
**
顺序结构示例
编写程序,接受用户输入的两个整数,输出其中较大者
#include <iostream>
using namespace std;
int main()
{
int a, b, max;
/* 输入部分 */
cout << "The program gets two numbers and prints the greater one.\n";
cout << "The first number: ";
cin >> a;
cout << "The second number: ";
cin >> b;
/* 计算部分 */
max = a > b ? a : b; /* 三元表达式 */
/* 输出部分 */
cout << "The greater one is " << max << "." << endl;
return 0;
}
2.分支结构
3.循环结构
- 复杂控制结构
2.2 布尔数据
枚举类型
- 枚举类型的声明
格式:enum 枚举名 { 元素名1, 元素名2, …, 元素名n };
例:enum MONTH{ JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
默认第一个元素值为0
枚举类型声明中的元素为枚举文字,不是变量 - 枚举类型变量的定义
例:MONTH month;//MONTH为枚举名,month为枚举类型变量名
- 枚举类型的意义
将多个文字组织在一起,表达从属于特定类型的性质,使源代码更易理解
用户自定义类型
- 自定义类型的格式
格式:typedef 原类型标识 新类型名;
例一:typedef int DWORD;
- 自定义类型的性质
新类型与原类型相同,并未产生新类型,重新命名的自定义类型使程序更易理解
若整数可以用于表示两类不同数据对象,使用自定义类型可以区分它们
自定义类型不是简单的类型替换,虽然它们确实等同
布尔类型
- bool 类型 适用于C++
取值:false、true
- bool 量的定义
定义:bool modified;
赋值:modified = true;
关系表达式
- 关系操作符
大于(>)、等于(==)、小于(<)、不大于(<=)、不小于(>=)、不等于(!=) - 关系表达式
关系操作符与两个操作数构成的表达式
关系表达式
多个关系表达式可连接起来构成复杂关系表达式
运算结果为逻辑值:真或假 - 逻辑值(布尔值)
C/C++ 语言以 0 表示假,以非 0 表示真(经常以 1 表示)
尽量使用 bool 类型表示逻辑值
逻辑表达式
- 逻辑操作符:逻辑与(
&&
)、逻辑或(||
)、逻辑非(!
) - 逻辑表达式
逻辑操作符与一个或两个操作数构成的表达式,结果仍为真或假
x && y
:若 x、y 均为真,则结果为真,否则为假
x || y
:若 x、y 均为假,则结果为假,否则为真
!x
:若 x 为真,则结果为假,否则为真 - 复杂逻辑表达式
例:x > y || a != b && 3 <= 2
- 关系操作符与逻辑操作符的优先级
从高到低顺序:
逻辑非“!”;小于“<”、不小于“>=”、大于“>”、不大于“<=”(同级);
等于“==”、不等于“!=”(同级);
逻辑与“&&”;逻辑或“||”
2.3 分支结构
if分支结构
-
If 分支结构的三种格式
格式一:if( 条件表达式 ) { 语句序列 }
格式二:if( 条件表达式 ) { 语句序列 1 } else { 语句序列 2 }
格式三:if( 条件表达式 1 ) { 语句序列 1 } else if( 条件表达式 2 ) { 语句序列 2 } … else { 语句序列 n }
-
特别说明
条件表达式必须位于括号内,一般为关系或逻辑表达式
先计算条件表达式值,若为真则执行语句序列 1,否则执行语句序列 2
语句序列 1 与语句序列 2 可以为复合语句、单语句或空语句
语句序列 1 与语句序列 2 只能有一个被执行
若仅用于确定某条语句是否执行,else 分支可以省略 -
简单if语句 实例:编写程序,接受用户输入的整数,如果该整数为奇数则将其乘 3 加 1 后输出,偶数直接输出
#include <iostream>
using namespace std;
int main(){
int input;
int output;
cout << "Input a number: ";
cin >> input;
output = input;
if (input%2!=0){
output = input * 3 + 1;
}
cout << output << endl;
return 0;
}
运行结果
Input a number: 8
8
Input a number: 15
46
- if-else 语句 实例:接受用户输入的整数,如果该整数为奇数则将其乘 3 加 1 后输出,偶数除以 2 后输出
#include <iostream>
using namespace std;
int main(){
int input;
int output;
cout << "Input a number: ";
cin >> input;
output = input;
if (input%2!=0){
output = input * 3 + 1;
}
else{
output = input/2;
}
cout << output << endl;
return 0;
}
运行结果:
Input a number: 9
28
Input a number: 10
5
- if-else if-else 语句 实例:已知2006年12月1日为星期五。编制程序,接受用户输入的1~31之间的整数,按照下述格式将该日星期几信息打印在对应栏下。例如,2006年12月1日打印在星期五“Fr”下面:
#include <iostream>
#include <iomanip>//Table
using namespace std;
int main(){
int input;
int date;
int cal;
//enum WEEKDAY{Sun,Mon,Tue,Wed,Thu,Fri,Sat};//Sun = 0
enum WEEKDAY{Thu,Fri,Sat,Sun,Mon,Tue,Wed};//Fri=1
WEEKDAY weekday;
cout << "Input the DATE(1~31): ";
cin >> input;
date = input;
cout << "In printing: 2006-12 Calendar "<< endl;
if(date<1||date>31){
cout << "ERROR DATE!!!!" <<endl;
return 1;
}
cal = date % 7;
weekday = (WEEKDAY)cal;
cout<<"Calendar 2006-12\n";
cout<<"------------------\n";
cout<<"Su Mo Tu We Th Fr Sa\n";
if (weekday == Sun){
cout << setw(2)<< date;
}
else if(weekday == Mon){
cout << setw(5)<< date;
}
else if(weekday == Tue){
cout << setw(8)<< date;
}
else if(weekday == Wed){
cout << setw(11)<< date;
}
else if(weekday == Thu){
cout << setw(14)<< date;
}
else if(weekday == Fri){
cout << setw(17)<< date;
}
else{
cout << setw(20)<< date;
}
cout << endl;
return 0;
}
运行结果1:
Input the DATE(1~31): 0
In printing: 2006-12 Calendar
ERROR DATE!!!!
运行结果2:
Input the DATE(1~31): 33
In printing: 2006-12 Calendar
ERROR DATE!!!!
运行结果3:
Input the DATE(1~31): 1
In printing: 2006-12 Calendar
Calendar 2006-12
------------------
Su Mo Tu We Th Fr Sa
1
运行结果4:
Input the DATE(1~31): 8
In printing: 2006-12 Calendar
Calendar 2006-12
------------------
Su Mo Tu We Th Fr Sa
8
运行结果5:
Input the DATE(1~31): 27
In printing: 2006-12 Calendar
Calendar 2006-12
------------------
Su Mo Tu We Th Fr Sa
27
运行结果6:
Input the DATE(1~31): 30
In printing: 2006-12 Calendar
Calendar 2006-12
------------------
Su Mo Tu We Th Fr Sa
30
switch 分支结构
- 计算过程
先计算表达式的值
依次与常数表达式比较
若相同则执行该分支(子句)
否则转向 default 分支
最后退出 switch 语句 - 表达式
switch( 表达式 )
{
case 常数表达式 1: 语句序列 1
case 常数表达式 2: 语句序列 2
┇
case 常数表达式 n: 语句序列 n
default: 默认语句序列
}
-
执行流程
-
特别说明
switch 后面的表达式必须为整型、字符型或枚举型
case 后面必须为常量表达式,且各个 case 值必须不同
若无 default 分支,且无 case 分支匹配,则不执行
case 分支中的语句可以有多条,不需要花括号 -
上面计算日期用switch代码表示
#include <iostream>
#include <iomanip>//Table
using namespace std;
int main(){
int input;
int date;
int cal;
//enum WEEKDAY{Sun,Mon,Tue,Wed,Thu,Fri,Sat};//Sun = 0
enum WEEKDAY{Thu,Fri,Sat,Sun,Mon,Tue,Wed};//Fri=1
WEEKDAY weekday;
cout << "Input the DATE(1~31): ";
cin >> input;
date = input;
cout << "In printing: 2006-12 Calendar "<< endl;
if(date<1||date>31){
cout << "ERROR DATE!!!!" <<endl;
return 1;
}
cal = date % 7;
weekday = (WEEKDAY)cal;
cout<<"Calendar 2006-12\n";
cout<<"------------------\n";
cout<<"Su Mo Tu We Th Fr Sa\n";
switch (weekday)
{
case Sun:
cout << setw(2)<< date;
break;
case Mon:
cout << setw(5)<< date;
break;
case Tue:
cout << setw(8)<< date;
break;
case Wed:
cout << setw(11)<< date;
break;
case Thu:
cout << setw(14)<< date;
break;
case Fri:
cout << setw(17)<< date;
break;
case Sat:
cout << setw(20)<< date;
break;
default:
break;
}
cout << endl;
return 0;
}
2.4 break 语句
- break 语句的目的
终止 switch 语句的执行
如果没有 break 语句,则程序会从指定的 case 分支开始,并在该分支结束后继续执行下去
除非 switch 语句结束,后面的其他 case 分支或 default 分支中的语句都会得到执行
原因:case 子句中的常数表达式仅起到语句标号的作用,不是分支之间的分隔标记 - 省去break 语句的场合
允许多个分支执行同样的代码
2.5 循环结构
while 循环
- while 循环格式:
while ( 表达式 ) 循环体
- while 循环执行流程
先判断后执行:表达式为真时,执行一遍循环体(一次迭代),返回重新计算表达式的值以确定是否重复执行循环体;若表达式为假,则终止循环
为保证循环终止,循环体内应有能改变表达式值的语句
- while 循环示例:编写程序,接受用户输入的多个整数求和,用户输入0时程序结束
#include <iostream>
using namespace std;
int main(){
int input;
int sum=0;
cout <<"Input some integers, I will help you to get their sum."<< endl;
cout << "If you want to quit the program, please input 0 " << endl;
cin >> input;
while(input!=0){
sum += input;
cout<< "Go continue: " << endl;
cin >> input;
}
cout << "The sum is : " << sum << endl;
return 0;
}
运行结果:
Input some integers, I will help you to get their sum.
If you want to quit the program, please input 0
4
Go continue:
7
Go continue:
0
The sum is : 11
无限循环
- 发生无限循环的场合
循环体内没有改变循环变量值的语句
即使改变循环变量值,也不能否定循环条件
循环体内没有能够强制终止循环执行的语句或命令 - 无限循环的后果
程序永远不会结束,大多数时有害,编程时一般应避免
例外情况:循环体内有专门控制循环终止的语句或命令
命令格式:满足某种条件下使用 break 语句,终止循环执行
哨兵:使循环满足终止条件的循环变量值
使用 break 语句终止循环
cout << "If you want to quit the program, please input 0";
while( true )
{
cout << "Please input an integer: ";
cin >> n;
if( n == 0 )
break;
sum += n;
}
- 使用无限循环和哨兵的优势
不再需要将首个数据处理过程提到循环体前单独处理
for 循环结构
-
递增递减表达式
递增递减表达式的优先级非常高 -
前缀递增递减
格式:++变量名称; --变量名称;
例一:设 a 为 1,++a 等价于 a = a + 1,a 结果为 2
例二:设 a 为 1,--a 等价于 a = a - 1,a 结果为 0
计算要诀:先递增递减,再参与运算
例三:设 a 为 1,b = ++a * 3 等价于 a = a + 1; b = a * 3,a 结果为 2, b 结果为 6
例四:设 a 为 1,b = --a * 3 等价于 a = a - 1; b = a * 3,a 结果为 0, b 结果为 0
-
后缀递增递减
格式:变量名称++; 变量名称--;
例一:设 a 为 1,a++ 等价于 a = a + 1,a 结果为 2
例二:设 a 为 1,a-- 等价于 a = a - 1,a 结果为 0
计算要诀:先参与运算,再递增递减
例三:设 a 为 1,b = a++ * 3 等价于 b = a * 3; a = a + 1,a 结果为 2, b 结果为 3
例四:设 a 为 1,b = a-- * 3 等价于 b = a * 3; a = a - 1,a 结果为 0, b 结果为 3
-
注意事项
操作数必须为变量,而不能为其他表达式
不要在复杂表达式中使用递增递减操作符 -
for 语句 循环格式
for( 初始化表达式; 条件表达式; 步进表达式 ) 循环体
-
for 循环执行流程
先判断后执行:先执行初始化表达式,再计算条件表达式,并根据其结果决定是否执行一遍循环体(为真时执行),计算步进表达式的值(循环再次“初始化”),返回重新计算条件表达式的值以确定循环是否终止
-
for 循环示例: 编写程序,接受用户输入的整数 n,求 1 ~ n 的平方和
#include <iostream>
using namespace std;
int main(){
int i,n;
int sum = 0;
cout << "Please input an integer: \n";
cin >> n;
for(i=1;i<=n;i++){
sum += i*i;
}
cout << "The sum is: " << sum << endl;
return 0;
}
运行结果:
Please input an integer:
4
The sum is: 30
for 与 while 的比较
- 两种循环结构可以互换使用
- while 循环常用于不需要或很少需要初始化的场合
- for 循环常用于需要简单初始化和通过递增递减运算控制循环体执行的场合
- for 循环将所有循环控制因素都放在循环头部,循环结构最清晰
- 通过省略循环头部的一个或多个表达式,for 循环也可能非常复杂
循环嵌套
编写程序,按下述格式打印九九乘法表
2.6 编程实践
- 1 使用循环结构打印带有"*"的正反等边三角形,三角形行数n由用户输入。
两个三角形中间间隔空格字符数m也由用户输入。
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int m,n;
int t;
int i,j,k,l;
int a,b;
cout << "How many lines of * do you want to print?\n";
cin >> n;
cout << "How many space do you want to print?\n";
cin >> m;
for(i=1;i<=n;i++){
a = 2*i-1; //The '*' counts in each line on left
t = n-i; //The ' ' counts in each line on left
b = 2*n-a; //The '*' counts in each line on right
/*For the LEFT*/
for (j=1;j<=t;j++){
cout << " ";
}
for (k=1;k<=a;k++){
cout << "*";
}
cout << setw(m);
/*For the RIGHT*/
for(l=1;l<=b;l++){
cout << "*";
}
/*Next line*/
cout << endl;
}
return 0;
}
运行结果:
How many lines of * do you want to print?
5
How many space do you want to print?
4
* *********
*** *******
***** *****
******* ***
********* *
- 2.打印某年某月的日历:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int i,j,date;
enum WEEKDAY{Th,Fr,Sa,Su,Mo,Tu,We};
WEEKDAY weekday;
cout << "Calendar 2016-01" << endl;
cout << "---------------------------\n";
cout << "Su Mo Tu We Th Fr Sa" << endl;
cout << "---------------------------\n";
cout << setw(22) << 1;
cout << setw(4) << 2 << endl;
for (j = 0; j < 4; j++) {
for (i = 3; i <= 9; i++) {
weekday = WEEKDAY((7*j+i) % 7);
switch (weekday)
{
case(Su):cout << setw(2) << (7 * j + i);
break;
case(Mo):cout << setw(4) << (7 * j + i);
break;
case(Tu):cout << setw(4) << (7 * j + i);
break;
case(We):cout << setw(4) << (7 * j + i);
break;
case(Th):cout << setw(4) << (7 * j + i);
break;
case(Fr):cout << setw(4) << (7 * j + i);
break;
case(Sa):cout << setw(4) << (7 * j + i);
break;
default:
break;
}
}
cout << endl;
}
cout << setw(2) << 31 << endl;
cout << "---------------------------\n";
return 0;
}
运行结果:
Calendar 2016-01
---------------------------
Su Mo Tu We Th Fr Sa
---------------------------
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
---------------------------