C++——语句和流控制

简单的 C++ 语句是程序的每个单独指令,就像前面几节中看到的变量声明和表达式一样。它们始终以分号 () 结尾,并按照它们在程序中出现的顺序执行。

但是程序并不局限于线性的语句序列。在此过程中,程序可能会重复代码段,或者做出决策并分叉。为此,C++ 提供了流控制语句,用于指定我们的程序必须执行哪些作、何时以及在什么情况下执行。

本节中介绍的许多流控制语句都需要泛型 (sub) 语句作为其语法的一部分。此语句可以是简单的 C++ 语句(例如以分号 () 结尾的单个指令),也可以是复合语句。复合语句是一组语句(每个语句都以自己的分号结尾),但所有语句都分组在一个块中,用大括号括起来:{}:

整个块被视为单个语句(由多个子语句组成)。只要泛型语句是流控制语句语法的一部分,这可以是简单语句或复合语句。;;{ statement1; statement2; statement3; }

选择语句:if 和 else

关键字用于执行语句或块(当且仅当满足条件)。它的语法是:

这里,是正在计算的表达式。如果为 true,则执行。如果为 false,则不执行(简单地忽略它),并且程序在整个 selection 语句之后继续。
例如,以下代码片段仅在变量中存储的值确实为 100 时打印 message :ifif (condition) statementconditionconditionstatementstatement(x is 100)x

1
2
if (x == 100)
  cout << "x is 100";

如果不完全是 100,则忽略此语句,并且不会打印任何内容。

如果要包含多个在满足条件时要执行的语句,则这些语句应括在大括号 () 中,形成一个块:x{}

1
2
3
4
5
if (x == 100)
{
   cout << "x is ";
   cout << x;
}

像往常一样,代码中的缩进和换行符没有效果,所以上面的代码等价于:

1
if (x == 100) { cout << "x is "; cout << x; }

选择语句 with 还可以通过使用关键字引入替代语句来指定不满足条件时会发生什么情况。它的语法是:

如果 condition 为 true,则执行其中,如果 condition 为 true,则执行。

例如:ifelse if (condition) statement1 else statement2
statement1statement2

1
2
3
4
if (x == 100)
  cout << "x is 100";
else
  cout << "x is not 100";

如果 x 的值为 100,则打印 ,但如果不是,并且仅当它不是,它才会打印。
可以连接多个 if + else 结构,以便检查一系列值。例如:x is 100x is not 100

1
2
3
4
5
6
if (x > 0)
  cout << "x is positive";
else if (x < 0)
  cout << "x is negative";
else
  cout << "x is 0";

这将通过连接两个 if-else 结构来打印 x 是正、负还是零。同样,也可以通过将每个 case 分组到用大括号括起来的块中来执行多个语句:。{}

迭代语句(循环)

循环重复语句一定次数,或在满足条件时重复。它们由关键字 、 和 引入。whiledofor

while 循环

最简单的循环是 while 循环。它的语法是:

while 循环只是重复 while is true。如果在执行 , 后不再为 true,则循环结束,程序在循环之后继续。例如,让我们看一下使用 while 循环的倒计时:
 while (expression) statement


statement
expression
statement
expression

 


// custom countdown using while
#include <iostream>
using namespace std;

int main ()
{
  int n = 10;

  while (n>0) {
    cout << n << ", ";
    --n;
  }

  cout << "liftoff!
";
}
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

在 cpp.sh 上编辑和运行

中的第一个语句设置为值 10。这是倒计时中的第一个数字。然后 while 循环开始:如果该值满足条件(大于零),则执行条件后面的块,只要条件 () 保持为真,就会重复。

上一个程序的整个过程可以按照下面的脚本(从 开始 )进行解释:
mainn
n>0n
n>0
main

 

n被分配一个值
条件被选中 ()。此时有两种可能性:whilen>0

condition 为 true:语句被执行(到步骤 3)
条件为 false:忽略语句并在其后继续(到步骤 5)

Execute 语句:
(打印 的值并减 1) cout << n << ", ";
--n;

nn
块的结束。自动返回步骤 2。
在块之后继续程序:
print 并结束程序。liftoff!

使用 while 循环要考虑的一点是,循环应该在某个时间点结束,因此该语句应该以某种方式改变条件中检查的值,从而迫使它在某个时间点变为 false。否则,循环将永远继续循环。在这种情况下,循环包括 ,这会将条件 () 中正在计算的变量的值减少 1 – 这最终会在一定数量的循环迭代后使条件 () 为 false。更具体地说,在 10 次迭代后,变为 0,使条件不再为真,并结束 while 循环。

请注意,这个循环的复杂性对于计算机来说是微不足道的,因此整个倒计时是立即执行的,计数元素之间没有任何实际的延迟(如果感兴趣,请参阅带有延迟的倒计时示例)。
--n
n
n>0
n
sleep_for

