C++ Tutorials: C++ Language: Program structure: Statements and flow control

C++官网参考链接:Statements and flow control - C++ Tutorials (cplusplus.com)

语句和流程控制
一个简单的C++语句是一个程序的每一个单独的指令,就像前面的变量声明和表达式。它们总是以分号(;)结束,并且按照它们在程序中出现的顺序执行。
但是程序并不局限于语句的线性序列。在其过程中,程序可能重复代码段,或做出决策和分叉。为此,C++提供了流控制语句,用于指定程序必须做什么、什么时候做以及在什么情况下做。
本节中解释的许多流控制语句都需要一个泛型(子)语句作为其语法的一部分。这个语句可以是一个简单的C++语句,比如以分号(;)结尾的单个指令,也可以是一个复合语句。复合语句是一组语句(每个语句都以自己的分号结束),但都放在一个块中,用花括号括起来:{}:
{ statement1; statement2; statement3; } 
整个块被认为是单独语句(由多个子语句组成)。当泛型语句成为流控制语句语法的一部分时,它可以是简单语句,也可以是复合语句。

选择语句:if和else
关键字if用于执行语句或块,当且仅当一个条件被满足时。它的语法是:
if (condition) statement

这里,condition是要计算的表达式。如果此条件为true,则执行statement。如果为false,则不执行statement(直接忽略),程序在整个选择语句之后继续执行。
例如,以下代码片段只在存储在x变量中的值确实为100时打印消息(x is 100):
if (x == 100)
  cout << "x is 100";
