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 example if-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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章