聲明和流控制
一個簡單的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++通過引入while
,do
和for關機子
。當滿足條件時,循環重複一次語句一定次數。
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
)解釋前一個程序的整個過程:
n
被賦予一個值- 該
while
條件被選中(n>0
)。此時有兩種可能性:- condition爲true:執行語句(到第3步)
- condition爲false:忽略語句並在其後繼續(到第5步)
- 執行語句:( 打印值減1 並減1)
cout << n << ", ";
--n; - 結束語句塊。自動返回第2步。
- 在程序段後立即繼續執行程序:
打印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)的特定位置,分別在循環開始第一次之前和每次迭代之後執行。因此,使用計數器變量特別有用。 它的工作方式如下:
initialization
被執行。通常,這會聲明一個計數器變量,並將其設置爲某個初始值。這在循環開始時執行一次。condition
檢查。如果是,則循環繼續; 否則,循環結束,並statement
跳過,直接進入步驟5。statement
被執行。像往常一樣,它可以是單個語句,也可以是用花括號括起來的塊{ }
。increase
執行,循環返回到步驟2。- 循環結束:執行後繼續執行下一個語句。
這是使用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次迭代後成爲假,此時兩個變量n
和i的值
都等於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語句的語法有點奇怪。其目的是檢查許多可能的常量表達式中的值。它類似於連接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
語句的結尾(結束括號)。
如果表達式不等於constant1
,則對其進行檢查constant2
。如果它等於這個,它將執行group-of-statements-2
直到break
找到a,當它跳轉到開關的末尾。
最後,如果表達式的值與之前指定的任何常量都不匹配(可能有任何數量的這些),程序將執行default:
標籤後面包含的語句(如果存在)(因爲它是可選的不一定要有)。
以下兩個代碼片段都具有相同的行爲,演示了switch語句的if-else等價的例子:(CSDN變成表格後會比較奇怪)
switch example | if-else equivalent |
---|---|
|
|
該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 ++常量表達式。
要檢查非常量的範圍或值,最好使用if
和else if
語句的連接而不是switch。