如果x不完全是100,则忽略此语句,并且不打印任何内容。
如果你想包含多个语句在条件(condition)满足时执行,这些语句(statement)应该用大括号({})括起来,形成一个块:
if (x == 100)
{
   cout << "x is ";
   cout << x;

通常,代码中的缩进和换行没有作用,所以上面的代码相当于:
if (x == 100) { cout << "x is "; cout << x; }
带有if的选择语句还可以指定当条件(condition)不满足时发生的情况,通过使用else关键字引入一个替代语句。它的语法是:
if (condition) statement1 else statement2 

如果condition为true,则执行statement1,如果不是true,则执行statement2。
例如: 
if (x == 100)
  cout << "x is 100";
else
  cout << "x is not 100";
如果x的值确实为100,则打印x is 100,但如果x不是100,且仅当x不是100,则打印x is not 100。
可以将多个if + else结构连接起来,以检查值的范围。例如: 
if (x > 0)
  cout << "x is positive";
else if (x < 0)
  cout << "x is negative";
else
  cout << "x is 0";
通过连接两个if-else结构来输出x is postion、negative或者0。同样,通过将语句分组到用大括号:{}括起来的块中,也可以在每个情况中执行多条语句(statement)。

迭代语句(循环) 
循环重复一条语句一定次数,或者在满足某个条件时重复。它们是由关键词while、do和for引入的。
while循环
最简单的循环是while循环。它的语法是: 
while(expression) statement 

while循环只是简单地重复statement,只要while中的expression为true。如果在执行任何statement之后,expression不再是true,则循环结束,程序在循环之后继续运行。例如,让我们看看使用while循环的countdown程序:

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

int main ()
{
  int n = 10;

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

  cout << "liftoff!\n";
}

输出:

main中的第一个语句将n设置为10。这是countdown程序的第一个数字。然后开始while循环:如果该值满足条件n>0 (n大于0),则执行条件后面的块,并且只要条件(n>0)仍然为true则重复执行。
上一个程序的整个过程可以按照以下步骤进行解释(从main开始): 
1.n被赋值
2.检查while条件(n>0)。在这一点上有两种可能: 
条件为true:执行语句(到步骤3) 
条件为false:忽略语句并在它之后继续执行(到步骤5) 
3.执行语句: 
cout << n << ", ";
--n;
(输出n的值并将n减少1) 
4.块的结束。自动返回步骤2。
5.在块之后继续程序: 
打印liftoff!然后结束这个项目。
对于while循环需要考虑的一点是,循环应该在某一时刻结束,因此语句应该以某种方式改变条件中检查的值,从而迫使它在某一时刻变为false。否则,循环将永远循环下去。在这种情况下,循环包括--n,它将条件(n)中正在计算的变量的值减少1---这将在一定次数的循环迭代后最终使条件(n>0)为false。更具体地说,在10次迭代之后,n变为0,使条件不再为true,并结束while循环。
请注意,这个循环的复杂性对于计算机来说是微不足道的,因此整个countdown程序是立即执行的,在计数元素之间没有任何实际的延迟(如果感兴趣,请参阅sleep_for获得一个带有延迟的countdown程序示例)。
do_while循环
一个非常类似的循环是do-while循环,它的语法是:
do statement while(condition); 

它的行为类似于while循环,只是condition是在statement执行之后而不是之前求值,保证至少执行一次statement,即使condition永远不满足。例如,以下示例程序回显用户引入的任何文本,直到用户输入goodbye:

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

int main ()
{
  string str;
  do {
    cout << "Enter text: ";
    getline (cin,str);
    cout << "You entered: " << str << '\n';
  } while (str != "goodbye");
}

当需要至少执行一次语句时,例如在循环语句本身中确定循环结束的条件(condition)时,do-while循环通常比while循环更可取。在前面的例子中,用户在块中的输入将决定循环是否结束。因此,即使用户想通过输入goodbye尽快结束循环,循环中的块也需要至少执行一次来提示输入,而条件(condition)实际上只有在执行之后才能确定。
for循环
for循环被设计为多次迭代。它的语法是:
for (initialization; condition; increase) statement;

与while循环一样,当condition为true时,该循环重复执行statement。但是,此外,for循环还提供了包含initialization和increase表达式的特定位置,分别在循环第一次开始之前和每次迭代之后执行。因此,使用计数器变量作为condition是特别有用的。 
它的工作方式如下:
1.执行initialization。通常,这将声明一个计数器变量,并将其设置为某个初始值。它只在循环开始时执行一次。
2.检查condition。如果为true,循环继续;否则,循环结束,语句被跳过,直接进入步骤5。
3.执行statement。通常,它可以是单个语句,也可以是用花括号{}括起来的块。
4.执行increase,循环返回到步骤2。
5.循环结束:继续执行后面的下一条语句。

下面是使用for循环的countdown示例:

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

int main ()
{
  for (int n=10; n>0; n--) {
    cout << n << ", ";
  }
  cout << "liftoff!\n";
}

输出:

for循环中的三个字段是可选的。它们可以为空,但在所有情况下,它们之间都需要分号。例如,for (;n<10;)是一个没有initialization或increase的循环(相当于while循环);而for (;n<10;++n)是一个带increase的循环,但没有initialization(可能因为变量在循环之前已经初始化)。一个没有condition的循环等同于一个以true为condition的循环(即无限循环)。
因为每个字段都是在循环生命周期的特定时间内执行的,所以将多个表达式作为任何initialization,condition或statement执行可能会很有用。不幸的是,这些不是语句,而是简单的表达式,因此不能用块替换。然而,作为表达式,它们可以使用逗号操作符(,):该操作符是一个表达式分隔符,可以在通常只期望一个表达式的情况下分隔多个表达式。例如,使用它,for循环可以处理两个计数器变量,对它们进行初始化和递增:
for ( n=0, i=100 ; n!=i ; ++n, --i )
{
   // whatever here...
}
如果n和i都没有在循环中被修改,这个循环将执行50次: 

n的起始值是0,i的起始值是100,条件(condition)是n!=i(即n不等于i),因为每次迭代n增加1,i减少1,所以在第50次迭代后,当n和i都等于50时,循环的条件将变为false。
基于范围for循环
for循环还有另一种语法,专门用于范围:
for ( declaration : range ) statement;

这种for循环遍历range内的所有元素,其中的declaration声明了某个变量,该变量可以接受这个范围内元素的值。range是元素序列,包括数组、容器和支持begin和end函数的任何其他类型;这些类型中的大多数在本教程中还没有介绍,但我们至少已经熟悉了一种范围:string,它是字符序列。
一个使用string的基于范围的for循环示例:

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

int main ()
{
  string str {"Hello!"};
  for (char c : str)
  {
    cout << "[" << c << "]";
  }
  cout << '\n';
}

输出:

注意,在for循环中冒号(:)前面是一个char变量的声明(string中的元素都是char类型的)。然后,我们在语句块中使用这个变量c来表示范围内每个元素的值。
此循环是自动的,不需要显式声明任何计数器变量。
基于范围的循环通常也使用auto对元素的类型进行类型推断。通常,上面基于范围的循环也可以写成:
for (auto c : str)
  cout << "[" << c << "]";
在这里,c的类型被自动推导为str中元素的类型。

跳转语句
跳转语句允许通过执行跳转到特定位置来更改程序流。
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;
    }
  }
}

