C++ 程式設計
通常程式不是線性指令序列。它可能會重複程式碼或為給定的路徑目標關係做出決定。大多數程式語言都有控制流語句(結構),這些語句提供一些控制結構,用於指定執行程式必須執行的順序,從而允許此順序的順序變化。
- 語句可能只在特定條件下(條件語句)執行,
- 語句可能在特定條件下(迴圈)重複執行,
- 一組遠端語句可能執行(子例程)。
- 邏輯表示式作為條件
- 邏輯表示式可以在迴圈和條件語句中使用邏輯運算子,作為要滿足的條件的一部分。
有些指令沒有特定的結構,但將在塑造其他控制流語句的結構方面具有非凡的用處,必須特別注意防止非結構化和混亂的程式設計。
break 將強制當前迴圈迭代退出到迴圈外部的下一條語句。除了switch 控制語句之外,它在迴圈結構之外沒有用處。
continue 指令用於迴圈內部,它將停止當前迴圈迭代,並啟動下一個迭代。
goto 關鍵字不鼓勵使用,因為它使得難以跟蹤程式邏輯,從而導致錯誤。goto 語句使當前執行執行緒跳轉到指定的標籤。
- 語法
label:
statement(s);
goto label;
在一些罕見的情況下,goto 語句允許編寫簡潔的程式碼,例如,在處理導致函式退出時清理程式碼的多個退出點時(並且異常處理或物件解構函式不是更好的選擇)。除了這些罕見情況外,無條件跳轉的使用通常是設計複雜的徵兆,因為存在許多巢狀語句層級。
在特殊情況下,例如重度最佳化,程式設計師可能需要對程式碼行為進行更多控制;goto 允許程式設計師指定執行流程直接且無條件地跳轉到所需的標籤。標籤是函式中其他地方的標籤語句的名稱。
例如,goto 可以用於退出兩個巢狀迴圈。此示例在用零替換遇到的第一個非零元素後退出。
for (int i = 0; i < 30; ++i) {
for (int j = 0; j < 30; ++j) {
if (a[i][j] != 0) {
a[i][j] = 0;
goto done;
}
}
}
done:
/* rest of program */
雖然簡單,但它們很快就會導致難以閱讀和難以維護的程式碼。
// snarled mess of gotos
int i = 0;
goto test_it;
body:
a[i++] = 0;
test_it:
if (a[i])
goto body;
/* rest of program */
比等效的
for (int i = 0; a[i]; ++i) {
a[i] = 0;
}
/* rest of program */
Goto 通常用於效能至關重要的函式或機器生成的程式碼的輸出(如由yacc 生成的解析器)。
goto 語句幾乎應該總是避免,但有些情況下它會提高程式碼的可讀性。一種情況是“錯誤部分”。
示例
#include <new>
#include <iostream>
...
int *my_allocated_1 = NULL;
char *my_allocated_2 = NULL, *my_allocated_3 = NULL;
my_allocated_1 = new (std::nothrow) int[500];
if (my_allocated_1 == NULL)
{
std::cerr << "error in allocated_1" << std::endl;
goto error;
}
my_allocated_2 = new (std::nothrow) char[1000];
if (my_allocated_2 == NULL)
{
std::cerr << "error in allocated_2" << std::endl;
goto error;
}
my_allocated_3 = new (std::nothrow) char[1000];
if (my_allocated_3 == NULL)
{
std::cerr << "error in allocated_3" <<std::endl;
goto error;
}
return 0;
error:
delete [] my_allocated_1;
delete [] my_allocated_2;
delete [] my_allocated_3;
return 1;
此結構避免了處理錯誤來源的麻煩,並且比使用控制結構的等效結構更簡潔。因此,它不易出錯。
正如我們將在後面看到的,C++ 中包含的標準 C 庫 還提供了一些有用的函式,可以改變控制流。有些函式允許你終止程式的執行,使你能夠設定返回值或在終止請求時啟動特殊任務。你將不得不跳到abort() - exit() - atexit() 部分以獲取更多資訊。
很可能在沒有任何編寫過的有意義的程式中,計算機都不會根據某些特定條件展示基本的決策能力。實際上,可以認為沒有人類活動是不涉及決策、本能或其他方面的。例如,在駕駛汽車並靠近紅綠燈時,一個人不會想,“我將繼續駛過十字路口。”相反,一個人會想,“如果燈是紅色,我會停車,如果燈是綠色,我會走,如果燈是黃色,如果我以一定速度行駛並且距離十字路口一定距離,我會走。”這些過程可以使用條件語句進行模擬。
條件語句是指示計算機僅在滿足特定條件時才執行某些程式碼塊或更改某些資料的語句。
最常見的條件語句是 if-else 語句,條件表示式和 switch-case 語句通常用作更簡潔的方法。
if 語句允許根據指定的條件選擇一條可能的路徑。
語法
if (condition)
{
statement;
}
語義
首先,評估條件
- 如果條件為真,則語句在繼續執行主體之前執行。
- 如果條件為假,則程式跳過語句並繼續執行程式的其餘部分。
示例
if(condition)
{
int x; // Valid code
for(x = 0; x < 10; ++x) // Also valid.
{
statement;
}
}

