---
# System prepended metadata

title: 【子柚程式】C++新手入門

---

# 前言
本文章宗旨為帶領新手入門C++，我會從0開始帶你了解C++，並且學習一些基礎應用，在接下來的程式教學中，為了節省版面，部分程式只會書寫主程式內的代碼，如果有需要運行的話，可以把等等要介紹的基本架構複製後，改掉main函數中的內容，就可以運行了。

# 基本架構
這是在各類程式中最一開始你會見到的基礎型，我們來簡單的了解一下架構。
```cpp=1
#include <bits/stdc++.h>
// 引入了C++中幾乎所有的宣告，我們才有辦法在接下來的程式中使用一些指令。

using namespace std;
// 使用標準函數庫

int main() {
    // main() 是 CPP 程式的起始函數
    // 主程式碼書寫區域

    return 0;
    // 回傳0表示程式執行完畢
}
```

# C++守則
在C++當中，有幾件你必須知道的事情：
1. 每寫完一行程式，就必須在那之後加上半形分號，才能繼續寫下一行，就跟我們寫作文需要逗號一樣，一個句子寫完就要有一個標點符號。
2. 基本上所有的大括號、小括號都是成雙成對存在。
3. 格式很重要！格式很重要！格式很重要！
4. 基本上在初學階段，你的所有程式都會寫在main裡面。

