---
# System prepended metadata

title: C++
tags: [C++]

---

# C++ 基礎

[TOC]

## 1. 開發環境

### 1.1 整合開發環境（IDE）

- Dev-C++
- Code::Blocks
- Visual Studio Code
- Xcode (MacOS)

### 1.2 輕量級選擇：文字編輯器 + 編譯器

#### 文字編輯器
- Sublime Text
- Vi/Vim
- Emacs
- Nano

#### 編譯器 Clang

**Clang** 是一個基於 LLVM 架構的開源編譯器，支援 C、C++、Objective-C 等語言。Clang 以其高效的編譯速度、清晰易懂的錯誤與警告訊息，以及模組化設計而聞名，常用於開發者工具中。它和 GCC 一樣廣泛支援多平台，但比起 GCC 更加靈活，尤其在編譯大型專案時表現優秀。Clang 也能與 LLVM 工具鏈一起使用，提供高效的優化和靜態分析，並且經常被用作 macOS 和 iOS 開發的默認編譯器。

#### 編譯器 GCC

**GCC**（GNU Compiler Collection）是由 GNU 開發的開源編譯器集合，支援多種編程語言，包括 C、C++、Objective-C、Fortran、Ada 等。最初是為了編譯 C 語言而設計的，但隨著時間推移，擴展為多語言、多平台的強大工具。GCC 具有高效的優化功能，能夠生成性能優異的程式碼，因此在軟體開發、嵌入式系統等領域廣泛使用。

它的多平台特性使其能夠在多種作業系統（如 Windows、macOS、Linux）上使用，並且是 Linux 開發環境中的主要編譯器之一。

#### 技巧：下一個指令同時編譯和執行（使用 Shell）

用文字編輯器，將下列 Shell 函式加入你的 Shell 設定檔（`~/.bashrc` 或 `~/.zshrc`）


```bash=
cr() {
    # Check if a filename is provided
    if [ -z "$1" ]; then
        echo "Please provide a file name to compile"
        return 1
    fi

    # Compile and generate the executable
    clang++ -std=c++11 "$1.cpp" -o "$1"

    # If the compilation succeeds, execute the file
    if [ $? -eq 0 ]; then
        echo "Executing $1..."
        ./"$1"
    else
        echo "Compilation failed"
    fi
}

```

加入之後，重新載入 Shell 設定檔
```bash
source ~/.bashrc  # 如果用 zsh，則執行 source ~/.zshrc
```


### 1.3 線上開發環境