有時程式需要根據條件選擇兩個可能的路徑之一。為此,我們可以使用 if-else 語句。
if (user_age < 18)
{
std::cout << "People under the age of 18 are not allowed." << std::endl;
}
else
{
std::cout << "Welcome to Caesar's Casino!" << std::endl;
}
在這裡,如果使用者未滿 18 歲,我們將顯示一條訊息。否則,我們允許使用者進入。只有當 'user_age' 小於 18 時才會執行 if 部分。在其他情況下(當 'user_age' 大於或等於 18 時),將執行 else 部分。
if 條件語句可以串聯在一起,以實現更復雜的條件分支。在這個例子中,我們擴充套件了之前的例子,還檢查了使用者是否超過 64 歲,並在滿足條件時顯示另一條訊息。
if (user_age < 18)
{
std::cout << "People under the age of 18 are not allowed." << std::endl;
}
else if (user_age > 64)
{
std::cout << "Welcome to Caesar's Casino! Senior Citizens get 50% off." << std::endl;
}
else
{
std::cout << "Welcome to Caesar's Casino!" << std::endl;
}

switch (多重分支)
[edit | edit source]switch 語句根據特定的整數值進行分支。
switch (integer expression) {
case label1:
statement(s)
break;
case label2:
statement(s)
break;
/* ... */
default:
statement(s)
}
正如你在上面的方案中看到的,case 和 default 在程式碼塊的末尾都有一個 "break;" 語句。這個表示式將導致程式退出 switch,如果沒有新增 break,程式將繼續執行其他 case 中的程式碼,即使整數表示式不等於該 case。這可以在某些情況下被利用,如下一個例子所示。
我們要將輸入從數字分離到其他字元。
char ch = cin.get(); //get the character
switch (ch) {
case '0':
// do nothing fall into case 1
case '1':
// do nothing fall into case 2
case '2':
// do nothing fall into case 3
/* ... */
case '8':
// do nothing fall into case 9
case '9':
std::cout << "Digit" << endl; //print into stream out
break;
default:
std::cout << "Non digit" << endl; //print into stream out
}
在這段小程式碼中,對於每個小於 '9' 的數字,它將繼續傳播到 case,直到它到達 case '9' 並列印 "digit"。
如果不是這樣,它將直接進入預設的 case,在那裡它將列印 "Non digit"。
迴圈(迭代)
[edit | edit source]迴圈(也稱為迭代或重複)是一系列語句,這些語句只指定一次,但可以連續執行多次。迴圈“內部”的程式碼(迴圈的主體)會按照指定的次數執行,或者針對每個專案執行一次,或者直到滿足某個條件為止。
迭代是重複一個過程,通常是在計算機程式中。令人困惑的是,它可以用作通用的術語,與重複同義,也可以用來描述具有可變狀態的特定形式的重複。
當以第一種意義使用時,遞迴是迭代的一個例子。
但是,當以第二種(更嚴格)意義使用時,迭代描述了在指令式程式設計語言中使用的程式設計風格。這與遞迴形成對比,遞迴採用更宣告性的方法。
由於 C++ 的性質,在區分單詞的使用時可能會導致更大的問題,因此為了簡化問題,使用“迴圈”來指代本節中描述的簡單遞迴,使用迭代或迭代器(執行迭代的“一個”)來指代 STL 中使用的類迭代器(或與物件/類相關)。
- 無限迴圈
有時程式需要永遠迴圈,或者直到出現錯誤等異常情況。例如,事件驅動的程式可能打算永遠迴圈處理發生的事件,只有在操作員終止程序時才停止。
更常見的是,無限迴圈是由於條件控制迴圈中的程式設計錯誤造成的,在這種情況下,迴圈條件在迴圈內從未改變。
// as we will see, these are infinite loops...
while (1) { }
// or
for (;;) { }
- 條件控制迴圈
大多數程式語言都有用於重複迴圈直到某個條件改變的結構。
條件控制迴圈分為兩類:預條件或入口條件,將測試放在迴圈的開頭;後條件或退出條件迭代,將測試放在迴圈的末尾。在前一種情況下,主體可能會完全跳過,而在後一種情況下,主體始終至少執行一次。
在條件控制迴圈中,break 和 continue 關鍵字變得重要。break 關鍵字導致退出迴圈,繼續執行程式的其餘部分。continue 關鍵字終止迴圈的當前迭代,迴圈繼續進行下一輪迭代。
while (預條件迴圈)
[edit | edit source]語法
while (''condition'') ''statement''; ''statement2'';
語義 首先,評估條件。
- 如果條件為真,則執行語句並再次評估條件。
- 如果條件為假,則繼續執行語句2。
備註:語句可以是一個包含多個指令的程式碼塊 { ... }。
'while' 語句與 'if' 語句的不同之處在於,一旦執行了主體(在上面稱為語句),它將返回到 'while' 並再次檢查條件。如果為真,它將再次執行。實際上,它將一直執行,直到表示式為假。
示例 1
#include <iostream>
using namespace std;
int main()
{
int i=0;
while (i<10) {
cout << "The value of i is " << i << endl;
i++;
}
cout << "The final value of i is : " << i << endl;
return 0;
}
執行
The value of i is 0 The value of i is 1 The value of i is 2 The value of i is 3 The value of i is 4 The value of i is 5 The value of i is 6 The value of i is 7 The value of i is 8 The value of i is 9 The final value of i is 10
示例 2
// validation of an input
#include <iostream>
using namespace std;
int main()
{
int a;
bool ok=false;
while (!ok) {
cout << "Type an integer from 0 to 20 : ";
cin >> a;
ok = ((a>=0) && (a<=20));
if (!ok) cout << "ERROR - ";
}
return 0;
}
執行
Type an integer from 0 to 20 : 30 ERROR - Type an integer from 0 to 20 : 40 ERROR - Type an integer from 0 to 20 : -6 ERROR - Type an integer from 0 to 20 : 14
do-while (後條件迴圈)
[edit | edit source]語法
do {
statement(s)
} while (condition);
statement2;
語義
- 執行語句(s)。
- 評估條件。
- 如果條件為真,則轉到 1)。
- 如果條件為假,則繼續執行語句2。
do - while 迴圈在語法和目的上與 while 迴圈類似。該結構將迴圈繼續條件的測試移動到程式碼塊的末尾,以便在任何評估之前至少執行一次程式碼塊。
示例
#include <iostream>
using namespace std;
int main()
{
int i=0;
do {
cout << "The value of i is " << i << endl;
i++;
} while (i<10);
cout << "The final value of i is : " << i << endl;
return 0;
}
執行
The value of i is 0 The value of i is 1 The value of i is 2 The value of i is 3 The value of i is 4 The value of i is 5 The value of i is 6 The value of i is 7 The value of i is 8 The value of i is 9 The final value of i is 10
for (預條件和計數控制迴圈)
[edit | edit source]for 關鍵字用作預條件迴圈的特例,它支援用於以步進表示式的形式僅重複迴圈一定次數的構造,可以測試該表示式並用於透過在每次迴圈中遞增或遞減來設定步進大小(變化率)。
- 語法
for (initialization ; condition; step-expression)
statement(s);
for 結構是一個通用的迴圈機制,它包含 4 個部分。
- . 初始化,它包含 0 個或多個用逗號分隔的變數初始化語句。
- . 測試條件,它被評估以確定是否繼續執行 for 迴圈。
- . 遞增,它包含 0 個或多個用逗號分隔的語句,這些語句遞增變數。
- . 語句列表,它包含 0 個或多個語句,這些語句將在每次執行迴圈時執行。
for 迴圈等效於下一個 while 迴圈
initialization
while( condition )
{
statement(s);
step-expression;
}
示例 1
// a unbounded loop structure
for (;;)
{
statement(s);
if( statement(s) )
break;
}
示例 2
// calls doSomethingWith() for 0,1,2,..9
for (int i = 0; i != 10; ++i)
{
doSomethingWith(i);
}
可以改寫為
// calls doSomethingWith() for 0,1,2,..9
int i = 0;
while(i != 10)
{
doSomethingWith(i);
++i;
}
for 迴圈是一個非常通用的結構,它可以執行無界迴圈(示例 1),並且不需要遵循許多更正式語言中類似命名結構強加的嚴格迭代模型。C++(就像現代 C)允許在 for 迴圈的初始化部分宣告變數(示例 2),並且通常被認為是一種良好的形式,只在可以初始化時宣告物件,並在儘可能小的作用域中進行初始化。本質上,for 和 while 迴圈是等效的。大多數 for 語句也可以改寫為 while 語句。
在 C++11 中,添加了 for 迴圈的另一種形式。這種迴圈遍歷範圍(通常是字串或容器)中的每個元素。
- 語法
for (variable-declaration : range-expression)
statement(s);
示例 2
std::string s = "Hello, world";
for (char c : s)
{
std::cout << c << ' ';
}
將列印
H e l l o , w o r l d
.