2.3 初识语句
语句 是 依序执行 的 C++ 程序片段。当多个语句被排列在一起时,它们会按照从前往后的顺序依次执行。
在编译器处理语句的时候,换行符如同空格一样,当做空白字符处理。因此,换行符不会影响语句的语义。
表达式语句简单来说就是一个表达式后面跟着一个分号 ;。例如:
a = 1;a = b, b = c, c = a;表达式语句的执行就是计算表达式的值,然后抛弃这个值。表达式语句的主要作用是表达式的副作用,例如利用赋值表达式修改对象的值。
如果表达式语句的表达式是空的,那么这个表达式语句也称为空语句。例如:
;在前面的章节中,我们已经大概介绍了声明的形式。现在我们可以把声明称为声明语句。
在声明中,介绍了声明语句的形式是:类型 标识符; 或者 类型 标识符 初始化器;。
在表达式中,介绍了声明语句的形式是:类型 初始化声明, 初始化声明, 初始化声明 ... ;。
下面是一些声明语句的例子:
int a; // 声明并创建一个整数类型的对象 aint b = 42; // 声明并创建一个整数类型的对象 b,并初始化为整数值 42int c, d = 1, e = 2; // 声明并创建整数类型的对象 c、d、e,并初始化 d 为 1,e 为 2复合语句是由花括号 {} 包围的语句序列。复合语句可以包含任意数量的语句,也可以嵌套在其他复合语句中。
我们可以简单地为表达式语句的例子添加花括号,就得到了复合语句的例子:
{ a = 1; int b = a + 1; int c = a * b; a = b, b = c, c = a;}这里,{} 包围的部分就是一个复合语句,里面包含了四个语句:a = 1;、int b = a + 1;、int c = a * b;、a = b, b = c, c = a;。
复合语句里面可以包含所有种类的语句,包括带标号语句、表达式语句、复合语句等。
在复合语句内,只能出现语句序列,而如下的代码是错误的:
{ int a = 1; b = 3}这里,b = 3 没有 ; 结尾,只是一个表达式而非语句,编译器一般会报错。
带标号语句的形式是
label statement这里 label 是一个标号,statement 是一个语句。标号的结尾总是一个冒号 :,标号后面的语句可以是任意一种语句。
标号语句的执行就是执行标号后面的语句,前面的标号在这时没有实际作用。
标号的形式是:
- 标识符跟着一个冒号
:,例如label: case value:,其中value是一个表达式default:
label: a = b, c = 3;good: { a = 1; b = 2;}标号语句会用于 switch 语句中,用来表达程序的跳转目标。
在关键字一节中提到了 if、break、else、switch 等关键字,这些关键字用于构造选择语句。
if 语句的形式是:
if (condition) statement或者
if (condition) statementelse statement这里 condition 是一个表达式,用来表达选择条件,statement 是一个语句,用来表达选中时执行的操作。包围 condition 的括号是 if 语句的一部分,不可省略。
if 语句的执行流程是:
- 计算
condition的值。 - 将
condition的值转换为bool。 - 如果上一步的结果为
true,则执行statement;否则,执行else后面的statement。
举例而言,if 语句可以像这样使用:
if (a > b) max = a;else max = b;在上面的代码中,如果 a 大于 b,则将 a 的值赋给 max;否则,将 b 的值赋给 max。
此外,在 if 的 condition 之前,可以加入一个初始化语句,例如:
if (int a = 1; a > b) max = a;else max = b;这和下面的代码是等价的:
{ int a = 1; if (a > b) max = a; else max = b;}在这里,先声明并初始化了一个整数类型的对象 a,然后执行了后面的 if 语句。
switch 语句
Section titled “switch 语句”switch 语句的形式是:
switch (condtion) statement这里 condtion 是一个表达式,用来表达选择条件,statement 是语句,表示 switch 需要控制执行的语句。
读者可能会奇怪,这后面只有一个 statement,这个选择语句在选择什么呢?实际上,switch 语句规定了,在 switch 语句中的任何一个语句,可以使用 case 或者 default 标号,组成标号语句。
这意味着 switch 后面的 statement 往往是一个复合语句,里面包含了多个 case 标号语句和 default 标号语句。
举例而言,switch 语句可以像这样使用:
switch (a) { case 1: as = 1; break; case 2: as = 4; break; case 3: as = 9; break; default: as = 0;}在这里,switch 语句的 statement 是一个复合语句,里面包含了三个 case 标号语句和一个 default 标号语句。当 a 的值为 1 时,执行 as = 1;,然后结束 switch 语句;当 a 的值为 2 时,执行 as = 4;,然后结束 switch 语句;当 a 的值为 3 时,执行 as = 9;,然后结束 switch 语句;当 a 的值不是 1、2、3 时,执行 as = 0;,然后我们来到了这个 switch 语句的结尾。
switch 语句的执行过程是:
- 计算
condtion的值。 - 比较
condtion的值和switch语句中case标号语句后面的value的值。- 如果存在
condtion的值和某个case后面的value的值相等,则从这个case语句开始依次执行。 - 如果找不到
condtion的值和任何case后面的value的值相等,则从default标号语句开始执行。
- 如果存在
- 如果执行到
break;语句,则结束switch语句的执行。
这里, break; 也是一种语句,称为跳转语句,它用于多种语句结构中,switch 语句中的 break; 用于结束 switch 语句的执行。
此外,在 switch 的 condition 之前,可以加入一个初始化语句,例如:
switch (int b = 2; a) { case 1: as = b; break; case 2: as = b * 4; break; default: as = 0;}这和下面的代码是等价的:
{ int b = 2; switch (a) { case 1: as = b; break; case 2: as = b * 4; break; default: as = 0; }}这里,先声明并初始化了一个整数类型的对象 b,然后执行了后面的 switch 语句。
多层选择结构
Section titled “多层选择结构”if 语句中出现的 statement 当然也可以是 if 语句。多个 if 语句可以嵌套在一起,形成如下的多层选择结构:
if (condition1) if (condition2) statement2 else statement2_elseelse if (condition3) statement3 else if (condition4) statement4 else statement4在多个条件并列时,我们也可以把连用的 else 和 if 理解成一个整体,称为 else if,这样可以使代码更加简洁:
if (condition1) statement1else if (condition2) statement2else if (condition3) statement3else statement4对于switch语句,在常见的设计中,我们希望 switch 语句在执行完一个 case 标号语句后就结束。这时我们需要在每个 case 标号语句后面加上 break; 语句,就像前面的例子那样。但有的时候我们需要作出更复杂的选择,例如:
switch(a) { case 1: case 2: case 3: result = 1; // 上面这里是一个标号语句套着标号语句,再套着标号语句,再套着赋值表达式语句。 default: if(a % 7) result = 2; else if(a % 5) case 4: result = 3; else result = 0;}在这个例子中:
- 当
a的值为1、2、3时,result的值为1 - 当
a的值为4时,result的值为3 - 当
a的值不是1、2、3时,如果a除以7的余数不为0,result的值为2- 否则,如果
a除以5的余数不为0,result的值为3; - 否则,
result的值为0。
- 否则,如果
此外,可以在 switch 语句中使用 switch 语句。这时,case 和 default 标号语句,以及 break; 跳转语句仅关联到往上级最近的 switch 语句。例如
switch(a) { case 1: switch(b) { case 2: result = 1; break; case 3: result = 2; break; default: result = 0; } break; case 4: result = 3; break; default: result = 0;}当 a 的值为 3 的时候,这里不会执行 result = 2;,而是执行 result = 0;(最后的 default 标号语句)。
循环语句有三种,包括 while、do while 和 for。
while 语句
Section titled “while 语句”while 语句的形式是:
while (condition) statement这里 condition 是一个表达式,用来表达循环条件,statement 是一个语句,表示循环体。
while 语句的执行流程是:
- 计算
condition表达式的值。将condition的值转换为bool. - 如果上一步的结果为
true,则执行statement,然后回到第一步;否则,结束while语句的执行。
举例而言,while 语句可以像这样使用:
int a = 0, sum = 0;while (a < 10) { sum += a; a += 1;}// 执行到这里时,a 的值为 10,sum 的值为 45此外,如果在 while 语句中执行到 break; 语句,那么 while 语句的执行会结束。如果执行到 continue; 语句,那么 while 语句的执行会跳过本次循环的剩余部分,直接进入下一次循环(回到上述执行流程的第一步,即再次计算 condition 的值 )。
这里,break; 和 continue; 都是跳转语句。
do while 语句
Section titled “do while 语句”do while 语句的形式是:
do statement while (condition);注意,在 while (condition) 后面有一个分号 ;。
这里 condition 是一个表达式,用来表达循环条件,statement 是一个语句,表示循环体。
do while 语句和 while 语句很像,不同之处在于 do while 语句会先执行 statement,然后再判断 condition 的值。因此,do while 语句至少会执行一次 statement。
具体而言,do while 语句的执行流程是:
- 执行
statement。 - 计算
condition表达式的值。将condition的值转换为bool。 - 如果上一步的结果为
true,则回到第一步;否则,结束do while语句的执行。
同样的,可以在 do while 语句中使用 break; 和 continue; 语句。break; 语句会结束 do while 语句的执行。
区别于 while 语句,do while 语句的 condition 计算在循环的末尾,在 do while 中执行 continue; 会跳转到 condition 的计算部分,判断是否继续循环。
下面是一个 do while 语句的例子:
int a = 0;do { if(b % 2) { a += b; break; }
if(c < 10) { a = c; break; }} while (false);这里使用了 do ... while(false) 这样的写法,以体现出和 while 的区别。
在这个程序里,如果 b 为奇数,那么会将 b 赋值给 a;如果 b 为偶数,且 c 小于 10,那么 a 的值为 c;否则,a 的值为 0。由于 condition 为 false,所以这个 do while 里面的语句只会执行一次。
for 语句
Section titled “for 语句”for 语句的形式是:
for (init condition; loop) statement这里 init 是初始化语句,condition 是循环条件表达式,loop 是循环后表达式,statement 是循环体语句。
这里,初始化语句可以是一个表达式语句或者一个声明语句。注意,这两种语句的末尾都有一个分号 ;。这使得实际情况中,for 语句看起来会像是 for( ... ; ... ; ...) 这样,有两个分号的形式。
for 语句的执行流程是:
- 执行
init语句。 - 计算
condition表达式的值。将condition的值转换为bool。 - 如果上一步的结果为
true,则执行statement,然后执行loop,再回到第二步;否则,结束for语句的执行。
举例而言,for 语句可以像这样使用:
int sum = 0;for (int i = 0; i < 10; ++i) { sum += i;}// 执行到这里时,sum 的值为 45for 语句中的 condition 可以为空,这时 for 语句的执行流程是:
- 执行
init语句。 - 执行
statement。然后执行loop,再回到第二步。
这种情况下,for 语句会一直执行下去,必须通过内部的 break; 语句来结束循环。例如:
int sum = 1;for(;;) { // 这里 init、condition、loop 都为空,在初始化语句执行和循环体执行后,都不会做任何事 sum = sum * 2; if(sum > 100) break;}这里,sum 的值会一直翻倍,直到 sum 的值大于 100 时,执行 break; 语句,结束 for 语句的执行。