# 前言
本文章宗旨為帶領新手入門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的考試中不能使用。下載教學網路上都有,這邊不多做說明,如果啟動有看到下方這個,就選第三個就好了。

## 如何開始一個新的專案
步驟一:點擊新增檔案(下圖中紅色圈圈)

步驟二:新增一個新的空白檔案(下圖中紅色框框)

步驟三:點擊儲存檔案(下圖中紅色圈圈)

步驟四:取好檔名後在後方加上.cpp(下圖中紅色框框)

這樣就完成啦!可以開始寫程式了!
## 快捷鍵介紹
下方是幾個常用的快捷鍵空能,建議背起來,能大幅提升效率喔。
| 按鍵 | 功能 |
| -------- | -------- |
| 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]={資料,資料,資料,資料,資料};
```
圖解:如下

## 陣列的編碼
陣列的編號在程式中是從 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) ,往右跟往下都是正的。

## 陣列的輸入與輸出
如同一維陣列,我們並不一定會事前知道陣列中的資料,所以我們通常用下方的這個格式來處理大多數二維陣列的問題:
```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/)