do-while 循环

一个非常相似的循环是 do-while 循环,其语法是:

它的行为类似于 while 循环,不同之处在于它是在执行 of 之后而不是之前计算的,保证至少执行一次 ,即使从未实现。例如,以下示例程序会回显用户引入的任何文本,直到用户输入 goodbye:
 do statement while (condition);


condition
statement
statement
condition

 


// echo machine
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string str;
  do {
    cout << "Enter text: ";
    getline (cin,str);
    cout << "You entered: " << str << '
';
  } while (str != "goodbye");
}
Enter text: hello
You entered: hello
Enter text: who's there?
You entered: who's there?
Enter text: goodbye
You entered: goodbye

在 cpp.sh 上编辑和运行

当需要至少执行一次时,例如在循环语句本身中确定检查到循环结束的条件时,do-while 循环通常优于 while 循环。在前面的示例中,块中的用户输入将决定循环是否结束。因此,即使用户想通过 enter 尽快结束循环,循环中的块也需要至少执行一次以提示输入,而实际上只有在执行后才能确定条件。
statementgoodbye

for 循环

该循环旨在迭代多次。它的语法是:

与 while 循环一样,这个循环重复 while is true。但是,此外,for 循环还提供了包含 an 和 an 表达式的特定位置,分别在循环第一次开始之前和每次迭代之后执行。因此,使用 counter variables as 特别有用。

它的工作原理如下:
for
 for (initialization; condition; increase) statement;


statement
condition
initialization
increase
condition

 

initialization被执行。通常,这会声明一个 counter 变量,并将其设置为某个初始值。这在循环开始时执行一次。
condition被选中。如果为 true,则循环继续;否则,循环将结束并跳过,直接进入第 5 步。statement
statement被执行。像往常一样,它可以是单个语句,也可以是用大括号括起来的块。{ }
increase执行,循环返回到第 2 步。
循环结束:执行由它之后的 Next 语句继续。

以下是使用 for 循环的倒计时示例:

 


// countdown using a for loop
#include <iostream>
using namespace std;

int main ()
{
  for (int n=10; n>0; n--) {
    cout << n << ", ";
  }
  cout << "liftoff!
";
}
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

在 cpp.sh 上编辑和运行

for 循环中的三个字段是可选的。它们可以留空,但在所有情况下,它们之间的分号符号都是必需的。例如,是一个没有
初始化
增加的循环(相当于 while 循环);并且是一个带有 
increase 但没有
初始化的循环(可能是因为变量在循环之前已经初始化了)。没有
条件的循环等效于具有 as 条件的循环(即无限循环)。

由于每个字段都是在循环生命周期中的特定时间执行的,因此将多个表达式作为
初始化
条件
语句中的任何一个执行可能很有用。不幸的是,这些不是语句,而是简单的表达式,因此不能用块代替。但是,作为表达式,它们可以使用逗号运算符 ():此运算符是表达式分隔符,可以分隔通常只有一个表达式的多个表达式。例如,使用它,for 循环可以处理两个 counter 变量,初始化和增加这两个变量:
for (;n<10;)
for (;n<10;++n)
true
,

 

1
2
3
4
for ( n=0, i=100 ; n!=i ; ++n, --i )
{
   // whatever here...
}

如果循环中两者都没有修改,则此循环将执行 50 次:

 

以值 0 开头,以 100 开头,条件为(即,不等于)。因为在每次迭代中增加 1,减少 1,所以循环的条件将在第 50 次迭代后变为 false,此时 和 都等于 50。
n
i
n
i
n!=i
n
i
n
i
n
i

基于范围的 for 循环

for 循环还有另一种语法,专门用于 ranges:

这种 for 循环迭代 中的所有元素,其中声明一些变量能够获取此 range 中元素的值。范围是元素序列,包括数组、容器和支持函数 和 ;本教程尚未介绍这些类型中的大多数,但我们已经熟悉了至少一种范围:字符串,它们是字符序列。

使用字符串的基于范围的 for 循环示例:
 for ( declaration : range ) statement;


range
declarationbeginend

 


// range-based for loop
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string str {"Hello!"};
  for (char c : str)
  {
    cout << "[" << c << "]";
  }
  cout << '
';
}
[H][e][l][l][o][!]

在 cpp.sh 上编辑和运行

请注意,在 for 循环中冒号 () 前面的是变量的声明(字符串中的元素类型为 )。然后,我们在语句块中使用这个变量 ,来表示范围内每个元素的值。

此循环是自动的,不需要显式声明任何 counter 变量。

基于范围的循环通常还对元素的类型使用类型推导。通常,上面的基于范围的循环也可以写成:
:
char
char
c
auto

 

1
2
for (auto c : str)
  cout << "[" << c << "]";

在这里,的类型自动推导为 中的元素类型 。
c
str

Jump 语句

Jump 语句允许通过执行跳转到特定位置来改变程序的流程。

