1.4 基本语句
C++融入了C语言的面向过程的结构化程序设计模式,因而它也可实现结构化程序设计中所需要的三种基本结构:顺序结构、选择结构和循环结构。
1.4.1 顺序语句和块
语句是描述程序操作的基本单位,是C++源程序的重要组成部分,每条语句均以分号(“;”)来结束,分号前面可以有0个或多个空格。 这里先讨论说明语句、表达式语句和块语句,它们是构成按书写顺序依次执行的顺序结构的主要语句。
1.说明语句
在C++中,把完成对数据结构的定义和描述、对变量或标识符常量的属性说明(如初值、类型等)称为说明语句或声明语句。说明语句的目的是用来在程序中引入一个新的标识符(变量名、函数名、数组名、类名、对象名、引用名及类型名等),本身一般不执行操作。
2.表达式语句
表达式语句是C++程序中最简单也是最常用的语句。任何一个表达式加上分号就是一个表达式语句,例如:
x + y; nNum = 5;
这里的“x+y;”是一个由算术运算符“+”构成的表达式语句,其作用是完成“x+y”的操作,但由于不保留计算结果,所以无实际意义。“nNum=5;”是一个由赋值运算符“=”构成的表达式语句,简称为赋值语句,其作用是改变nNum变量的值。
在书写格式上,可以将几个简单的表达式语句同时写在一行上,但此时的语句之间必须插入一些空格以提高程序的可读性。例如:
a=1; b=2; c=a+b;
此时3个赋值语句写在一行,各条语句之间需要增加空格。
如果表达式是一个空表达式,那么构成的语句称为空语句,也就是说,仅有分号也能构成一个语句,这个语句就是空语句。空语句不执行任何动作,根据语法的需要而设置。
3.块语句
块语句,简称为块(block),是由一对花括号“{ }”括起来的语句,又称为复合语句。例如:
{ // 块开始 int i=2,j=3,k=4; cout<<i<<j<<k<<endl; // 输出结果是2、3和4 } // 块结束
则是由两条语句构成的块语句。其中,左花括号“{”表示块的开始,右花括号“}”表示块的结束,它们是成对出现的。要注意,块中的语句书写时一定要缩进。
事实上,任何合法的语句都可以出现在块中,包括空语句。需要说明的是:
(1)从整体上看,块语句等效于一条语句。反过来说,若需要将两条或两条以上的语句作为一个整体单条语句时,则必须将它们用花括号括起来。
(2)块中的语句可以是0个、1个或多个。与空语句相类似,一个不含任何语句的块,即仅由一对花括号构成的块,称为空块,它也是仅为语法的需要而设置的,并不执行任何动作。
1.4.2 选择结构语句
选择结构是对给定条件进行判断,根据判断的结果(真或假)来决定执行两个分支或多个分支程序段中的一个分支。在C++中,用于构成选择结构的分支语句有if语句和switch语句,它们又称条件语句。
1.条件语句
条件语句if具有下列一般形式:
if (<表达式e>)<语句s1> [ else <语句s2> ]
这里的if和else是C++的关键字。注意,if后的一对圆括号不能省略。当表达式e为true或不为0时,将执行语句s1。当表达式e为false或0时,语句s2被执行。其中,else可以省略,即变成这样的简单的if语句:
if (<表达式e>)<语句s>
这样,只有当表达式e为true或不为0时,语句s才被执行。
【例Ex_Compare】 输入两个整数,比较两者的大小
#include <iostream.h> int main() { int nNum1, nNum2; cout<< "Please input two integer numbers: "; cin>>nNum1>>nNum2; if (nNum1!=nNum2) if (nNum1>nNum2) cout<<nNum1<< " > "<<nNum2<<endl; else cout<<nNum1<< " < "<<nNum2<<endl; else cout<<nNum1<< " = "<<nNum2<<endl; return 0; }
程序运行结果如下:
Please input two integer numbers: 10 123↵
10 < 123
需要注意的是:
(1)条件语句中的表达式一般为逻辑表达式或关系表达式,如程序中的nNum1> nNum2。当然,表达式的类型也可以是任意的数值类型(包括整型、实型、字符型等)。例如:
if (3) cout<<"This is a number 3";
执行结果是输出"This is a number 3";因为3是一个不为0的数,条件总为“真”。
(2)适当添加花括号“{ }”来增加程序的可读性。例如:上面【例Ex_Compare】中的条件语句还可写成下列形式,其结果是一样的。
if (nNum1!=nNum2) { if (nNum1>nNum2) cout<<nNum1<<" > "<<nNum2<<endl; else cout<<nNum1<<" < "<<nNum2<<endl; } else cout<<nNum1<<" = "<<nNum2<<endl;
(3)如果在if和esle后有多条语句(复合语句),则必须用花括号将这些语句括起来,否则只有后面的第一条语句有效。例如:
if (nNum1>nNum2) cout<<nNum1<<">"<<nNum2; // 此句是if后面的有效语句 cout<<endl; // 此句无论if表达式是否为真都会执行
(4)条件语句中的语句s、语句s1和语句s2也可以是if条件语句,这就形成了if语句的嵌套。例如,程序中if (nNum1!=nNum2)后面的语句也是一个if条件语句。
(5)else不能单独使用,它总是和其前面最近的未配套的if相配套。例如,程序中的第1个else属于第2个if,而第2个else是属于第1个if的。
2.开关语句
当程序有多个判断条件时,若使用if语句则可能使嵌套太多,降低程序的可读性。开关语句switch能很好地解决这种问题,它具有下列形式:
switch (<表达式e>) { case <常量表达式v1> :[语句s1] case <常量表达式v2> :[语句s2] ... case <常量表达式vn> :[语句sn] [default :语句sn+1] }
其中switch、case、default都是关键字,当表达式e的值与case中某个常量表达式的值相等时,就执行该case中冒号“:”后面的所有语句,直至遇到break语句跳出。若case中所有常量表达式的值都不等于表达式e的值,则执行“default:”后面的语句,若default省略,则跳出switch结构。需要注意的是,switch后面的表达式e可以是整型、字符型或枚举型的表达式,而case后面的常量表达式的类型则必须与其相匹配。
【例Ex_Switch】 根据成绩的等级输出相应的分数段
#include <iostream.h> int main() { char chGrade; cout<<"Please input a char(A~E): "; cin>>chGrade; switch(chGrade) { case 'A': case'a': cout<<"90--100"<<endl; break; case 'B': case'b': cout<<"80--89"<<endl; break; case 'C': case'c': cout<<"70--79"<<endl; case 'D': case'd': cout<<"60--69"<<endl; case 'E': case'e': cout<<"<60"<<endl; default: cout<<"error!"<<endl; } return 0; }
运行时,当用户输入A时,则运行结果如下:
Please input a char(A~E): A↵
90--100
但当用户输入d时,则运行结果如下:
Please input a char(A~E): d↵
60--69
< 60
error!
显然,这不是想要的结果,而应该只输出60--69。仔细比较这两个结果可以发现,“case 'a':”后面含有break语句,而“case 'd':”后面则没有。由于break语句能使系统跳出switch结构,因此当系统执行“case 'a':”后面的语句“cout<<"90--100"<<endl;”后,break语句使其跳出switch结构,以保证结果的正确性;若没有break语句,则后面的语句继续执行,直到遇到下一个break语句或switch结构的最后一个花括号“}”为止才跳出该结构。因此,break语句对switch结构有时是不可缺少的(后面还会专门讨论)。
另外,还需注意的是:
(1)多个case可以共有一组执行语句,如程序中的:
case 'B': case'b': cout<<"80--89"<<endl; break;
这时,当用户输入B或b时将得到相同的结果。
(2)若同一个case后面的语句是复合语句,即有两条或两条以上的语句,则这些语句可以不用花括号“{ }”括起来。
(3)由于case语句起标号作用,因此每一个case常量表达式的值必须互不相同,否则会出现编译错误。
1.4.3 循环结构语句
构成循环结构的循环语句提供了重复操作的能力,当指定的循环条件为true时,循环体中的语句就会被重复执行,并且每循环一次,就会测试一下循环条件,如果为false,则循环结束,否则继续循环。C++为循环结构提供了三种形式的循环语句:while、do…while和for语句。这些循环语句的功能是相似的,在许多情况下它们可以相互替换,唯一区别是它们控制循环的方式。
1.while语句
语句具有下列格式:
while(<表达式e>) <语句s>
其中,while是C++的关键字,语句s是循环体,它可以是一条语句,也可以是多条语句。当为多条语句时,一定要用花括号“{ }”括起来,使之成为块语句,如果不加花括号,则while的循环体s只是紧跟while (e)后面的第1条语句。当表达式e为true或不为0时便开始执行while循环体中的语句s,然后反复执行,每次执行都会判断表达式e是否为true或不为0,若为false或为0,则终止循环。
【例Ex_SumWhile】 求整数1~50的和
#include <iostream.h> int main() { int nNum=1, nTotal=0; while (nNum<=50) { nTotal += nNum; nNum++; } cout<<"The sum from 1 to 50 is: "<<nTotal<<"\n"; return 0; }
程序运行结果如下:
The sum from 1 to 50 is: 1275
需要说明的是,对于循环结构来说,循环体中一定要有使循环趋向结束的语句。比如上述示例中,nNum的初值为1,循环结束的条件是不满足nNum<=50,随着每次循环都改变nNum的值,使得nNum的值也越来越大,直到nNum>50为止。如果没有循环体中的“nNum++;”,则nNum的值始终不改变,循环永不终止。
2.do…while语句
语句具有下列格式:
do <语句s> while (<表达式e>) ;
其中do和while都是C++关键字,语句s是循环体,它可以是一条语句,也可以是块语句。程序从do开始执行,然后执行循环体语句s,当执行到while时,将判断表达式e是否为true,若是,则继续执行循环体语句s,直到下一次表达式e等于false为止。要注意,while后面的表达式e两边的圆括号不能省略,且表达式e后面的分号不能漏掉。
【例Ex_SumDoWhile】 求整数1~50的和
#include <iostream.h> int main() { int nNum=1, nTotal=0; do { nTotal+=nNum; nNum++; } while (nNum<=50); cout<<"The sum from 1 to 50 is: "<<nTotal<<"\n"; return 0; }
由于程序总是自上而下地顺序运行(除非遇到if、while等流程控制语句),因此do语句中的循环会先执行,这样sum值为1,i为2。然后判断while后面的“(i<=50)”是否为true,若是,则流程转到do循环体中,直到“(i<=50)”为false。
程序运行结果如下:
The sum from 1 to 50 is: 1275
从上述例子中可以看出:
(1)do…while循环语句至少执行一次循环体,而while循环语句可能一次都不执行。
(2)从局部来看,while和do…while循环都有“while (表达式e)”。为区别起见,对于do…while循环来说,无论循环体是单条语句还是多条语句,习惯上都要用花括号将它们括起来,并将“while (表达式e);”直接写在右花括号“}”的后面,如【例Ex_SumDoWhile】中的格式。
3.for语句
语句具有下列格式:
for ([表达式e1]; [表达式e2]; [表达式e3]) <语句s>
其中for是C++的关键字,语句s是循环体,它可以是一条语句,也可以是块语句。一般情况下,表达式e1用做循环变量的初始化,表达式e2用做循环体的循环条件,当其为true时,开始执行循环体语句s,然后计算表达式e3,再判断表达式e2的值是否为true,若是,再执行循环体s,再计算表达式e3,如此反复,直到表达式e2为false或0为止。如图1.7所示,图中箭头表示程序运行的方向,称为流向,程序运行的次序称为流程,这样的图称为流程图。下面用for语句来改写【例Ex_SumDoWhile】中的代码。
图1.7 for语句的流程
【例Ex_SumFor】 求整数1~50的和
#include <iostream.h> int main() { int nTotal=0; for (int nNum=1; nNum<=50; nNum++) nTotal += nNum; cout<<"The sum from 1 to 50 is: "<<nTotal<<"\n"; return 0; }
程序运行结果如下:
The sum from 1 to 50 is: 1275
需要说明的是:
(1)由于表达式e1用做循环变量的初始化,因此也可将循环变量的定义放在表达式e1中进行,如代码中for语句的“int nNum=1”。但此时nNum的作用范围仅限于for循环结构中,这是ANSI/ISO C++中的新规定。但在Visual C++ 6.0中,nNum的作用范围和在for前面定义的变量(如nTotal)的作用范围是一样的。
(2)表达式e1、表达式e2和表达式e3可以是一个简单的表达式,也可以是逗号表达式,即包含两个或两个以上的简单表达式,中间用逗号分隔。例如:
for(nNum=1,nTotal=0;nNum<=50;nNum++) nTotal+=nNum;
(3)循环体s中的语句也可以是一条空语句,这样的循环往往用于时间延时。例如:
for(int i=0;i<10000;i++) ; // 注意后面的分号表示一条空语句
(4)实际运用时,for循环还有许多变化的形式,这些形式都是将for后面括号中的表达式e1、表达式e2、表达式e3进行部分或全部省略,但要注意起分隔作用的分号“;”不能省略。常见的省略形式有下列几种:
① 若省略表达式e1,不影响循环体的正确执行,但循环体中所需要的一些变量及其相关的数值要在for语句之前定义。例如:
int nNum=1; for(;nNum<=50;nNum++) nTotal+=nNum;
② 若省略表达式e2,则默认的表达式e2的值被认为true,循环无终止地进行下去,应在循环体中添加额外代码使之有跳出或终止循环的可能。例如:
for(int nNum=1; ;nNum++) { nTotal += nNum; if (nNum>50)break; // 当nNum>50时,执行break语句,跳出循环 }
③ 若省略表达式e3,应在设计循环结构时保证表达式e2的值有等于false的可能,以便能终止循环。例如:
for (int nNum=1; nNum<=50 ;) { nTotal+=nNum; nNum++; }
④ 若省略表达式e1和表达式e3,则相当于while循环。例如:
⑤ 若表达式全部省略,例如:
int nNum=1; for ( ; ; ) { nTotal+=nNum; nNum++; if (nNum>50) break; }
则循环体中所需要的一些变量及其相关的数值要在for语句之前定义,如“int nNum = 1;”,且应在循环体中添加额外代码使之有跳出或终止循环的可能,如“if (nNum>50) break;”。
(5)由于循环体可由任何类型的语句组成,因此在循环体内还可以包含前面几种循环语句,这样就形成了循环的嵌套。例如:
for(…; …; …) { while (…) { } } while (…) { for(…; …; …) { } }
以上是C++几种类型的循环语句,使用时可根据实际需要进行适当选择。但不管是怎样的循环结构,在编程时应保证循环有终止的可能。否则,循环永不结束,就像“死机”一样。
1.4.4 break和continue语句
在C++程序中,若需要跳出循环结构或提前结束本次循环,就需要使用break和continue语句,其格式如下:
break; continue;
break语句用于强制结束switch结构(如【例Ex_Switch】)或从一个循环体跳出,即提前终止循环。要注意,break仅使流程跳出其所在的最近的那一层循环或switch结构,而不是跳出所有层的循环或switch结构。
continue适用于那些依靠条件判断而进行循环的循环语句,如for、while、do…while语句,它的目的是提前结束本次循环。对于while和do…while语句来说,continue提前结束本次循环后,流程转到while后面的表达式e。对于for语句来说,continue提前结束本次循环后,其流程转到for语句的表达式e3,然后转到表达式e2。
【例Ex_Continue】 将1~100之间不能被7整除的数输出
#include <iostream.h> int main() { for (int nNum=1; nNum<=100; nNum++) { if (nNum%7 == 0) continue; cout<<nNum<<" "; } cout<<"\n"; return 0; }
当nNum能被7整除时,执行continue语句,流程转到for语句中的nNum++,并根据表达式nNum<=100的值来决定是否再做循环。而当nNum不能被7整除时,才执行cout<<nNum<<""语句。
程序运行结果如下:
1 2 3 4 5 6 8 9 10 11 12 13 15 16 17 18 19 20 22 23 24 25 26 27 29 30 31 32 33 34 36 37 38 39 40 41 43 44 45 46 47 48 50 51 52 53 54 55 57 58 59 60 61 62 64 65 66 67 68 69 71 72 73 74 75 76 78 79 80 81 82 83 85 86 87 88 89 90 92 93 94 95 96 97 99 100