## 2.1 控制結構(Control Structures)
一個程序的語句往往并不僅限于線性順序結構。在程序的執行過程中它可能被分成兩支執行,可能重復某些語句,也可能根據一些判斷結果而執行不同的語句。因此C++ 提供一些控制結構語句 (control structures) 來實現這些執行順序。
為了介紹程序的執行順序,我們需要先介紹一個新概念:語句塊(block of instructions)。一個語句塊(A block of instructions) 是一組互相之間由分號semicolons (;) 分隔開但整體被花括號curly bracket signs: { and }括起來的語句。
本節中我們將看到的大多數控制結構允許一個通用的statement做參數,這個statement根據需要可以是一條語句,也可以是一組語句組成的語句塊。如果我們只需要一條語句做statement,它可以不被括在花括號 ({}) 內。但如果我們需要多條語句共同做statement,則必須把它們括在花括號內 ({}) 以組成一個語句塊。
### 條件結構Conditional structure: if and else
條件結構用來實現僅在某種條件滿足的情況下才執行一條語句或一個語句塊。它的形式是:
`if (condition) statement`
這里 condition 是一個將被計算的表達式(expression)。如果表達式值為真,即條件(condition)為true,statement 將被執行。否則,statement 將被忽略(不被執行),程序從整個條件結構之后的下一條語句繼續執行。
例如,以下程序段實現只有當變量x存儲的值確實為100的時候才輸出"x is 100":
if (x == 100)
cout
如果我們需要在條件condition為真true的時候執行一條以上的語句,我們可以花括號{}將語句括起來組成一個語句塊:
if (x == 100)
{
cout << "x is ";
cout << x;
}
我們可以用關鍵字else 來指定當條件不能被滿足時需要執行的語句,它需要和if 一起使用,形式是:
`if (condition) statement1 else statement2`
例如:
if (x == 100)
cout << "x is 100";
else
cout
以上程序如果x的值為100,則在屏幕上打出x is 100,如果x不是100,而且也只有在x不是100的時候,屏幕上將打出x is not 100。
多個if + else 的結構被連接起來使用來判斷數值的范圍。以下例子顯示了如何用它來判斷變量 x中當前存儲的數值是正值,負值還是既不正也不負,即等于0 。
if (x > 0)
cout << "x is positive";
else if (x < 0)
cout << "x is negative";
else
cout
記住當我們需要執行多條語句時,必須使用花括號{}將它們括起來以組成一個語句塊block of instructions。
### 重復結構 Iteration structures 或循環loops
循環Loops 的目的是重復執行一組語句一定的次數或直到滿足某種條件。
#### while 循環
格式是:
`while (表達式expression) 語句statement`
它的功能是當expression 的值為真true時重復執行statement。
例如,下面我們將用while循環來寫一個倒計數程序:
~~~
| // custom countdown using while
#include
int main ()
{
int n;
cout ";
cin >> n;
while (n>0) {
cout << n << ", ";
--n;
}
cout << "FIRE!";
return 0;
} | Enter the starting number > 8
8, 7, 6, 5, 4, 3, 2, 1, FIRE! |
~~~
程序開始時提示用戶輸入一個倒計數的初始值。然后while 循環開始,如果用戶輸入的數值滿足條件n>0 (即 n 比0 大),后面跟的語句塊將會被執行一定的次數,直到條件 (n>0) 不再滿足(變為false)。
以上程序的所有處理過程可以用以下的描述來解釋:
從**main**開始:
1. 用戶輸入一個數值賦給n.
2. while語句檢查(n>0)是否成立,這時有兩種可能:
* true: 執行statement (到第3步)
* false: 跳過statement. 程序直接執行第5步.
3. 執行statement:
`cout << n << ", ";
--n;`
(將n 的值打印在屏幕上,然后將n 的值減1).
4. 語句塊結束,自動返回第2步。
5. 繼續執行語句塊之后的程序:打印 FIRE! ,程序結束。
我們必須考慮到循環必須在某個點結束,因此在語句塊之內(loop的statement之內) 我們必須提供一些方法使得條件condition 可以在某個時刻變為假 false,否則循環將無限重復下去。在這個例子里,我們用語句--n;使得循環在重復一定的次數后變為false :當 n 變為0, 倒計數結束。
#### do-while 循環
格式:
`do 語句statement while (條件condition);`
它的功能與while 循環一抹一樣,除了在do-while循環中是先執行statement 然后才檢查條件condition ,而不想while循環中先檢查條件然后才執行statement。這樣,即使條件condition從來沒有被滿足過,statement 仍至少被執行一次。例如,下面的程序重復輸出(echoes)用戶輸入的任何數值,直到用戶輸入0為止。
~~~
| // number echoer
#include
int main ()
{
unsigned long n;
do {
cout << "Enter number (0 to end): ";
cin >> n;
cout << "You entered: " << n << "\n";
} while (n != 0);
return 0;
} | Enter number (0 to end): 12345
You entered: 12345
Enter number (0 to end): 160277
You entered: 160277
Enter number (0 to end): 0
You entered: 0 |
~~~
*do-while* 循環通常被用在判斷循環結束的條件是在循環語句內部被決定的情況下,比如以上的例子,在循環的語句塊內用戶的輸入決定了循環是否結束。如果用戶永遠不輸入0,則循環永遠不會結束。
#### for 循環
格式是:
`for (initialization; condition; increase) statement;`
它的主要功能是當條件condition 為真**true**時重復執行語句statement ,類似while 循環。但除此之外,for 還提供了寫初始化語句initialization 和增值語句increase 的地方。因此這種循環結構是特別為執行由計數器控制的循環而設計的。
它按以下方式工作:
1. 執行初始化initialization 。通常它是設置一個計數器變量(counter variable)的初始值,初始化僅被執行一次。
2. 檢查條件condition ,如果條件為真true,繼續循環,否則循環結束循環中語句statement 被跳過。
3. 執行語句statement 。像以前一樣,它可以是一個單獨的語句,也可以是一個由花括號{ }括起來的語句塊。
4. 最后增值域(increase field)中的語句被執行,循環返回第2步。注意增值域中可能是任何語句,而不一定只是將計數器增加的語句。例如下面的例子中計數器實際為減1,而不是加1。
下面是用for循環實現的倒計數的例子:
~~~
| // countdown using a for loop
#include
int main ()
{
for (int n=10; n>0; n--) {
cout << n << ", ";
}
cout << "FIRE!";
return 0;
} | 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE! |
~~~
初始化initialization 和增值increase 域是可選的(即可以為空)。但這些域為空的時候,它們和其他域之間間隔的分號不可以省略。例如我們可以寫:for (;n<10;)來表示沒有初始化和增值語句;或for (;n<10;n++) 來表示有增值語句但沒有初始化語句。
另外我們也可以在for循環初始化或增值域中放一條以上的語句,中間用逗號 coma(,)隔開。例如假設我們想在循環中初始化一個以上的變量,可以用以下的程序來實現:
for ( n=0, i=100 ; n!=i ; n++, i-- )
{
// whatever here...
}
這個循環將被執行50 次,如果n 和i 在循還內部都不被改變的話:

