C++之声明和流控制

声明和流控制

一个简单的C ++语句是由每个单独指令组成的程序,比如前面部分中看到的变量声明和表达式。它们总是以分号(;)结尾,并按照它们在程序中出现的顺序执行。

但是程序不仅限于线性序列的陈述。在其过程中,程序可以重复代码段,或者做出决定和分叉。为此,C ++提供了流控制语句,用于指定何时以及在何种情况下程序必须完成的操作。

本节中解释的许多流控制语句都需要通用(子)语句作为其语法的一部分。该语句可以是简单的C ++语句,例如单个指令,以分号结尾(;) - 或复合语句,复合语句是一组语句(每个语句都以它自己的分号结尾),但是所有语句都在一个块中组合在一起,用大括号括起来:{};

{ statement1; statement2; statement3; } 

上面的整个语句被认为是一个整体语句(它由多个子语句组成)。每当泛型语句是流控制语句的语法的一部分时,它可以是简单语句或复合语句。

选择语句:if和else

if关键字用于执行语句或块中,意思是如果,且仅当一个条件被满足。它的语法是:
 

if (condition) statement

这里condition是正在判断的表达式。如果condition是true,则statement部分的代码执行。如果为false,statement则不执行(只是忽略它),程序在整个选择语句之后继续执行。

例如,以下代码片段(x is 100)仅在存储在x变量中的值确实为100 时才打印消息:

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

如果x不是加好为100,则忽略此语句,并且不打印任何内容。

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

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

像往常一样,代码中的缩进和换行没有任何效果,因此上面的代码相当于:
 

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

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

if (condition) statement1 else statement2

statement1只有在condition的值是true的情况下才会执行,而当condition为false的情况下statement2才执行。

例如:

if (x == 100)
  cout << "x is 100";
else
  cout << "x is not 100";

上面的代码,当x的值为100的时候会输出x is 100,当x不是100,且仅当x==100的值为false的时候,程序代替的会输出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 positive、negtive或0,同样也可以将它们用{}分成各个块,每个块中可以有多个执行语句。

迭代语句

C++通过引入whiledofor关机子。当满足条件时,循环重复一次语句一定次数。

while循环

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


while (expression) statement

当while后面的expression是true的时候执行statement,执行结束后重新判断expression是否为真直至其为假不再循环statement,继续执行while语句块之后的语句,例如,让我们看看使用while循环的倒计时:

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

int main ()
{
  int n = 10;

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

  cout << "liftoff!\n";

结果是:

10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

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

可以根据以下脚本(从头开始main)解释前一个程序的整个过程:

  1. n 被赋予一个值
  2. while条件被选中(n>0)。此时有两种可能性:
    • condition为true:执行语句(到第3步)
    • condition为false:忽略语句并在其后继续(到第5步)
  3. 执行语句:( 打印值减1 并减1)
    cout << n << ", ";
    --n;
  4. 结束语句块。自动返回第2步。
  5. 在程序段后立即继续执行程序:
    打印liftoff!并结束程序。

 while循环要考虑的一点是循环应该在某个点结束,因此语句应该以某种方式改变在条件中检查的值,以便在某些时候强制它变为false。否则,循环将继续循环(无限循环)。在上面这种情况下,循环包括--n,将条件(n)中正在计算的变量的值减1;这将最终使条件(n>0)在一定数量的循环迭代后变为假。更具体地说,在10次迭代之后,n变为0,使条件不再为真,并结束while循环。

请注意,这个循环的复杂性对于计算机来说是微不足道的,因此整个倒计时是立即执行的,计数的元素之间没有任何实际的延迟(如果感兴趣,请参阅http://www.cplusplus.com/reference/thread/this_thread/sleep_for/sleep_for)具有延迟的倒计时示例)。

 

do-while循环

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

do statement while (condition);

 它的行为类似于while循环体,只是判断是在执行statement之后而不是之前,保证至少执行一次,即使condition的值从未实现过过,一旦当while后的condition为true则结束循环。例如,以下示例程序回显用户引入的任何文本,直到用户进入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");
}

结果是:

Enter text: hello
You entered: hello
Enter text: who's there?
You entered: who's there?
Enter text: goodbye
You entered: goodbye

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

for循环

for循环被设计为迭代多次。它的语法是:

for (initialization; condition; increase) statement;

 像while循环一样,当condition为true的时候这个循环重复。此外,for循环提供了包含一个初始值(initialization)和一个表达式(increase)的特定位置,分别在循环开始第一次之前和每次迭代之后执行。因此,使用计数器变量特别有用。 它的工作方式如下:

  1. initialization被执行。通常,这会声明一个计数器变量,并将其设置为某个初始值。这在循环开始时执行一次。
  2. condition检查。如果是,则循环继续; 否则,循环结束,并statement跳过,直接进入步骤5。
  3. statement被执行。像往常一样,它可以是单个语句,也可以是用花括号括起来的块{ }
  4. increase 执行,循环返回到步骤2。
  5. 循环结束:执行后继续执行下一个语句。

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

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

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

 结果是:

10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

for循环中的三个字段是可选的。它们可以留空,但在所有情况下都都不能省略它们之间的分号。例如,for (;n<10;)是一个没有初始化增加的循环(相当于一个while循环); 而for (;n<10;++n)是一个增加的循环,但没有初始化(可能因为变量在循环之前已经初始化)。没有条件的循环等同于具有true条件的循环(即,无限循环)。

因为每个字段中在一个循环的生命周期的特定时间被执行时,它可以在多于一个单一表达式作为任何的是执行有用初始化条件声明。不幸的是,这些不是语句,而是简单的表达式,因此不能被块替换。但是,作为表达式,它们可以使用逗号运算符(,):此运算符是表达式分隔符,可以分隔多个表达式,其中通常只需要一个表达式。例如,使用它,for循环可以处理两个计数器变量,初始化和增加两个:

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

如果在循环内没有修改n或i,则该循环将执行50次:

 

n以值0开始,并且i等于100,条件是n!=i(即,n不等于i)。因为每次迭代n增加一,并且i减少一,循环的条件将第50次迭代后成为假,此时两个变量ni的值都等于50。

基于范围的循环

for循环有另一种语法,它专门用于范围:

for ( declaration : range ) statement;

这种for循环遍历所有元素,其中声明declaration变量能够获取该range范围内元素的值。 范围是元素序列,包括数组,容器和支持函数begin和end的任何其他类型。大多数这些类型尚未在本教程中介绍,但我们已经熟悉至少一种范围:字符串,它们是字符序列。

使用字符串的基于范围的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';
}