输出:

continue语句 
continue语句使程序在当前迭代中跳过循环的其余部分,就好像语句块已经到达结束一样,从而使程序跳到下一轮迭代的开始。例如,让我们跳过countdown程序中的数字5:

// 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!\n";
}

输出:

goto语句
goto允许绝对跳转到程序中的另一个点。此无条件跳转忽略嵌套级别,并且不会导致任何自动堆栈展开。因此,在使用这个特性时要小心,最好是在同一个语句块中,特别是在存在局部变量的情况下。
目标点由一个标签标识,然后将其用作goto语句的实参。标签由一个有效的标识符和一个冒号(:)组成。
goto通常被认为是一种低级特性,在现代高级编程范式中没有特定的用例,通常与C++一起使用。但是,作为一个例子,这里有一个使用goto的countdown循环版本:

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

int main ()
{
  int n=10;
mylabel:
  cout << n << ", ";
  n--;
  if (n>0) goto mylabel;
  cout << "liftoff!\n";
}

输出:

另一个选择语句:switch
switch语句的语法有点奇怪。它的目的是在许多可能的常量表达式中检查一个值。它类似于链接if-else语句,但仅限于常量表达式。它最典型的语法是:
switch (expression)
{
  case constant1:
     group-of-statements-1;
     break;
  case constant2:
     group-of-statements-2;
     break;
  .
  .
  .
  default:
     default-group-of-statements
}

它的工作方式如下:switch计算expression并检查它是否等价于constant1;如果是,则执行group-of-statements-1,直到找到break语句。当它找到这个break语句时,程序跳到整个switch语句(右花括号)的结束。
如果expression不等于constant1,则对constant2进行检查。如果它等于这个,它执行group-of-statements-2,直到找到一个break,这时它跳到switch的结束。
最后,如果expression的值不匹配前面指定的任何常量(可以有任意数量的常量),程序就执行包含在default:标签后面的default-group-of-statements,如果default:存在的话(因为它是可选的)。
下面两个代码片段都有相同的行为,演示了等价于switch语句的if-else:
switch example                                if-else equivalent
switch (x) {                                       if (x == 1) {
  case 1:                                             cout << "x is 1";
    cout << "x is 1";                            } 
    break;                                           else if (x == 2) {
  case 2:                                              cout << "x is 2";
    cout << "x is 2";                             }
    break;                                            else {
  default:                                               cout << "value of x unknown";
    cout << "value of x unknown";       }
}
switch语句从早期的C编译器继承了一些特殊的语法,因为它使用标签而不是块。在最典型的使用中(如上所示),这意味着对于特定的标签,每组语句之后都需要break语句。如果不包括break,case后面的所有语句(包括任何其他标签下的语句)也会被执行,直到switch块的结束或到达跳转语句(如break)处。
如果上面的例子在第一种情况之后缺少break语句,那么在打印x is 1之后,程序将不会自动跳转到switch块的结束,而是继续执行在第二种情况下的语句(因此打印x is 2)。然后,它将继续这样做,直到遇到break语句,或到达switch块结束。这样就不需要将每一种情况的语句都包含在花括号{}中,而且对于针对不同的可能值执行同一组语句也很有用。例如:
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";

注意,switch仅限于将其求值表达式与常量表达式的标签进行比较。不能将变量用作标签或范围,因为它们不是有效的C++常量表达式。
要检查不是常量的范围或值,最好使用if和else if语句的连接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_40186813

你的能量无可限量。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值