- [Programiz](https://www.programiz.com/cpp-programming/online-compiler/)
- [W3School](https://www.w3schools.com/cpp/trycpp.asp?filename=demo_compiler)

![W3School](https://hackmd.io/_uploads/HkqO8BJekl.png)

## 2. 編譯語言概念

C++ 程式的開發過程可以分為六個主要階段，每個階段都有其獨特的作用，從撰寫原始碼到最終執行程式。以下是這六個階段的簡介：

#### 1. **編輯（Editing）**
   編輯階段是程式開發的第一步，開發者在文字編輯器或 IDE 中撰寫 C++ 程式碼，並將其儲存為 `.cpp` 或 `.h` 檔案。這些原始碼包含了程式的邏輯、變數、函式等部分。

#### 2. **前置處理（Preprocessing）**
   在前置處理階段，編譯器會處理 C++ 原始碼中的指令，例如 `#include`、`#define` 等指令。這些指令由**前置處理器**進行處理，將外部的標頭檔案包含進來，替換巨集定義，並且處理條件式編譯等。在這個階段，程式還未進行語法分析或轉換成機器碼，只是進行簡單的文本處理。

   輸出文件為預處理後的代碼，通常使用 `.i` 或 `.ii` 擴展名。

#### 3. **編譯（Compiling）**
   編譯階段將前置處理過的 C++ 原始碼轉換成**中間表示**，再進一步將其轉換成**組合語言**（Assembly Code）。這個階段主要進行語法分析、語義分析，確保程式語法正確無誤。編譯的輸出結果是組合語言檔案，通常是 `.s` 檔案。

#### 4. **組譯（Assembling）**
   組譯階段會將生成的組合語言轉換為**目標碼**（Object Code），目標碼是一種機器碼，但它尚未被完整連結，不能單獨執行。生成的目標碼通常以 `.o`（Linux/macOS）或 `.obj`（Windows）為副檔名。

#### 5. **連結（Linking）**
   連結階段會將多個目標碼檔案以及需要的函式庫（例如標準 C++ 函式庫）進行**整合**，並解決符號之間的相互引用，例如函式和變數的定義和呼叫。連結器會生成最終的**可執行檔案**。如果有外部函式庫沒有正確連結，會在這個階段報錯。

   輸出的可執行文件在 Windows 上通常為 `.exe`，在 Unix 系統上為沒有副檔名的檔案。

#### 6. **載入（Loading）**
   當執行程式時，操作系統會將可執行檔案載入到**記憶體**中。這個過程稱為載入，操作系統負責分配記憶體並設置程式執行所需的環境，包括載入程式依賴的動態函式庫（例如 `.dll` 或 `.so` 檔案）。

#### 7. **執行（Execution）**
   最後，在執行階段，程式會從進入點（通常是 `main()` 函式）開始運行。程式會按照程式碼的邏輯執行，並進行 I/O 操作、計算，直到結束執行。執行過程中，可能會遇到例外狀況或錯誤，這些錯誤會導致程式中斷或異常退出。

這六個階段構成了 C++ 程式從撰寫到執行的完整流程，理解這些階段有助於開發者有效地進行程式除錯和效能優化。


## 3. 程式範例 1 - Hello world

```c++=
#include <iostream>

int main() {
    std::cout << "Hello world!\n";  // Print "Hello world!"
    
    return 0;
}
```

- `#include <iostream>` 前置處理指令 (preprocessor directive)
- `<iostream>` 輸入輸出串流標頭檔 (input/output stream header file)
- `<<` 串流插入運算子 (stream insertion operator)
- [C++ Outputs](https://www.w3schools.com/cpp/cpp_output.asp)
- [C++ Comments](https://www.w3schools.com/cpp/cpp_comments.asp)

## 4. 程式範例 2 - 整數加法

```c++=
#include <iostream>

int main() {
    // 變數宣告
    int number1;
    int number2;
    int sum;
    
    std::cout << "Enter first integer: ";  // prompt
    std::cin >> number1;
    
    std::cout << "Enter second integer: ";  // prompt
    std::cin >> number2;
    
    sum = number1 + number2;
    
    std::cout << "The sum is " << sum << std::endl;
    
    return 0;
}
```

- `>>` 串流擷取運算子（stream extraction operator）
- [C++ User Inputs](https://www.w3schools.com/cpp/cpp_user_input.asp)
- [C++ Data Types](https://www.w3schools.com/cpp/cpp_data_types.asp)
- [C++ Operators](https://www.w3schools.com/cpp/cpp_operators.asp)
    - 算術運算子
    - 指派運算子
    - 比較運算子
    - 邏輯運算子
    - 位元運算子

使用 `using namespace std;` 可以避免重複輸入 `std::`

```c++=
#include <iostream>
using namespace std;

int main() {
    // 變數宣告
    int number1;
    int number2;
    int sum;
    
    cout << "Enter first integer: ";  // prompt
    cin >> number1;
    
    cout << "Enter second integer: ";  // prompt
    cin >> number2;
    
    sum = number1 + number2;
    
    cout << "The sum is " << sum << endl;
    
    return 0;
}
```

## 5. 控制結構

在 C++ 中，控制結構用來改變程式的執行流程，常見的控制結構有 `if-else` 條件語句、`for` 和 `while` 迴圈等等。以下是各種控制結構的簡單介紹和範例：

### 5.1 **`if` 和 `else` 條件語句**
`if-else` 讓程式根據條件來決定執行哪一段程式碼。

```cpp
#include <iostream>
using namespace std;

int main() {
    int x = 10;

    if (x > 5) {
        cout << "x is greater than 5" << endl;
    } else {
        cout << "x is not greater than 5" << endl;
    }

    return 0;
}
```

- **`if`**：如果條件為真，執行 `{}` 中的程式碼。
- **`else`**：如果 `if` 條件不成立，則執行 `else` 中的程式碼。

### 5.2 **`else if` 條件語句**
`else if` 可以處理多個條件，讓程式根據不同情況執行不同程式碼。

```cpp
#include <iostream>
using namespace std;

int main() {
    int x = 10;

    if (x > 10) {
        cout << "x is greater than 10" << endl;
    } else if (x == 10) {
        cout << "x is equal to 10" << endl;
    } else {
        cout << "x is less than 10" << endl;
    }

    return 0;
}
```

### 5.3 **`for` 迴圈**
`for` 迴圈用來重複執行一段程式碼固定次數。

```cpp
#include <iostream>
using namespace std;

int main() {
    for (int i = 0; i < 5; i++) {
        cout << "Iteration " << i << endl;
    }

    return 0;
}
```

- 初始化 (`int i = 0`)：在迴圈開始前執行一次。
- 條件檢查 (`i < 5`)：每次執行迴圈前都會檢查，如果為真則執行迴圈。
- 增量 (`i++`)：每次迴圈執行後增加 `i`。

### 5.4 **`while` 迴圈**
`while` 迴圈會根據條件持續執行，直到條件為假。

```cpp
#include <iostream>
using namespace std;

int main() {
    int i = 0;

    while (i < 5) {
        cout << "Iteration " << i << endl;
        i++;  // 別忘記增加變數 i
    }

    return 0;
}
```

- **`while`**：只要條件為真，迴圈就會持續執行。

### 5.5 **`do-while` 迴圈**
`do-while` 迴圈至少會執行一次，然後檢查條件來決定是否繼續執行。

```cpp
#include <iostream>
using namespace std;

int main() {
    int i = 0;

    do {
        cout << "Iteration " << i << endl;
        i++;
    } while (i < 5);

    return 0;
}
```

- **`do-while`**：先執行 `do` 內的程式碼，再檢查 `while` 條件。


### 5.6 `switch` 結構

在 C++ 中，`switch` 是一種多重選擇控制結構，可以根據變數的值執行對應的程式碼塊。`switch` 常用來替代多個 `if-else if` 條件，當你的程式需要根據某一個變數的不同值來做不同的事情時，`switch` 可以讓程式碼更清晰和簡潔。

#### 基本語法：
```cpp
switch (expression) {
    case value1:
        // 當 expression 等於 value1 時執行這裡的程式碼
        break;
    case value2:
        // 當 expression 等於 value2 時執行這裡的程式碼
        break;
    // 可以有多個 case
    default:
        // 如果 expression 不符合任何 case，則執行這裡的程式碼
}
```

#### 注意事項
- `expression` 通常是一個整數或字元變數，不能是浮點數。
- `case` 表示對應的值，當 `expression` 的值和 `case` 的值匹配時，程式會執行對應的程式碼。
- `break` 用來結束 `switch`，否則程式會繼續執行下面的 `case`（稱為「貫穿」）。
- `default` 是可選的，當沒有任何 `case` 匹配時，執行 `default` 區塊內的程式碼。

#### 範例
```cpp
#include <iostream>
using namespace std;

int main() {
    int day = 3;

    switch (day) {
        case 1:
            cout << "Monday" << endl;
            break;
        case 2:
            cout << "Tuesday" << endl;
            break;
        case 3:
            cout << "Wednesday" << endl;
            break;
        case 4:
            cout << "Thursday" << endl;
            break;
        case 5:
            cout << "Friday" << endl;
            break;
        default:
            cout << "Invalid day" << endl;
    }

    return 0;
}
```

#### 說明
- 當 `day` 等於 `3` 時，程式會匹配 `case 3`，然後印出 "Wednesday"。
- `break` 是必要的，否則如果沒有 `break`，程式會繼續執行下一個 `case` 的程式碼。

#### 貫穿現象
如果沒有使用 `break`，`switch` 會出現貫穿現象，即使條件已經滿足，仍會繼續執行後續的 `case`。

```cpp
#include <iostream>
using namespace std;

int main() {
    int day = 2;

    switch (day) {
        case 1:
            cout << "Monday" << endl;
        case 2:
            cout << "Tuesday" << endl;
        case 3:
            cout << "Wednesday" << endl;
        default:
            cout << "Invalid day" << endl;
    }

    return 0;
}
```

這個程式會印出：
```
Tuesday
Wednesday
Invalid day
```

原因是 `switch` 在執行 `case 2` 後，沒有 `break`，因此繼續執行 `case 3` 和 `default` 區塊。

#### 總結：
- `switch` 提供了一種更清晰的方式來處理多重選擇情境，適用於值較固定的情況。
- 別忘了使用 `break` 來避免貫穿。
- `default` 區塊用來處理不符合任何 `case` 的情況。

這就是 C++ 中 `switch` 語句的基本使用方式。

## 程式練習 1 - 九九乘法表 

```c++=
#include <iostream>
using namespace std;

int main() {
    for (int i = 1; i < 10; i++) {
        for (int j = 1; j < 10; j++) {
            cout << i << '*' << j << '=' << i * j << endl;
        }
    }
    
    return 0;
}
```

## 程式練習 2 - 根據等第判斷成績範圍


```c++=
#include <iostream>
using namespace std;

int main() {
    char level;
    
    cout << "Enter your grade level: ";
    cin >> level;
    
    switch (level) {
        case 'A':
            cout << "Your grade is between 90 and 100";
            break;
        case 'B':
            cout << "Your grade is between 80 and 90";
            break;
        case 'C':
            cout << "Your grade is between 70 and 80";
            break;
        case 'D':
            cout << "Your grade is between 60 and 70";
            break;
        case 'F':
            cout << "Your grade is below 60";
            break;
        default:
            cout << "Invalid grade level!";
            break;
    }
    
    return 0;
}
```

## 程式練習 3 - 閏年判斷

如果年份「可被400整除」，或者「可被4整除，但不被100整除」，就是閏年；否則是平年。

```c++=
#include <iostream>
using namespace std;

int main() {
    int year;
    
    cout << "Enter a year: ";
    cin >> year;
    
    if ((year % 400 == 0 ) || (year % 4 == 0 && year % 100 != 0)) {
        cout << "It's a leap year." << endl;
    } else {
        cout << "It's a normal year." << endl;
    }
    
    return 0;
}
```

##  附錄 A. 補充資料

### 命名空間

在 C++ 中，**命名空間**（namespace）是一個用來組織程式碼的方式，避免名稱衝突。特別是在大型專案或有多個函式庫時，不同的程式碼可能會有相同的函式或變數名稱，這時可以使用命名空間來區分它們。

C++ 標準函式庫的 `std` 就是一個命名空間。你可以透過 `std::` 來存取標準庫中的函式和物件，例如 `std::cin` 和 `std::cout`。

#### 範例說明：

```cpp
#include <iostream>

int main() {
    int age;
    std::cout << "Enter your age: ";  // 使用 std 命名空間中的 cout
    std::cin >> age;  // 使用 std 命名空間中的 cin
    std::cout << "You are " << age << " years old." << std::endl;
    return 0;
}
```

在這個範例中，`std::cout` 和 `std::cin` 是分別位於 `std` 命名空間內的輸出和輸入函式。若不想每次使用 `std::`，你可以引入命名空間：

```cpp
#include <iostream>
using namespace std;  // 引入命名空間

int main() {
    int age;
    cout << "Enter your age: ";  // 不需要 std::
    cin >> age;
    cout << "You are " << age << " years old." << endl;
    return 0;
}
```

#### 為什麼需要 namespace？
當程式越來越大或引用多個函式庫時，可能會出現相同名稱的函式或變數。命名空間可以幫助將它們隔離，防止名稱衝突。例如：

```cpp
#include <iostream>

namespace A {
    void display() {
        std::cout << "Namespace A" << std::endl;
    }
}

namespace B {
    void display() {
        std::cout << "Namespace B" << std::endl;
    }
}

int main() {
    A::display();  // 呼叫 A 命名空間的 display
    B::display();  // 呼叫 B 命名空間的 display
    return 0;
}
```

在這個範例中，兩個命名空間 `A` 和 `B` 都有一個 `display` 函式，使用命名空間來區分它們，以避免函式名稱衝突。

## 附錄 B. 學習資源

以下是一些優質的 C++ 學習資源，適合從初學到進階不同階段的學習者：

### 線上教學網站
1. **[Cplusplus.com](http://www.cplusplus.com/doc/tutorial/)**
   - 提供詳細的 C++ 教程，從基礎語法到 STL（標準模板庫）的使用，適合初學者和中級學習者。

2. **[LearnCPP](https://www.learncpp.com/)**
   - 這個網站涵蓋了 C++ 的所有核心概念，從簡單的語法介紹到進階的物件導向編程、指標、範本等，適合循序漸進地學習。

3. **[Codecademy C++](https://www.codecademy.com/learn/learn-c-plus-plus)**
   - 互動式教學平台，通過實時練習來學習 C++，對於新手非常友好。

4. **[GeeksforGeeks C++](https://www.geeksforgeeks.org/c-plus-plus/)**
   - 涵蓋廣泛的 C++ 主題，從基礎知識到演算法和資料結構，並且有大量的範例程式碼和問題解答。

5. **[Udemy C++ Courses](https://www.udemy.com/topic/c-plus-plus/)**
   - Udemy 提供許多不同層次的 C++ 課程，包括基礎入門和高級專題，可以根據自己的需求選擇適合的課程。

### 書籍
1. **《[C++ Primer](https://www.tenlong.com.tw/products/9789865021726)》**（Stanley B. Lippman, Josée Lajoie, Barbara E. Moo）
   - 一本非常經典且全面的 C++ 入門書籍，適合剛接觸 C++ 的初學者以及希望加深基礎的學習者。

2. **《[Effective C++](https://www.tenlong.com.tw/products/9787121123320)》**（Scott Meyers）
   - 這本書涵蓋了許多 C++ 的最佳實踐，幫助你撰寫更高效、更可靠的程式碼，適合中級到進階的開發者。
   - [PDF](https://qjdxmy.com/download/effective-c++.pdf)

3. **《[The C++ Programming Language](https://www.books.com.tw/products/0010676898?srsltid=AfmBOoqhKTFdzDu0tJqRILiwo7GF_8U-XEwMioefk1ZM_kdCgmmUz6rO)》**（[Bjarne Stroustrup](https://www.stroustrup.com/)）
   - 由 C++ 創始人撰寫的書籍，深入介紹了語言的各個方面，適合進階學習者。

4. **《[C++ 標準庫－學習教本與參考工具](https://www.tenlong.com.tw/products/9789863474395)》**（[Nicolai M. Josuttis](https://www.josuttis.com/)）
   - 主要介紹 C++ 標準庫的使用，適合進階學習者或開發者。

5. **《[C++ 程式設計藝術](https://www.tenlong.com.tw/products/9789862803196)》**（[P. Deitel & H. Deitel](https://deitel.com/)）
    - 適合初學者和中級開發者深入理解 C++ 的核心概念與實踐應用。

### 練習平台
1. **[LeetCode](https://leetcode.com/problemset/all/)**
   - 提供各類演算法與資料結構問題，你可以使用 C++ 來解決問題並進行測試，適合提升程式設計技巧。

2. **[HackerRank](https://www.hackerrank.com/domains/tutorials/10-days-of-cpp)**
   - 10 Days of C++：專為 C++ 設計的挑戰，可以幫助你在 10 天內掌握 C++ 的基礎。

3. **[Exercism.io C++ Track](https://exercism.io/tracks/cpp)**
   - 一個開源的編程練習平台，提供 C++ 的實踐挑戰和社區代碼審查。

### 線上論壇與社群
1. **[Stack Overflow](https://stackoverflow.com/questions/tagged/c++)**
   - 當你遇到 C++ 問題時，這裡是尋求幫助的好地方，社群中有大量的 C++ 專家可以解答問題。

2. **[Reddit C++](https://www.reddit.com/r/cpp/)**
   - C++ 的討論區，分享資源、問題討論和最新技術動向。

透過這些資源，無論是初學者還是進階學習者都能找到合適的教材，並逐步提升 C++ 開發技巧。如果你有更具體的學習目標，我也可以推薦更針對性的資源！