输出结果:

[H][e][l][l][o][!]

注意for循环中冒号(:)之前的内容是char变量的声明(字符串中的元素是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;
    }
  }
}

结果:

10, 9, 8, 7, 6, 5, 4, 3, countdown aborted!

continue语句

continue语句使程序跳过当前迭代中的其余循环,就好像已到达语句块的结尾一样,导致它跳转到下一次迭代的开始。例如,让我们在倒计时中跳过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";
}

结果是:

10, 9, 8, 7, 6, 4, 3, 2, 1, liftoff!

结果中少了5。

goto语句(慎用,一般不用)

goto允许绝对跳转到程序中的另一个点。此无条件跳转忽略嵌套级别,并且不会导致任何自动堆栈展开。因此,小心使用是一个特征,最好是在同一个语句块中,特别是在存在局部变量的情况下。

目标点由标签标识,然后将其用作goto语句的参数。甲标签的情况下(一个有效标识符,后跟一个冒号的:)。
goto通常被认为是低级功能,在通常与C ++一起使用的现代高级编程范例中没有特定的用例。但是,举个例子,这是我们使用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!\n";
}

结果是:

10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

另外一个选择声明:switch

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

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语句的结尾(结束括号)。

如果表达式不等于constant1,则对其进行检查constant2。如果它等于这个,它将执行group-of-statements-2直到break找到a,当它跳转到开关的末尾。

最后,如果表达式的值与之前指定的任何常量都不匹配(可能有任何数量的这些),程序将执行default:标签后面包含的语句(如果存在)(因为它是可选的不一定要有)。

以下两个代码片段都具有相同的行为,演示了switch语句的if-else等价的例子:(CSDN变成表格后会比较奇怪)

switch exampleif-else equivalent
switch (x) {
  case 1:
    cout << "x is 1";
    break;
  case 2:
    cout << "x is 2";
    break;
  default:
    cout << "value of x unknown";
  }
if (x == 1) {
  cout << "x is 1";
}
else if (x == 2) {
  cout << "x is 2";
}
else {
  cout << "value of x unknown";
}

 

switch语句有一些从第一个C编译器的早期继承的特殊语法,因为它使用标签而不是块。在最典型的用法中(如上所示),这意味着break在特定标签的每组语句之后需要语句。如果break不包括在内,则也会执行该案例后面的所有语句(包括任何其他标签下的语句),直到达到switch块或跳转语句(例如break)的结尾。
如果上面的示例在第一个案例一之后缺少break语句,则程序在打印后不会自动跳转到switch块的末尾,x is 1而是在两个案例中继续执行语句(因此也打印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 ++常量表达式。

要检查非常量的范围或值,最好使用ifelse if语句的连接而不是switch。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值