**n**初始值為**0**,**i**初始值為**100**,條件是**(n!=i)**(即**n**不能等于**i**)。因為每次循環**n**加**1**,而且**i**減**1**,循環的條件將會在第50次循環之后變為假**false**(**n** 和 **i** 都等于**50**)。
### 分支控制和跳轉(Bifurcation of control and jumps)
#### break 語句
通過使用**break**語句,即使在結束條件沒有滿足的情況下,我們也可以跳出一個循環。它可以被用來結束一個無限循環(infinite loop),或強迫循環在其自然結束之前結束。例如,我們想要在倒計數自然結束之前強迫它停止(也許因為一個引擎故障):
~~~
| // break loop example
#include
int main ()
{
int n;
for (n=10; n>0; n--) {
cout << n << ", ";
if (n==3)
{
cout << "countdown aborted!";
break;
}
return 0;
} | 10, 9, 8, 7, 6, 5, 4, 3, countdown aborted! |
~~~
#### continue 語句
**continue**語句使得程序跳過當前循環中剩下的部分而直接進入下一次循環,就好像循環中語句塊的結尾已經到了使得循環進入下一次重復。例如,下面例子中倒計數時我們將跳過數字5的輸出:
| // continue loop example
include
int main ()
{
for (int n=10; n>0; n--) {
if (n==5) continue;
cout << n << ", ";
}
cout << "FIRE!";
return 0;
} | 10, 9, 8, 7, 6, 4, 3, 2, 1, FIRE! |
#### goto 語句
通過使用goto語句可以使程序從一點跳轉到另外一點。你必須謹慎只用這條語句,因為它的執行可以忽略任何嵌套限制。
跳轉的目標點可以由一個標示符(label)來標明,該標示符作為goto語句的參數。一個標示符(label)由一個標識名稱后面跟一個冒號colon (:)組成。
通常除了底層程序愛好者使用這條語句,它在結構化或面向對象的編程中并不常用。下面的例子中我們用goto來實現倒計數循環:
| // goto loop example
include
int main ()
{
int n=10;
loop:
cout << n << ", ";
n--;
if (n>0) goto loop;
cout << "FIRE!";
return 0;
} | 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE! |
#### exit 函數
**exit**是一個在[cstdlib (stdlib.h)](http://www.cplusplus.com/ref/cstdlib)庫中定義的函數。
**exit**的目的是一個特定的退出代碼來結束程序的運行,它的原型(prototype)是:
`void exit (int exit code);`
**exit code**是由操作系統使用或被調用程序使用。通常**exit code**為**0**表示程序正常結束,任何其他值表示程序執行過程中出現了錯誤。
### 選擇結構The selective Structure: switch
**switch** 語句的語法比較特殊。它的目標是對一個表達式檢查多個可能常量值,有些像我們在本節開頭學習的把幾個if 和else if 語句連接起來的結構。它的形式是:
switch (expression) {
case constant1:
block of instructions 1
break;
case constant2:
block of instructions 2
break;
.
.
.
default:
default block of instructions
}
它按以下方式執行:
switch 計算表達式expression 的值,并檢查它是否與第一個常量constant1相等,如果相等,程序執行常量1后面的語句塊block of instructions 1 直到碰到關鍵字break ,程序跳轉到switch 選擇結構的結尾處。
如果expression 不等于constant1,程序檢查表達式expression 的值是否等于第二個常量constant2, 如果相等,程序將執行常量2后面的語句塊block of instructions 2 直到碰到關鍵字break。
依此類推,直到最后如果表達式expression 的值不等于任何前面的常量(你可以用case語句指明任意數量的常量值來要求檢查),程序將執行默認區default: 后面的語句,如果它存在的話。default: 選項是可以省略的。
下面的兩段代碼段功能相同:
| *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**的語法有點特殊。注意每個語句塊結尾包含的**break**語句。這是必須的,因為如果不這樣做,例如在語句塊block of instructions 1 的結尾沒有**break**,程序執行將不會跳轉到**switch**選擇的結尾處 (**}**) ,而是繼續執行下面的語句塊,直到第一次遇到**break**語句或到**switch**選擇結構的結尾。因此,不需要在每一個case 域內加花括號**{ }** 。這個特點同時可以幫助實現對不同的可能值執行相同的語句塊。例如:
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**只能被用來比較表達式和不同常量的值constants。因此我們不能夠把變量或范圍放在case之后,例如 (case (n*2):) 或 (case (1..3):) 都不可以,因為它們不是有效的常量。 如果你需要檢查范圍或非常量數值,使用連續的if 和else if 語句。