break 语句

break留下一个循环,即使其结束的条件未得到满足。它可以用来结束无限循环,或强制它在自然结束之前结束。例如,让我们在倒计时自然结束之前停止倒计时:

 


// break loop example
#include <iostream>
using namespace std;

int main ()
{
  for (int n=10; n>0; n--)
  {
    cout << n << ", ";
    if (n==3)
    {
      cout << "countdown aborted!";
      break;
    }
  }
}
10, 9, 8, 7, 6, 5, 4, 3, countdown aborted!

在 cpp.sh 上编辑和运行

continue 语句

该语句使程序跳过当前迭代中循环的其余部分,就好像已到达 statement 块的末尾一样,从而导致它跳转到下一个迭代的开头。例如,让我们跳过倒计时中的数字 5:
continue

 


// continue loop example
#include <iostream>
using namespace std;

int main ()
{
  for (int n=10; n>0; n--) {
    if (n==5) continue;
    cout << n << ", ";
  }
  cout << "liftoff!
";
}
10, 9, 8, 7, 6, 4, 3, 2, 1, liftoff!

在 cpp.sh 上编辑和运行

goto 语句

goto允许对程序中的另一个点进行绝对跳转。这种无条件跳转忽略嵌套级别,并且不会导致任何自动堆栈展开。因此,这是一个需要谨慎使用的功能,最好在同一语句块中使用,尤其是在存在局部变量的情况下。

目标点由
标签标识,然后用作语句的参数。
标签由有效标识符后跟冒号 () 组成。

通常被视为低级功能,在通常与 C++ 一起使用的现代高级编程范式中没有特定的用例。但是,作为一个例子,下面是使用 goto 的倒计时循环的一个版本:
goto
:
goto

 


// goto loop example
#include <iostream>
using namespace std;

int main ()
{
  int n=10;
mylabel:
  cout << n << ", ";
  n--;
  if (n>0) goto mylabel;
  cout << "liftoff!
";
}
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

在 cpp.sh 上编辑和运行

另一个选择语句:switch。

switch 语句的语法有点奇特。其目的是在许多可能的常量表达式中检查值。它类似于 concatenating – 语句,但仅限于常量表达式。它最典型的语法是:

它的工作方式如下: 评估并检查它是否等同于 ;如果是,则执行该语句,直到找到该语句。当它找到此语句时,程序会跳转到整个语句的末尾(右大括号)。

如果 expression 不等于 ,则根据 进行检查。如果等于 this,则执行直到找到 a,然后跳转到 switch 的末尾。

最后,如果 expression 的值与任何先前指定的常量都不匹配(可能有任意数量的常量),则程序将执行标签后面包含的语句(如果存在)(因为它是可选的)。

以下两个代码片段具有相同的行为,演示了 switch 语句的 if-else 等效项:ifelse

code>switch (expression)

{

  case constant1:

     group-of-statements-1;

     break;

  case constant2:

     group-of-statements-2;

     break;

  .

  .

  .

  default:

     default-group-of-statements

}
/code>

switchexpressionconstant1group-of-statements-1breakbreakswitchconstant1constant2group-of-statements-2breakdefault:

switch 示例 if-else 等效
code>switch (x) {

  case 1:

    cout 

 "x is 1";

    break;

  case 2:

    cout 

 "x is 2";

    break;

  default:

    cout 

 "value of x unknown";

  }
/code>
code>if (x == 1) {

  cout 

 "x is 1";

}

else if (x == 2) {

  cout 

 "x is 2";

}

else {

  cout 

 "value of x unknown";

}


/code>

该语句具有从第一个 C 编译器的早期继承而来的某种奇特的语法,因为它使用标签而不是块。在最典型的用法中(如上所示),这意味着在特定标签的每组语句之后都需要 statements。如果不包含,则还将执行 case 后面的所有语句(包括任何其他标签下的语句),直到到达 switch 块的末尾或跳转语句(例如 )。

如果上面的示例在情况 1 的第一组之后缺少 break 语句,则程序在打印后不会自动跳转到 switch 块的末尾,而是继续执行情况 2 中的语句(因此也打印)。然后,它会继续这样做,直到遇到 statement 或块结束。这使得没有必要将每种情况的语句括在 braces 中,并且对于不同的可能值执行同一组语句也很有用。例如:switchbreakbreakbreakx is 1x is 2breakswitch{}

1
2
3
4
5
6
7
8
9
switch (x) {
  case 1:
  case 2:
  case 3:
    cout << "x is 1, 2 or 3";
    break;
  default:
    cout << "x is not 1, 2 nor 3";
  }

请注意,仅限于将其计算的表达式与作为常量表达式的标签进行比较。不能将变量用作标签或范围,因为它们不是有效的 C++ 常量表达式。

要检查不恒定的范围或值,最好使用 and 语句的串联。switchifelse if

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容