- C++程序设计基础(上)
- 周霭如 林伟健编著
- 1136字
- 2020-08-28 09:48:04
第2章 程序控制结构
语句是程序的基本语法成分。程序设计语言的语句按功能可以分成三类:说明语句、操作语句和控制语句。
说明语句不是执行语句。说明语句有两个作用:一是用于定义,例如,变量说明语句用于定义变量名并指示编译器分配内存,类型说明语句用于定义数据的组织方式;二是用于声明程序连接信息,如函数原型、静态量、全局量说明语句等。因此,为了区分说明语句的不同性质,有时特别把功能不同的说明语句分别称为定义语句和声明语句。
操作语句用于描述对数据的处理。例如,表达式语句和输入/输出语句分别表示对数据的运算和传输。
控制语句用于控制程序的执行流程。所有程序都只能包含3种控制结构:顺序结构、选择结构和循环结构。顺序结构是系统预置的,即除非特别指定,计算机总是按指令编写的顺序一条一条地执行。选择结构和循环结构由特定语句组织。
本章讨论C++的选择结构语句和循环结构语句及其应用。
2.1 选择控制
实际编写程序时,有时需要对给定的条件进行判断,并根据判断的结果选择不同的操作。
例如,给定三条边的长度,判断能否构成三角形。若能构成三角形,则求其面积;否则,显示“不能构成三角形”的信息。
又如,求一元二次方程ax2+bx+c=0的根,要对b2-4ac作判断。当b2-4ac的值等于0时,求重根;大于0时,求两个实根;小于0时,求共轭复根。
构成选择结构的语句称为条件语句。C++使用if语句和switch语句构成选择结构。
2.1.1 if语句
1.if语句的形式和执行流程
if语句有两种形式:一个分支的if语句和两个分支的if_else语句。
(1)一个分支的if语句
语句形式为:
if(表达式)语句;
其中,“表达式”一般为逻辑表达式,表示执行条件。若为其他类型表达式,则C++也把其结果作为逻辑值处理。“语句”可以是一个简单语句,也可以是复合语句或其他结构语句。
if语句首先计算“表达式”的值,如果值为true(非0),则执行“语句”;否则,即“表达式”的值为 false(0),视“语句”为空,转向执行后续语句。执行流程如图2.1所示。例如:
图2.1 if语句的执行流程
if(x>0) cout<<x<<endl;
首先判断x的值是否大于0,若x的值大于0,则输出x的值并换行;否则不输出x的值。又如:
if ((a+b > c) && (b+c > a) && (c+a > b)) { s=(a+b+c)/2.0; area = sqrt(s * (s-a) * (s-b) * (s-c));
cout << "area = "<< area << endl; }
先计算逻辑表达式(a+b>c)&&(b+c>a)&&(c+a>b)的值,若为true,则按顺序执行花括号相括的复合语句;否则跳过该语句。
(2)if_else语句
语句形式为:
if(表达式)语句1 ; else 语句2 ;
其中,“表达式”一般为关系表达式或逻辑表达式,表示执行条件。“语句1”和“语句2”为简单语句、复合语句或其他结构语句。
if_else语句的执行情况如图2.2所示。例如:
图2.2 if_else语句的执行流程
if (x>y) cout << "max = "<< x << endl; else cout<<"max="<<y<<endl;
判断x是否大于y,若是,则输出x的值;否则,输出y的值。又如:
if ((a+b > c) && (b+c > a) && (c+a > b)) { s=(a+b+c)/2.0; area = sqrt(s * (s-a) * (s-b) * (s-c)); cout << "area = "<< area << endl; } else cout<<"It is not a trilateral."<<endl;
先计算逻辑表达式(a+b>c)&&(b+c>a)&&(c+a>b)的值,若为真,则按顺序执行花括号内的三个语句;否则,输出字符串“It is not a trilateral.”。
2.if语句的嵌套
if语句中的执行语句如果是另一个if语句,则称为嵌套if语句。例如:
if(x>0) y=x; else if(x<0) y=-x; else y=0;
当x<=0时,执行else分支,嵌套了另一个if语句,分别处理x<0和x==0的情况。又如:
if(score>=90) cout<<"Grade A:"; else if(score>=80) cout<<"Grade B:"; else if(score>=70) cout<<"Grade C:"; else if(score>=60) cout<<"Grade D:"; else cout<<"Grade E:";
也是if语句的嵌套。
if语句有不同的嵌套形式,但要注意 if 与 else 的配对关系。C++语言规定,else 总是与它接近的if 配对。上述两个语句可以添加括号表示等价的嵌套匹配关系,改写为:
if(x>0) {y=x;} else { if(x<0) y=-x; else y=0; }
和
if(score>=90) {cout<<"Grade A:";} else { if(score>=80){cout<<"Grade B:";} else { if(score>=70){cout<<"Grade C:";} else { if(score>=60){cout<<"Grade D:";} else {cout<<"Grade E:";} } } }
使用复合语句,可以改变条件语句的执行流程。例如,以下形式的语句:
if(表达式 0) 等价于: if(表达式 0) if(表达式 1) { if(表达式 1) 语句 1; 语句 1; else if(表达式 2) else 语句 2; { if(表达式 2) else 语句 2; 语句 3; else 语句 3; } }
“语句 1”的执行条件是“表达式 0 && 表达式 1”为true;
“语句 2”的执行条件是“表达式 0 &&!表达式 1 &&表达式 2”为true;
“语句 3”的执行条件是“表达式 0 &&!表达式 1 &&!表达式 2”为true。
使用花括号构造复合语句,可以改变条件语句的配对关系。例如,上述语句改写为:
if (表达式 0) { if(表达式 1) 语句 1; else if (表达式 2) 语句 2; } else 语句 3;
这时,“语句 3”的执行条件为“!表达式 0”,即“表达式 0”的值为false时执行“语句 3”。
3.应用举例
【例2-1】从键盘上输入3个整数,求这3个数中的最大值。
假设输入的3个数分别存储在变量a、b和c中,变量max存储最大值。求最大值的算法可以为:先比较a和b的值并把较大值赋给max;然后将c与max进行比较,若c>max,则把c赋给max。此时,max的值就是3个数中的最大值了。程序如下:
#include <iostream> using namespace std; int main() { int a,b,c,max; cout << "a, b, c = "; cin >> a >> b >> c; if(a>b) max=a; //求a,b之中的较大值,赋给max else max=b; if(c>max) max=c; //求max,c之中的较大值,赋给max cout << "max = " << max << endl; }
简单的条件语句,通常可以用条件运算代替。程序中的if语句:
if(a>b) max=a; else max=b;
可以写为: max = a>b ? a :b;
【例2-2】输入3条边的边长,若这3条边构成三角形就求该三角形的面积;否则,输出“不是三角形”的信息。
假设三角形的3条边的边长为a、b和c,则这3条边构成三角形的条件是:任意两条边之和都大于第三边。如果这3条边能构成三角形,则求三角形的面积公式为:
式中,s = (a + b + c) / 2。
按求三角形的面积公式,编写程序如下:
#include <iostream> #include<cmath> //包含声明数学函数的头文件 using namespace std; int main() { double a,b,c,s,area; cout << "a, b, c = "; cin>>a>>b>>c; //输入3条边长 if(a+b>c&&b+c>a&&c+a>b) //判断构成三角形的条件 { s=(a+b+c)/2.0; //计算面积 area = sqrt(s * (s-a) * (s-b) * (s-c)); cout << "area = " << area << endl; } else cout << "It is not a trilateral!" << endl; }
运行程序,输入数据后输出结果如下:
a, b, c = 5 6 7 area = 14.696939
在上述程序中,调用了C++标准库函数sqrt求平方根,函数原型为:
double sqrt(double x);
数学运算的标准函数声明在C的标准头文件cmath中,详见附录B。
【例2-3】把输入字符转换为小写字母。对输入字符进行判断,如果是大写字母,则转换为小写字母;否则,不转换。
#include <iostream> using namespace std; int main() { char ch; cout << "ch = "; cin >> ch; if(ch>='A'&&ch<='Z') //ch是大写字母 ch+=32; //转换成小写字母 cout << ch << endl; }
【例2-4】求一元二次方程ax2 + bx + c = 0的根。
求一元二次方程的根的公式为:
编程时,要考虑如下各种情况。
① 当a=0 时,方程不是二次方程;
② 当 b2-4ac=0 时,有两个相同的实根:;
③ 当 b2-4ac>0 时,有两个不同的实根:;
④ 当 b2-4ac<0 时,有两个共轭复根:。
按上述公式,编写程序如下:
#include<iostream> #include<cmath> using namespace std; int main()
{ double a,b,c,d,x1,x2,rp,ip; cout<<"a, b, c = "; cin>>a>>b>>c; //输入系数 if(fabs(a)<=1e-8) //用误差判断,系数a等于0 cout<<" It is not quadratic."<<endl; else { d=b*b-4*a*c; //求判别式的值,赋给d if(fabs(d)<=1e-8) //d等于0,方程有两个相同的根 cout<<"It has two equal real roots: "<<-b/(2*a)<<endl; else if(d>1e-8) //d大于0,方程有两个不同的实根 { x1=(-b+sqrt(d))/(2*a); x2=(-b-sqrt(d))/(2*a); cout<<"It has two distinct real roots: " <<x1 <<" and "<<x2<<endl; } else //d小于0,方程有两个共轭复根 { rp=-b/(2*a); ip=sqrt(-d)/(2*a); cout<<"It has two complex roots: "<<endl; cout<<rp<<" + "<<ip<<"i"<<endl; cout<<rp<<" - "<<ip<<"i"<<endl; } } }
程序中的条件:
fabs(a)<=1e-8 和 fabs(d)<=1e-8
分别用来判断a和d的值是否为0。因为实数在计算和存储时会有微小的误差。若用“a==0”和“d==0”来判断a和d是否为0,则可能出现本来a和d等于0,由于计算或存储误差而导致判断结果不成立的情况。
程序运行结果:
a, b, c = 0 2 1 It is not quadratic. a, b, c = 1 2 1 It has two equal real roots: -1 a, b, c = 1 5 1 It has two distinct real roots: -0.208712 and -4.791288 a, b, c = 2 3 4 It has two complex roots: -0.75 + 1.198958i -0.75 - 1.198958i
2.1.2 switch语句
switch语句应用于根据一个整型表达式的不同值决定程序分支的情况。
1.switch语句的形式和执行流程
switch语句形式为:
switch(表达式) { case 常量表达式 1 :语句 1 ; case 常量表达式 2 :语句 2 ; … case 常量表达式 n :语句 n; [default : 语句 n+1 ;] }
其中,“表达式”类型为整型、字符型或枚举型,不能为浮点型。“常量表达式”具有指定值,与“表达式”类型相同。default子句为可选项。
switch语句的执行流程如图2.3所示。
图2.3 switch语句的执行流程
在switch语句中,case和default只起语句标号作用。进入switch后,首先计算“表达式”的值,然后用这个值依次与case后的“常量表达式”的值进行比较。如果“表达式”的值等于某个“常量表达式 i”的值,则执行“语句 i”。如果“语句 i”之后还有语句,就继续执行“语句 i+1”至“语句 n+1”。如果找不到与“表达式”的值相等的case常量,则执行default指示的“语句 n+1”。
【例2-5】测试switch语句的执行流程。
#include <iostream> using namespace std; int main() { int x; cout << "x = "; cin >> x; switch(x) { case 1:cout<<"one "; case 2:cout<<"two "; case 3:cout<<"three "; default:cout<<"other "; } cout << "end" << endl; }
运行程序,若输入x的值为1,则输出结果如下:
x = 1 one two three other end
若重新运行,输入x的值为3,则输出结果如下:
x = 3 three other end
要实现真正的选择控制,执行一个case标号语句后能够跳出switch语句块,转向执行后续语句,应该使用break语句。break语句强制中断一个语句块的执行,转向执行语句块的后续语句。
【例2-6】测试在switch的执行语句中增加break语句,中断语句块。
#include <iostream> using namespace std; int main() { int x; cout << "x = "; cin >> x; switch(x) { case 1:cout<<"one "; break; case 2:cout<<"two "; break; case 3:cout<<"three "; break; default:cout<<"other "; } cout << "end" << endl; }
运行程序,输入x的值为2,输出结果如下:
x = 2 two end
选择性地在case语句中使用break语句,可以实现多个case常量值执行同一个分支语句。
【例2-7】两个case常量值执行同一个分支语句。
#include <iostream> using namespace std; int main() { int x; cout << "x = "; cin >> x; switch(x) { case 1: case 2:cout<<"one or two "; break; case 3:cout<<"three "; break; default:cout<<"other "; } cout << "end" << endl; }
程序不管x的输入值是1还是2,都执行case 2后的语句。输入1时,程序输出结果为:
x = 1 one or two end
switch语句的说明如下。
① 常量表达式必须互不相同,否则,会出现矛盾而引起错误。例如:
switch (int(x)) { case 1: y=1; break; case 2: y=x; break; case 2: y=x*x; break; //错误,case 2已经使用 case 3: y=x*x*x; break; }
② 各个case和default出现的次序可以任意。在每个case分支都带有break的情况下,case的顺序不影响执行结果。
③ switch语句可以嵌套。
2.应用举例
【例2-8】根据x的值,按下式计算y的值。
从这个分段函数的自变量 x取值可以看出,当1≤x<2时,int(x)=1;当2≤x<4时,int(x)等于2或3;当4≤x<6,int(x)等于4或5。因此,可以用switch语句编写程序。
#include <iostream> using namespace std; #include<cmath> int main() { double x,y; cout << "x = "; cin >> x; switch (int(x)) { case 1: y=3*x-5; break; case 2: case 3: y=2*cos(x)+1; break;
case 4: case 5: y=sqrt(1+x*x); break; default:y=x*x-4*x+5; } cout<<"y="<<y<<endl; }
运行程序3次,输入不同的x值,输出结果如下:
x = 1.5 y = -0.5 x = 3.3 y = -0.97496 x = 4.7 y = 4.80521
【例2-9】输入年份和月份,输出该月的天数。
根据天文知识,每年的1、3、5、7、8、10和12月,每月有31天;每年的4、6、9和11月,每月有30天;若是闰年,则2月份为29天;若为平年,则2月份为28天。年份能被4整除,但不能被100整除,或者年份能被400整除的年份为闰年;否则,为平年。
#include <iostream> using namespace std; int main() { int year,month,days; cout << "year : "; cin >> year; cout << "month : "; cin >> month; switch(month) { case 1:case 3:case 5:case 7:case 8:case 10:case 12: days=31; break; case 4: case 6: case 9: case 11: days=30; break; case 2: if((year%4==0)&&(year%100!=0)||(year%400==0)) days = 29; else days=28; } cout << " days : " << days << endl; }
运行程序,输入数据和输出结果如下:
year : 2008 month : 5 days : 31
【例 2-10】输入包含两个运算量和一个运算符(+、-、* 或 /)算术表达式,计算并输出运算结果。
#include <iostream> using namespace std; int main() { double operand1,operand2,result; char oper; cout << "input oprand1,operator and oprand2:"; cin>>operand1>>oper>>operand2; //输入表达式 switch(oper) //根据运算符做选择计算 { case'+': result=operand1+operand2; break; case'-': result=operand1-operand2; break; case'*': result=operand1*operand2; break; case'/': result=operand1/operand2; break; default: cout<<"input error!"<<endl; goto L; //非法运算符转向L入口的空语句
} cout << operand1 << oper << operand2 << "=" << result << endl; L:; //空语句 }
运行程序,输入数据和输出结果如下:
input oprand1,operator and oprand2: 2+6 2+6=8
当用户输入无效的运算符时,程序用goto语句转向标号为L的语句,而L指示的语句是一个空语句。goto语句的目的是在无效输入时,跳过正常的结果显示。