無所不在的C++ - 新手村 === ###### tags: `程式設計` `cpp` :::success 🤖 本篇由 [**chatGPT**](https://platform.openai.com/) 及 [**Mai.Coding**](https://hackmd.io/@0x0607) 共同彙整 目前不考慮出第二篇,統整資料好累 ::: # **認識C++** :::info 💡 介紹一些關於C++的故事及特色 ::: ## **C++歷史** * **C++** 最早是由 Bjarne Stroustrup 於 **1983** 年開發的,當時其名為 **C with Classes**。 * **1985 年**,Bjarne Stroustrup 將 **C with Classes** 重新命名為 **C++**,並在同年發布了第一個 **C++** 版本。 * **C++** 廣泛應用於**系統軟體**、**桌面應用程式**以及**遊戲開發等方面**。 ## **C++語言特性** * **物件導向**:C++ 語言支援物件導向設計,可以將相關的變數和函式封裝在一個物件中。 * **封裝 (Encapsulation)**:可以將成員變數和成員函式封裝在一個類中,只提供必要的接口給外部。 * **繼承 (Inheritance)**:子類可以繼承父類的屬性和方法。 * **多型 (Polymorphism)**:同一個函式可以被不同的子類實現,並且可以按照類型自動選擇合適的實現方式。 ## **C++程式類型** * **C++ Application**:獨立運行在電腦上的 C++ 程式。 * **C++ Library**:可以被其他 C++ 程式引用的庫文件。 * **Driver:驅動程式**,用於控制硬體設備。 * **Kernel**:核心程式,用於管理電腦資源和運行其他程式。 ## **C++開發環境** * **IDE**:如 Microsoft Visual Studio、CodeLite、Xcode。 * **編譯器**:如 Microsoft Visual C++、GNU GCC。 * **編輯器**:如 Notepad++、Vim、Emacs。 ## **其他關於C++知識** ### **高效能** C++ 被稱為高效能的程式語言,因為其原始碼可以直接編譯成機器語言, 運行**速度快**,**佔用資源少**,且通常比其他高階語言更適合系統軟體和遊戲開發等場合。 ### **開發流程** C++ 的開發流程通常包括項目**規劃**、**設計**和**實現**、**測試**和**調試**以及**部署**和**維護**等階段。 在每個階段都需要開發人員進行經驗和技能的分工協作,以確保最終產品的品質和效率。 ### **庫文件** C++ 語言有許多可以重用代碼的庫文件,可以大大簡化開發人員的工作, 常見的庫文件有**標準庫**、**系統庫**、**框架庫**、**第三方庫**等等。 ### **跨平台** C++ 語言在原始碼級別上具有跨平台特性,但也因此需要特別注意程式碼的可移植性, 以適應不同的操作系統和硬件環境。 # **變數(Variables)** :::info 變數是儲存資料的單位,每個變數都有各自的名稱與資料型態。 在 C++ 中,變數必須先宣告才能使用。 ::: ## **變數宣告(Declaration)** 變數宣告的目的是告知電腦,程式中要使用哪些變數,並配置記憶體以供存放。 變數必須在第一次使用前宣告。 變數宣告的語法如下: ```cpp= DataType VarName [= Initial Value]; ``` - **DataType**:變數的資料型態,例如 `int`、`double` 等。 - **VarName**:變數的名稱,可以是任何合法的識別字,建議使用有意義的名稱。 - **Initial Value**:變數的初始值,可以省略不寫。 如果省略不寫,則變數的初始值為 `0`(數值類型)或 `null`(物件類型)。 以下是一個變數宣告的範例: ```cpp= int a = 24; double b; ``` 在這個範例中,我們宣告了兩個變數 `a` 和 `b`。 `a` 的資料型態為 `int`,初始值為 `24`。 `b` 的資料型態為 `double`,沒有初始值。 ## **變數命名規則** 在 C++ 中,變數的命名規則如下: - 變數名稱必須以`字母`或`底線`開頭。 - 變數名稱不能以`數字`開頭。 - 變數名稱只能包含`字母`、`數字`或`底線`。 - 變數名稱不能是 C++ 的關鍵字(例如 `int`、`double` 等)。 ## **資料型態** 以下這些基本資料型態是 C++ 語言中最基本的資料型態,用來儲存各種不同的資料。 在宣告變數時,**必須**指定變數的**資料型態**。 ### **整數型態** 在 C++ 中,整數型態用來儲存整數,包括`正整數`、`負整數`和`零`。整數型態在不同的系統和編譯器中可能大小不同,但通常包括 `char`、`short`、`int` 和 `long` 四種。 | 資料型態 | 描述 | 長度(位元組) | 範圍 | | --- | --- | --- | --- | | **short** | `16` 位元的`有符號整數` | 2 | `-32,768` 到 `32,767` | | **int** | `32` 位元的`有符號整數` | 4 |`-2,147,483,648` 到 `2,147,483,647` | | **long** | `64` 位元的`有符號整數` | 8 | `-9,223,372,036,854,775,808` 到 `9,223,372,036,854,775,807` | 宣告範本: ```c short s = 88; int i = 88; long l = 88L; ``` ### **浮點型態** 在 C++ 中,浮點型態用來儲存浮點數,包括`正數`、`負數`和`零`。浮點型態在不同的系統和編譯器中可能大小不同,但通常包括 `float` 和 `double` 兩種。 | 資料型態 | 描述 | 長度(位元組) | 範圍 | | --- | --- | --- | --- | | **float** | `單精度浮點數` | 4 | 可儲存 `6` 個有效位數 | | **double** | `雙精度浮點數` | 8 | 可儲存 `15` 個有效位數 | 宣告範本: ```c float f = 3.141f; double d = 3.141; ``` ### **字元型態** 在 C++ 中,字元型態用來儲存單個字符,包括`字母`、`數字`、`符號`和`控制字符`。字元型態為 `char`。 宣告範本: ```c char c = 'a'; ``` ### **字串型態** 在 C++ 中,字串型態用來儲存一序列的字元,類型為 `string`。字串是以雙引號或單引號表示的,透過這個型態來儲存**任意長度**的文字。 宣告範本: ```cpp string s = "Hello World!"; ``` :::spoiler :::info 值得注意的是`string`這個型態在C語言中是**沒有**的,而C語言則是使用`字元陣列`來處理字串 ::: ### **布林型態** C 語言中**沒有**內建的布林型態,通常可以使用 `int` 來儲存布林值, `0` 代表 `false`,非 `0` 值代表 `true`。 宣告範本: ```c int b = 1; ``` ## **溢位(Overflow)** 溢位是一種當數值超過資料型態範圍的錯誤。在 C++ 中,每種資料型態都有其範圍限制,如果資料型態無法容納某個數值,則會發生溢位錯誤。溢位錯誤可能會導致程式產生不正確的結果,因此在實際開發中應該避免使用可能導致溢位的操作。 以下是各種資料型態的範例程式,用來示範溢位錯誤: ```c // char 溢位 char c = 127; c++; std::cout << c << std::endl; // -128 // short 溢位 short s = 32767; s++; std::cout << s << std::endl; // -32768 // int 溢位 int i = 2147483647; i++; std::cout << i << std::endl; // -2147483648 // long 溢位 long l = 9223372036854775807L; l++; std::cout << l << std::endl; // -9223372036854775808 // float 溢位 float f = __FLT_MAX__; f *= 2; std::cout << f << std::endl; // inf // double 溢位 double d = __DBL_MAX__; d *= 2; std::cout << d << std::endl; // inf ``` 在這些範例中,我們使用了各種資料型態的最大值,然後將其加上 `1` 或乘以 `2`,以引發溢位錯誤。 當發生溢位時,資料型態的值會從最大值變成最小值,或從最小值變成最大值,因此會產生不正確的結果。 在實際開發中,我們應該避免使用可能導致溢位的操作,以確保程式的正確性。 ## **常數(constant)** 在 C++ 中,我們可以使用 `const` 來聲明常數,它指向的變數是**不可改變**的。 一旦使用 `const` 關鍵字聲明了一個變數,其值就不可再更改。 定義一個常數的語法如下: ```cpp const DataType VarName = InitialValue; ``` `DataType` 是指變數的資料型別。 `VarName` 是變數的名稱。 `InitialValue` 是變數的初始值。 以下是一個常數的範例: ```cpp const double PI = 3.1415; ``` :::info 在這個範例中,`PI` 被聲明為一個常數,其值為 `3.1415`。 由於 `PI` 是一個常數,所以在程式執行過程中其值不會改變。 ::: 如果在程式碼中試圖更改 PI 的值,例如: ```cpp const double PI = 3.1415; PI = 5.4321; ``` :::danger 則會在編譯時期產生錯誤。 ::: 需要補充的是,C++ 中的常數通常使用全部大寫字母表示,並使用底線分隔單詞,例如 `CURRENT_USER_NUM`。 此外,常數的命名應該具有**描述性**,以便於程式碼的閱讀和理解。 # **運算子(Operator)** :::info 運算子是在程式語言中用來執行特定操作的符號或關鍵字, 例如數學運算、邏輯運算、位元運算等。 每一種運算子都有其特定的功能和用法,並且可以應用在不同的資料型別上。 ::: ## **類型** C++ 中的運算子可對一個、兩個或三個運算元執行動作。 依照所需運算元數目,運算子可分為以下**三種**: * **一元運算子**:只需要**一**個運算元,對變數進行**遞增/遞減**操作, 例如 `++a`、`--a`。 * **二元運算子**:需要**兩**個運算元,將**右邊**的運算元**賦值**給**左邊**的運算元, 例如 `a = 99`。 * **三元運算子**:需要**三**個運算元,語法為 `condition ? expression1 : expression2`, 其中 `condition` 為條件,如果條件成立,則回傳 expression1 的值, 否則回傳 `expression2` 的值,例如 `(a>0) ? a-1 : (a+1)`。 另外,許多二元運算子都可以分成**算術運算子**、**關係運算子**和**邏輯運算子**這三種大類。 依照運算子擺放位置,運算子可分為以下**三種**: **前置運算子**:運算子擺放在運算元之**前**,例如 `++a`。 **後置運算子**:運算子擺放在運算元之**後**,例如 `a++`。 **中置運算子**:運算子擺放在**中間**,例如 `a + b`。 ### **算術運算子** #### **單一運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | + | +a | 表示正 a | | - | -a | 表示負 a | | ! | !a | 表示邏輯非,將 a 的值取反 | | ~ | ~a | 表示位元反轉,將 a 的二進位表示法的每個位元取反 | | ++ | a++ 或 ++a | 表示將 a 的值加 1,若放在 a 的後面則先回傳 a 的值再加 1,若放在 a 的前面則先加 1 再回傳 a 的值 | | -- | a-- 或 --a | 表示將 a 的值減 1,若放在 a 的後面則先回傳 a 的值再減 1,若放在 a 的前面則先減 1 再回傳 a 的值 | #### **二元運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | + | a + b | a 加上 b | | - | a - b | a 減去 b | | * | a * b | a 乘上 b | | / | a / b | a 除以 b | | % | a % b | a 除以 b 的餘數 | ### **指定運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | = | a = b | 將 b 的值賦給 a | | += | a += b | 將 a 加上 b 的值後再賦給 a | | -= | a -= b | 將 a 減去 b 的值後再賦給 a | | \*= | a \*= b | 將 a 乘上 b 的值後再賦給 a | | /= | a /= b | 將 a 除以 b 的值後再賦給 a | | %= | a %= b | 將 a 除以 b 的餘數再賦給 a | ### **關係運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | == | a == b | 判斷 a 是否等於 b,若成立則回傳 true,否則回傳 false | | != | a != b | 判斷 a 是否不等於 b,若成立則回傳 true,否則回傳 false | | < | a < b | 判斷 a 是否小於 b,若成立則回傳 true,否則回傳 false | | <= | a <= b | 判斷 a 是否小於等於 b,若成立則回傳 true,否則回傳 false | | > | a > b | 判斷 a 是否大於 b,若成立則回傳 true,否則回傳 false | | >= | a >= b | 判斷 a 是否大於等於 b,若成立則回傳 true,否則回傳 false | ### **條件運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | && | a && b | 邏輯 AND,若 a 和 b 都成立則回傳 true,否則回傳 false | | \|\| | a \|\| b | 邏輯 OR,若 a 或 b 有一個成立則回傳 true,否則回傳 false | ### **邏輯運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | ! | !a | 表示邏輯非,將 a 的布林值取反 | | & | a & b | 位元 AND,將 a 和 b 的二進位表示法進行 AND 運算 | | \| | a \| b | 位元 OR,將 a 和 b 的二進位表示法進行 OR 運算 | | ^ | a ^ b | 位元 XOR,將 a 和 b 的二進位表示法進行 XOR 運算 | ### **位元運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | << | a << b | 左位移,將 a 的二進位表示法向左移動 b 個位元 | | >> | a >> b | 右位移,將 a 的二進位表示法向右移動 b 個位元 | | ~ | ~a | 取補數,將 a 的二進位表示法進行 NOT 運算 | | & | a & b | 二進位 AND,將 a 和 b 的二進位表示法進行 AND 運算 | | \| | a \| b | 二進位 OR,將 a 和 b 的二進位表示法進行 OR 運算 | | ^ | a ^ b | 二進位 XOR,將 a 和 b 的二進位表示法進行 XOR 運算 | ### **進階指定運算子** | 運算子 | 用法 | 說明 | | --- | --- | --- | | &= | a &= b | 將 a 和 b 的二進位表示法進行 AND 運算後再賦給 a | | \|= | a \|= b | 將 a 和 b 的二進位表示法進行 OR 運算後再賦給 a | | ^= | a ^= b | 將 a 和 b 的二進位表示法進行 XOR 運算後再賦給 a | | <<= | a <<= b | 將 a 的二進位表示法向左移動 b 個位元後再賦給 a | | >>= | a >>= b | 將 a 的二進位表示法向右移動 b 個位元後再賦給 a | | &= | a &= b | 將 a 和 b 的二進位表示法進行 AND 運算後再賦給 a | | \|= | a \|= b | 將 a 和 b 的二進位表示法進行 OR 運算後再賦給 a | | ^= | a ^= b | 將 a 和 b 的二進位表示法進行 XOR 運算後再賦給 a | | <<= | a <<= b | 將 a 的二進位表示法向左移動 b 個位元後再賦給 a | | >>= | a >>= b | 將 a 的二進位表示法向右移動 b 個位元後再賦給 a | # **程式區塊 (Blocks)** :::info 程式區塊是以 `{}` 大括號包覆而成,可以內含零個或以上的敘述。 通常在條件判斷語句中使用,例如 if 判斷句,若條件成立,就會執行 `{}` 內包含的敘述,否則略過。 在許多程式語言中,程式區塊還會配合分號 `;` 結束敘述,確保程式碼的正確執行。 ::: 範例: ```cpp= if (a > 2) { // 如果 a 大於 2,則執行以下程式區塊內的敘述 cout << "a is greater than 2." << endl; } else { // 如果 a 小於等於 2,則執行以下程式區塊內的敘述 cout << "a is less than or equal to 2." << endl; } ``` 在程式區塊的 `{}` 內也可以包含其他的程式區塊,例如**多層迴圈**、**巢狀**的**if 判斷**等等,只要在不同層次的程式區塊中使用不同的變數名稱,即可避免變數名稱衝突的問題。 # **程式流程(Program-flow)** :::info 程式可以使用結構化的方式來表達流程,讓程式碼更易讀、易維護 ::: ## **循序結構** 循序結構是程式中最簡單的結構之一,它**按照順序執行敘述**,從上到下按照程式碼的順序執行,沒有任何的分支或迴圈。 以下是一個簡單的 C++ 程式碼示例: ```cpp= int a = 1; int b = 2; int c = a + b; cout << c; ``` ## **選擇結構** 選擇結構基於條件來決定程式的執行路徑,當條件滿足時執行 `A 敘述`,否則執行 `B 敘述`。 下面是一個簡單的 `if-else` 選擇結構的例子: ```cpp= int x = 5; if (x > 0) { cout << "x 是一個正數"; } else { cout << "x 不是一個正數"; } ``` ## **重複結構** 重複結構可以讓程式重複執行某些敘述,以達到簡化程式碼的目的。 以下是一個簡單的 `while` 迴圈重複結構的例子: ```cpp= int i = 0; while (i < 9) { cout << i; i++; } ``` 此迴圈會進行 `5` 次迴圈,每次迴圈都會把目前的數字印出來,直到迴圈次數到達 `5` 次為止。 # **基本語法(Basic)** :::info 💡 開始寫程式囉 ::: ## **if-else和switch** `if-else` 和 `switch` 都是在程式中用來進行條件判斷的關鍵字。 ### **if-else** `if-else` 在條件成立時執行一段程式碼,反之則執行另外一段程式碼。 ```cpp= if (score >= 60) { cout << "pass" << endl; } else { cout << "fail" << endl; } ``` ## **switch** `switch`可以根據變數的值執行對應的程式碼。 ```cpp= switch (keyCode) { case 37: moveLeft(); break; case 38: moveUp(); break; case 39: moveRight(); break; case 40: moveDown(); break; default: cout << "invalid key" << endl; break; } ``` ## **輸入(Input)** 在C++中,使用`cin`來接收使用者的輸入。 使用時需先引入`<iostream>`標頭檔。 ```cpp= #include <iostream> using namespace std; int main() { int num; cout << "請輸入一個整數:"; cin >> num; cout << "你輸入的整數是:" << num << endl; return 0; } ``` 在上面的程式碼中,我們先宣告一個整數變數`num`。 然後使用`cout`輸出提示使用者輸入的訊息。 接下來使用`cin`來接收使用者輸入的整數, 並將其賦值給`num`變數。 ## **輸出(Output)** 在C++中,你可以使用`cout`來輸出訊息到控制台上。 ```cpp= #include <iostream> using namespace std; int main() { cout << "Hello, World!" << endl; return 0; } ``` 輸出結果: ```bash Hello, World! ``` `cou`t是標準輸出流,是C++中最常用的輸出方法之一。 它可以幫助你將訊息輸出到控制台上,而`endl`可以輸出**換行符號**,使輸出結果更加美觀。