# Code::Blocks介紹
本次使用的軟體為Code::Blocks，不使用Visual Studio Code的原因是，在APCS的考試中不能使用。下載教學網路上都有，這邊不多做說明，如果啟動有看到下方這個，就選第三個就好了。
![1_lY3aD1ofoyKd2Ryv6pzulQ](https://hackmd.io/_uploads/S1N4T6S3R.png)

## 如何開始一個新的專案
步驟一：點擊新增檔案(下圖中紅色圈圈)
![步驟1](https://hackmd.io/_uploads/Sywry0Bn0.png)
步驟二：新增一個新的空白檔案(下圖中紅色框框)
![步驟2](https://hackmd.io/_uploads/rJ3Bk0Hn0.png)
步驟三：點擊儲存檔案(下圖中紅色圈圈)
![步驟3](https://hackmd.io/_uploads/rJx8y0B2A.png)
步驟四：取好檔名後在後方加上.cpp(下圖中紅色框框)
![步驟4](https://hackmd.io/_uploads/H1zL1RHnC.png)
這樣就完成啦！可以開始寫程式了！

## 快捷鍵介紹
下方是幾個常用的快捷鍵空能，建議背起來，能大幅提升效率喔。
| 按鍵 | 功能 |
| -------- | -------- |
| Tab | 空4格 |
| F9 | 執行 |
| Ctrl+C | 複製 |
| Ctrl+V | 貼上 |
| Ctrl+Z | 上一步 |

# 格式
格式是為了讓版面看起來更舒服，下方幾點為常見格式要求：
1. 每進入一個大括號就要空4格(按一下Tab)。
2. 通常在每個符號前後會空1格。
```cpp=1
#include <bits/stdc++.h>

using namespace std;

int main() {
    int a;
    cin >> a;
    if (條件) {
        if (條件) {
            if (條件) {
                cout << "字串";
            }
            else {
                cout << "字串";
            }
        }
        else {
            cout << "字串";
        }
    }
    else {
        cout << "字串";
    }
    return 0;
}
```
下方為錯誤示範，程式一樣可以運行沒錯，但出現BUG的時候會很難找錯誤，易讀性大大降低。
```cpp=1
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a;
cin>>a;
if(條件){
if(條件){
if(條件){
cout<<"字串";
}
else{
cout<<"字串";
}
}
else{
cout<<"字串";
}
}
else{
cout<<"字串";
}
return 0;
}
```
# 變數宣告
變數宣告的功能就是讓電腦幫你記憶一個變數，但在電腦程式中，我們需要詳細的定義這個變數的性質。
| 名稱 | 類型 | 範圍 |
| -------- | -------- | -------- |
| int | 整數 |-2^31 ~ 2^31-1 |
| long long | 長整數  |-2^63 ~ 2^63-1 |
| float | 浮點數 | 小數點後第七位 |
| double | 雙精度浮點數 | 小數點後第十五位 |
| char | 字元 | 一個字元 |
| string | 字串 | 多個字元 |
| bool | 布林值 | 0(代表false)1(代表true) |

以下是變數宣告的示範：
```cpp=1
#include <bits/stdc++.h>

using namespace std;

int main() {
    // 整數
    int myInt = 42; 

    // 長整數
    long long myLongLong = 123456789012345; 

    // 浮點數
    float myFloat = 3.14; 

    // 雙精度浮點數
    double myDouble = 2.718281828459045; 

    // 字元
    char myChar = 'Z'; 

    // 字串
    string myString = "Learning C++"; 

    // 布林值
    bool myBool = false; 

    // 顯示變數的值
    cout << "int: " << myInt << endl;
    cout << "long long: " << myLongLong << endl;
    cout << "float: " << myFloat << endl;
    cout << "double: " << myDouble << endl;
    cout << "char: " << myChar << endl;
    cout << "string: " << myString << endl;
    cout << "bool: " << (myBool ? "true" : "false") << endl; //看不懂沒關係

    return 0;
}
```
### 輸出結果
```
int: 42
long long: 123456789012345
float: 3.14
double: 2.71828
char: Z
string: Learning C++
bool: false
```
## 想一想
1. 變數超出該類型的範圍會發生什麼事呢？（例如 int a = 9999999999999999999，這樣子再輸出 a 會得到什麼呢？）

## 想一想-解答
當變數超出其範圍時，會發生溢出（overflow）。這種情況下，變數會回繞至該型別的最小值或最大值附近，導致結果不正確。具體的行為取決於平台和編譯器，但通常遵循以下模式：
* 正溢出：以 int 舉例，當一個數值超過 int 的最大值時，它會回繞到最小值。假設你的 int 最大值是 2,147,483,647，若將其增加 1，如下方：
```cpp=1
#include <bits/stdc++.h>

using namespace std;

int main() {
    int maxInt = 2147483647;  // int 的最大值2^31-1
    cout << "Before overflow: " << maxInt << endl;
    maxInt++;
    cout << "After overflow: " << maxInt << endl;
    return 0;
}
```
### 輸出結果
```
Before overflow: 2147483647
After overflow: -2147483648
```
* 負溢出：以 int 舉例，當一個數值低於 int 的最小值時，它會回繞到最大值。假設你的 int 最小值是 -2,147,483,648，若將其減少 1，如下方：
```cpp=1
#include <bits/stdc++.h>

using namespace std;

int main() {
    int minInt = -2147483648;  // int 的最小值-2^31
    cout << "Before overflow: " << minInt << endl;
    minInt--;
    cout << "After overflow: " << minInt << endl;
    return 0;
}
```
### 輸出結果
```
Before overflow: -2147483648
After overflow: 2147483647
```

# 變數範圍
變數根據宣告的位置，可以決定有多少程式碼「認識它」，舉個例子，就像是你在班上自我介紹，但是隔壁班同學不會認識你一樣，如果你在全校面前自我介紹，那隔壁班同學就會認識你。而在程式中，我們稱之為「全域變數」和「區域變數」。
```cpp=1
#include <bits/stdc++.h>

using namespace std;

int m=20; //全域變數

void add(){
    int p=30; //區域變數
}

int main(){
    int n=10; //區域變數
    for(int i=0;i<10;i++){ //迴圈變數
        i=i+n;
    }
    return 0;
}
```

## 想一想
1. 上方那些變數可以在main函數中輸出呢？

## 想一想-解答
答案是 m 和 n 喔！

# 輸出指令-cout
cout 可以將一些資訊輸出到螢幕上，如果是字串，就要用" "框起來，如果是變數就不用。
```cpp=1
int a = 10;
string s = "電腦研習社 讚！"
    
cout << "資訊" << endl;
cout << s << endl;
cout << a;
```
### 輸出結果
```
資訊
電腦研習社 讚！
10
```

若要輸出更多資訊，又不想打很多 cout，則可以使用連續輸出。
```cpp=1
cout << "第一個資訊" << "第二個資訊" << "第三個資訊";
```
若想將輸出的內容分行，可以使用指令 endl。
```cpp=1
cout << "第一個資訊" << endl << "第二個資訊" << endl << "第三個資訊";
```
這邊需要注意的就是 << 的方向，不要跟接下來的 cin搞錯了。

## 高手過招
如果希望輸出指定位數的小數，可以使用 setprecision()，具體可參考下方寫法：
```cpp=1
#include <bits/stdc++.h>

using namespace std;

int main() {
    double num = 123.456789;

    // 顯示 3 個有效數位
    cout << setprecision(3) << num << endl;
    
    // 顯示小數點後 3 位
    cout << fixed << setprecision(3) << num;

    return 0;
}
```
### 輸出結果
```
123
123.457
```

# 輸入指令-cin
cin 可以將你輸入的內容儲存到變數中，換句話說，你必須先宣告一個變數，才能使用 cin。
```cpp=1
int a;
cin >> a;
```
如同 cout，cin 也可以做連續輸入。
```cpp=1
int a, b, c;
cin >> 變數a >> 變數b >> 變數c;
```
這邊會出現的問題，大概就是 >> 和 << 弄混了吧！

## 題目練習
[A0001-教師示範程式](https://code.dali.tc.edu.tw/problem/A0001)

---

# 運算子
運算子幫助我們進行簡單的運算，或者是邏輯的判別。
| 符號 | 意思 |
| -------- | -------- |
| = | 設為 |
| == | 相等 |
| ++ | 遞增 |
| ╴╴ | 遞減 |
| > | 大於 |
| < | 小於 |
| >= | 大於等於 |
| <= | 小於等於 |
| != | 不等於 |
| && | 而且 |
| ｜｜ | 或者 |
| ! | 非 |

值得注意的是，輸出運算結果時，並不需要加上" "，否則會變成字串輸出，例如下方：
```cpp=1
#include <bits/stdc++.h>

using namespace std;

int main(){
    int a,b;
    a=5,b=3;
    cout << a+b << endl;
    cout << "a+b";
    return 0;
}
```
### 輸出結果
```
8
a+b
```

## 高手過招
* 若需使用較難的數學計算，可以在開頭先加入 #include <math.h>。
* 常用的計算函數像是 abs(x)、sqrt(x)、pow(x,n)等等，有興趣可以去學起來。

## 題目練習
[A0002-第一個線上程式](https://code.dali.tc.edu.tw/problem/A0002)

---

# 選擇結構
在寫判定式時，須注意格式，小括號內放的是條件，大括號內放的是執行內容。

## if
if 就是我們口頭上說的「如果...」，當我們給予的「條件」成立時，程式就會執行你指定的「內容」，反之，程式將會跳過這個判定式。
```c++=1
if(條件){
    執行內容
}
```

## if-else
if-else 就是我們口頭上說的「如果...否則...」，當我們給予的「條件」成立時，程式就會執行你指定的「內容」，反之，條件不成立時，程式將會執行 else 的部分。
```c++=1
if(條件){
    執行內容
}
else{
    執行內容
}
```

## else if
else if 通常用在需假設的條件數量 >=3 時，其意思和 if相同。
```c++=1
if(條件){
    執行內容
}
else if(條件){
    執行內容
}
else{
    執行內容
}
```

## 想一想
1. 如果有不止三種情況的話，該怎麼辦呢？
2. 一定要有 else 嗎？
3. 如果同時符合兩個條件的時候，會執行哪一個？

## 高手過招
三元運算符（ternary operator）是一種簡化的條件表達式，這個表達式在APCS觀念題很愛考。
```
condition ? expression1 : expression2
```
* condition：一個布林表達式，評估為 true 或 false。
* expression1：如果 condition 為 true，則運算結果為這個表達式的值。
* expression2：如果 condition 為 false，則運算結果為這個表達式的值。

## 題目練習
[A0006-分數的等第](https://code.dali.tc.edu.tw/problem/A0006)

---

# 重複迴圈
重複迴圈主要用來執行相同或有連續性的程式，它化簡了我們程式的長度，重複迴圈主要有以下幾個架構：
1. 執行條件
2. 重複次數
3. 執行內容

這三個東西在等一下的三種迴圈中會使用到，也是重複迴圈的核心概念所在。

## for
for 迴圈通常用在已知道重複次數的情況下，它的格式如下。
```c++=1
for(起始值;執行條件;一輪結束後起始值的變量){
    執行內容
}
//舉例
for(int i=0;i<5;i++){
    cout << i << endl;
}
/*
i的起始值為0，每經過一次循環+1，當i小於5時執行
第一round i=0 輸出0
第二round i=1 輸出1
第三round i=2 輸出2
第四round i=3 輸出3
第五round i=4 輸出4
第六round i=5 因為執行條件為i小於5時執行 故迴圈終止
*/
```
特別注意執行條件的部分，若條件沒給好，有可能導致迴圈無法正常執行或導致無窮迴圈。
```c++=1
for(int i=0;i>=0;i++){
    cout << i << endl;
}
//因為i>=0恆成立，所以此迴圈為無窮迴圈，不會終止
for(int i=0;i<0;i++){
    cout << i << endl;
}
//因為i<0恆不成立，所以此迴圈不會執行
```

## 想一想
1. 下方程式碼的輸出結果會是什麼呢？為什麼會這樣子？
```c++=1
int i;
for(i=0;i<10;i++){
    cout << i << endl;
}
cout << endl;
for(int j=0;j<5;j++){
    cout << j << endl;
}
cout << endl;
cout << i;
cout << j;
```

## 題目練習
[A0012-質數判斷](https://code.dali.tc.edu.tw/problem/A0012)

---

## while
while 迴圈通常用在不知道重複次數，只知道執行條件的情況下。
```c++=1
while(執行條件){
執行內容
}
```
當執行條件成立的情況下，while 迴圈便會一直執行。
```c++=1
int n=10;
while(n>0){
cout << n << endl;
n--;
}
```
### 執行結果
```
10
9
8
7
6
5
4
3
2
1
```

## do-while
do-while 和 while 迴圈最大的不同是，它不論如何都會先執行一次，才進行條件判斷。
```c++=1
do{
執行內容
}while(執行條件);
```
所以就算不符合執行條件，也會執行一次後才終止。
```c++=1
int n=10;
do{
cout << n << endl;
n--;
}while(n<0);
```
### 執行結果
```
10
```

## 題目練習
[A0008-兩數互質嗎?](https://code.dali.tc.edu.tw/problem/A0008)

---

# break and continue
這兩者主要用在重複迴圈內，特定條件下需要終止或者跳過這次迴圈所使用，以下用一個例子來說明。
```c++=1
for(int i=0;i<3;i++){
    for(int j=0;j<3;j++){
    cout << i << " " << j << endl;
    }
}
```
### 執行結果
```
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
```

##  break
break 是用來終止迴圈的，可以終止「最近的一層迴圈」，通常搭配 if 做使用。
```c++=1
for(int i=0;i<5;i++){
    if(i==3){
        break;
    }
    cout << i << endl;
}
```
### 執行結果
```
0
1
2
```

## 想一想
1. 下方這段程式的輸出結果是什麼呢？
```c++=1
for(int i=0;i<3;i++){
    for(int j=0;j<3;j++){
    cout << i << " " << j << endl;
    break;
    }
}
```

## 題目練習
[A0014-算術基本定理](https://code.dali.tc.edu.tw/problem/A0014)

---

## continue
continue 是用來「跳過」這一次的迴圈的，通常搭配 if 做使用。
```c++=1
for(int i=0;i<3;i++){
    for(int j=0;j<3;j++){
    if(j==2){
        continue;
    }
    cout << i << " " << j << endl;
    }
}
```
### 執行結果
```
0 0
0 1
1 0
1 1
2 0
2 1
```

# 一維陣列
白話：有一棟名字叫 a 的大樓，裡面有 n 個房間，每間房間裡面有放東西。
程式：如下
```c++=1
int a[n]={資料,資料,資料,資料,資料};
```
圖解：如下
![image](https://hackmd.io/_uploads/ByocuyI5p.png)

## 陣列的編碼
陣列的編號在程式中是從 0 開始，所以第一間房間叫做 a[0]，第二間叫做 a[1]，以此類推。所以一個陣列 a[n]總共可以存放 n 筆資料，第一筆資料叫做 a[0]，最後一筆資料叫做 a[n-1]。

## 陣列的輸入
大多時候我們並不是一開始就知道陣列中的數字，也不知道有幾項，而是需要使用者輸入，遇到這種情況，我們可以這麼做：
```c++=1
int n;
cin >> n;
//n代表有幾筆資料
int a[n]={};
//建立一個長度為n的空陣列
for(int i=0;i<n;i++){
    cin >> a[i];
    //輸入每一間房間的數字
}
```
上方這個範本之後會大量的出現在題目之中，一定要記起來！

## 陣列的輸出
陣列的輸出相對簡單，以下這段程式建立了一個名字叫做 a，用來儲存整數的一維陣列，並且將陣列中的每一項輸出。
```c++=1
int a[5]={10,20,30,40,50};
for(int i=0;i<5;i++){
    cout << a[i] << endl;
}
```
### 執行結果
```
10
20
30
40
50
```
## 想一想
1. 如果我只宣告了 int a[5]，但 cout << a[13]，會得到什麼結果呢？結果一定是 0 嗎？

## 陣列的運算
陣列中存放的資料可以透過運算子進行運算（忘了運算子是什麼可以回上面找）。
```c++=1
int a[5]={10,20,30,40,50};
cout << a[1]+a[2] << endl;
//20+30=50
cout << a[3]-a[2] << endl;
//40-30=10
cout << a[1]*a[4] << endl;
//20*50=1000
cout << a[4]/a[0] << endl;
//50/10=5
```
### 執行結果
```
50
10
1000
5
```

## 題目練習
[APCS-o076. 1. 特技表演](https://zerojudge.tw/ShowProblem?problemid=o076)

---

# 二維陣列
二維陣列你可以將他理解成多個一維陣列所拼湊起來的陣列，他有類似於數學的X,Y軸，只不過需要特別注意，在二維陣列中，左上角為原點 (0,0) ，往右跟往下都是正的。
![image](https://hackmd.io/_uploads/HJINdkL9a.png)
## 陣列的輸入與輸出
如同一維陣列，我們並不一定會事前知道陣列中的資料，所以我們通常用下方的這個格式來處理大多數二維陣列的問題：
```c++=1
int n,m;
cin >> n >> m;
//n,m代表陣列長寬
int a[n][m];
//建立一個n*m大小的空陣列
for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
        cin >> a[i][j];
        //輸入每一個陣列的資料
    }
}
for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
        cout << a[i][j];
        //輸出每一個陣列的資料
    }
}
```
我們使用了雙重 for 迴圈來拜訪到二維陣列中的每一格，這個寫法會很常出現在二維陣列中。

## 題目練習
[APCS-o077. 2. 電子畫布](https://zerojudge.tw/ShowProblem?problemid=o077)

---

# 小結
到這邊C++的新手教學差不多告一段落了，如果都看得懂的話，你可以嘗試去zerojudge上解題，以APCS的程度來分級的話，現在的你應該有接近3級分的程度了！已經超越了一半以上的高中生了喔！希望你對程式設計的熱誠不要消失，網路上有許多資源可以學習，我也會繼續學習，期待下一篇筆記能教導更多更進階的程式內容。

---

# 連結
* [SHCH Online Judge參考解答(教學版)](https://hackmd.io/@37aitHUHRnKghKiwEbbHmg/r1cT1qEhA)
* [SHCH Online Judge](https://code.dali.tc.edu.tw/)
* [ZeroJudge](https://zerojudge.tw/)
* [AP325](https://jmj.cmgsh.tp.edu.tw/files/AP325_v1.3.pdf)
* [Yui Huang 演算法學習筆記](https://yuihuang.com/)