<font size =20> C++課程講義</font>
# 程式前言與科普
在我們進入C++的教學之前,大家心裡一定有一個疑問,到底什麼是程式語言? 讓我們來簡單介紹一下~
**程式語言就是<font color="#f00">一連串交給電腦執行的命令</font>**
假如我今天要請一個搭載電腦的機器人幫我去買飲料!
你可能會說:
<Br><Br>

但是這樣的語言對電腦來說太過模糊,電腦實際上只懂得很簡單的語言,因此你得像是交待小朋友去買飲料一樣,詳細地以電腦能理解的語言寫下指令,像是這樣:
<Br><Br>

<Br><Br>
### **小整理**


<Br><Br><Br><Br><Br><Br><Br>
# 程式語言種類

#### 雖然程式語言有很多種,但其中的邏輯都是相同的啦,不要緊張!
# 整合開發環境
整合開發環境Integrated Development Environment 簡稱 **IDE** 除了能將我們打出來的程式語言轉換成電腦看得懂的形式,還能輔助我們編寫程式語言、並編譯打包成為可用的程式,有些甚至可以設計圖形介面!
IDE通常包括 程式**語言編輯器**、**編譯器**、**除錯器**。

# IDE種類介紹

# 程式基本架構
基本架構主要分成三個部分
* 標頭檔載入區
* 程式執行進入點(main函式)
* 程式主體

* ### 循序執行
>**將程式碼放入{ }中,就會由上到下執行。**
* ### 結束
>**一旦執行到 return 0 程式就會立刻結束。**
* ### 縮排
>**在{ }內的東西,利用tab鍵向右推。**
>縮排並<font color="#f00">**非必要**</font>,只是讓我們的排版整齊,更有效率的閱讀我們的程式碼~
* ### 分號
>**句子結尾要有分號,代表一個指令結束**
<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>
# 標頭檔載入

C語言為了程式的容易閱讀,容易發展,容易維護以及將來可以適用於不同的系統環境,在編譯器進行編譯之前,會先處理某些由"#"所帶領的指令,之後再將處理的結果與程式一起進行編譯,這就是我們的<font color="#f00">**前端處理**</font>,負責處理這些指令的部門,我們稱呼為<font color="#f00">**前端處理器**</font>!
我們**前端處理的指令**,可以利用<font color="#f00">**標頭檔的載入**</font>,如果我們未來要利用那些函式的時候,只要利用"#include"引入到自己的函式即可!
舉例來說: 我們要在程式裡面使用cin、cout,我們就要引入


**Hint**
>更多的函示庫可以參考下列網址https://www.cplusplus.com/reference/
# 註解
寫程式時為了方便閱讀理解會使用註解。
* 註解不會影響程式的執行。
* **單行註解**:在 // 後加註。
* **多行註解**:用 / * * /包起來。

# 變數
## 什麼是變數?
當電腦在處理指令時,我們希望他能記住一些資料。這個能儲存東西的物件就稱為1)__________ 。
變數,顧名思義,就是**內容**可以**隨時改變的數**,簡單來說,就像一個**抽屜**,可以把值存進去。

## 變數屬性類別
變數會根據資料的屬性有不同類別,以下為最常用到的
* **int** :儲存2 )__________ 型別資料 。 如: 1 、3 、100
* unsigned: 只能表示 0 和正數
* long long :處理較多位的數字
* **float** :儲存小數型別資料。如 3.4 、 2.99
* double: 處理較多位的小數
* **bool** :儲存真假值。如 true 和 false
共通點:凡是與3 )__________ 相關的請交給我
* **char** 處理 4 )__________ 型別資料。如: a 、z 、1
* **string** :處理一連串的文字。如 fruit 、 c 、 cool
共通點:凡是與5 )__________ 相關的請交給我

## 變數宣告規則
當我們需要使用變數時,需要先給變數一個名字(幫抽屜取名字),也就是所謂的變數宣告。取名的時候有幾個小規則是需要大家一起來遵守,才能讓電腦順利讀懂我們取的名字
* **不能重複命名** (ex: int a; float a;)
* **不能使用保留字** (ex: int float)
= >因為這些字在 c 中具有其他的功用喔
* **不能使用特殊符號** (ex:!@#$%)、含有空格,但 _ 可以
* **不能以數字開頭** (ex:123aaa)
* **英文有大小寫之分**(ex: int cat, int Cat, int CAT)
**小叮嚀**
> 變數一定要先宣告再使用
> 變數名稱要盡量宣告有意義的名字,提高程式可讀性
<Br><Br><Br><Br><Br>
## 變數宣告語法

### 範例:變數宣告
#### 法一
```cpp=
int a=2;//宣告一個變數 a,將數值2的值賦予到變數a中
```
#### 法二
```cpp=
int b;//宣告一個變數 b
b=2; //將數值2的值賦予到變數b中
```
大家一定覺得每次只能宣告一個變數不過癮吧!因此如果我們要一次宣告很多個變數時就用 6)__________ 把他們隔開吧!
(ex: int a ,b;)
# 輸入、輸出
為了與程式互動,在**終端機**下輸出程式執行結果,或是從終端機取得使用者的輸入資料是基本需求。<Br>
在C++ 中輸入輸出是由**標準程式庫的iostream**提供,這也就是為何要在程式的一開頭加上:#include <iostream>
### 範例:輸入變數值
```cpp=
int a,b,c;
cin>>a; //輸入a的值
cin>>b>>c;//連續輸入b和c的值
```
### 範例:輸出變數值
```cpp=
cout<<a; //在螢幕顯示a的值
cout<<endl;//換行
cout<<b<<c<<endl; //在螢幕上顯示b和c的值
cout<<"歡迎來到陽交大資財!"//在螢幕上顯示 歡迎來到陽交大資財
```
<Br><Br>
**Hint**
> **cin** 可以當作把數值從**鍵盤**輸入到**程式碼** 所以是 cin>>a 想成箭頭指向 a 。
> **cout** 可以當作從**程式碼**中輸出數值到**螢幕**上顯示,所以是 cout<<a
想成箭頭指向 cout 去印出你的字串 。
### 補充:終端機
>終端機是一台電腦或者電腦系統,用來讓使用者輸入資料,和顯示計算結果的機器。
簡而言之就是**使用者與計算機互動**的裝置!

```cpp=
#include<iostream>
using namespace std;
int main()
{
int year, month, day;
cin>>year>>month>>day;
cout<<"我的出生年是:"<<year<<endl;
cout<<"我的生日是:"<<month<<"/"<<day;
return 0;
}
```
# 運算子
當我們知道了如何去**命名**以及**判斷資料型別**之後,就能開始對變數進行一連串的運算啦!首先我們先從最常見也是大家最熟悉的數學系列開始介紹。
而連接兩個變數,使他們可以進行運算的符號就稱為1 )__________ 。
<Br><Br>
### (一)算數運算子
* "+" 兩個變數相加
* "-" 兩個變數相減
* "*" 兩個變數相乘
* "/" 兩個變數相除
* "%" 兩個變數 2)_____________
* "++" 某個變數的值加 1
* "--" 某個變數的值減 1
小叮嚀
>在int宣告時,「/」在 c 中運算出的值不會有小數點,因此,希望求出的解有小數位就改用float 宣告吧!
### 範例:變數運算
```cpp=
int a=7;
double b=7;
a=a/2;
b=b/2;
cout<<a;//輸出的值為3
cout<<b;//輸出的值為3.5
```
**Hint**
> 偷偷告訴大家一個小秘密~想要讓 a 的值增加(減少)1,有三種不同的表達方式,他們都能達成相同效果

> 這些方法在減法時也一樣適用,但是在乘法、除法和取餘數時只有前兩條可以用喔!因此下列幾段程式碼都是ok 的,寫起來也更為精簡




<Br><Br><Br><Br><Br><Br>
```cpp=
int A_time, T_time;
cin>>T_time;
A_time=(T_time-15+24)%________;
//如果相減變負的 我們就再多給 24 小時 並把結果再和 24 取餘數
cout<<A_time;
```
所以當我們碰到**循環**類型的題目,即數字被限定在某個範圍內不停循環,如:時間問題、電視台的台數 3)__________ 會是一個很好用的工具
小叮嚀
>等到後面學到了if 判斷式後再回來看看這題吧~
>
加減乘除的工具我們有了,接下來看看也是能套用在數學類型資料
(bool 除外 ),用來比較大小的比較運算子吧 ☺
### (二)關係運算子
* ">" 大於
* "<" 小於
* 4)________ 等於
* ">=" 大於**或**等於
* "<=" 小於**或**等於
* 5)________ 不等於
### (三)邏輯運算子
* "| |" 或
* "&&" 且
* "!" 非
在c 的世界中,不同的運算子處理的優先順序不一樣,就像是國小學加減乘除時候的「先乘除後加減」一樣喔。那究竟是誰有特權,又是誰被忽略到最後呢?以下為先後次序:

# if & else 邏輯判斷(單條件)
在解決題目時,我們常常需要判斷題目中的各項敘述再進行解題,程式在運作時也會遇到同樣的情形,因此這時候我們就要使用判斷陳述的方式去判斷程式現在面對的狀況,再依不同狀況執行不同程式,這時候我們就需要使用一種邏輯運算子 1 )__________
If判斷式就像一個**二分法**一樣,它會判斷題目的敘述並分為兩種情況,而分辨的方式就是依靠其中的 **條件式** 。條件式會是一個具體明確的敘述,而 if 判斷式將會分辨題目是否符合條件式的情況,若符合條件式,程式將會執行特定的程式,而不符合的話這段程式就不會被執行。

<Br><Br><Br><Br><Br>
## if 單條件架構

### 範例
```cpp=
if (成績不到60分)//成績是否到60分
{
cout<<"不及格";//如果低於60分,輸出 不及格
}
```
<Br><Br><Br><Br><Br>
# If & else 邏輯判斷 巢狀結構
有時,我們會遇到條件很多的問題,這時候我們可以用多次判斷陳述去解決問題,例如

<Br><Br><Br><Br><Br><Br><Br><Br>
## If & else 巢狀架構

除了用上面的方法,我們還可以用另外一種工具幫助我們把多個條件式合併成一個條件式,叫做 2 )__________ 而我們最常用的有以下兩種

當我們使用&& 時,代表 && 左右兩邊的條件式需要,同時達成才算符合條件式,而當我們使用 | | 時,左右兩邊的條件式只需要**達成其中一項**,就算符合條件式了!

**Hint**
> 在使用 if 判斷式時,如果我們要執行的 「事件」只有一行的話,我們就可以不用打用來框住「事件」的大括號 { } 而此時我們也可以將「事件」往上挪一排直接移到 if ( 條件式 ) 的後面喔~
### 範例
```cpp=
if(成績<60&& 成績>=40)//如果成績小於60且大於等於40
cout<<"可以補考";
```


<Br><Br><Br><Br><Br>
```cpp=
#include<iostream>
using namespace std;
int main()
{
int litter,flower,candy;
cout<<"撿了幾個垃圾:";
cin>> litter;
cout<<"澆了幾朵花:";
cin>> flower;
if((1)__________)
{
candy++;
(2)__________;
candy=candy+(3)__________;
}
if((4)__________)
{
candy++;
(5)__________;
candy=candy+(6)__________;
}
cout<<"總共可以拿到:"<<candy<<"顆糖果!"<<endl;
return 0;
}
```
# If & else邏輯判斷 (else 事件)
在剛剛,我們都只有在敘述符合條件式時才會執行事件,現在我們要在敘述不符合時也執行其他事件,而我們要做的就是在原本的程式碼下面加 else 陳述句,當敘述不符合 if 判斷式中的條件式時,程式就會執行 else 陳述句裡面的事件。

<Br><Br><Br>
## else 事件架構

### 範例
```cpp=
if (成績>=60分)//確認成績是否大於等於60分
{
cout<<"欸,恭喜";//大於60分,輸出 欸,恭喜
}
else
{
cout<<"再接再厲,摳連";//大於60分,輸出 再接再厲,摳連
}
```
<Br><Br>
# If & else 邏輯判斷 (else if 判斷式)
在上面的範例中,我們使用了一個if 和 else 進行邏輯判斷。但有時候我們需要考慮三種或以上的情況,而原本的 if else 只能將敘述分成兩種情況,因此這時候就需要使用 else if語法協助我們判斷其他情況。當敘述不符合 if 中的條件式時,程式碼會進入到 else if區塊,若敘述符合 else if 裡面的條件式時,程式就會執行else if裡面的事件。如果敘述依然不符合 else if 裡面的條件式的話,程式才會執行 else 裡面的事件。

## else if 事件架構

### 範例
```cpp=
if( 成績 >= 60)// 如果成績大於等於 60 分
{
cout<<" 恭喜及格 "<<endl;
}
else if (成績 >= 40 )//如果成績不到 60 分但大於等於 40 分
{
cout<<" 你還有救 "<< endl;
}
else//如果成績不到 40 分
{
cout<<" 努力不一定會成功,但不努力一定不會成功,加油! "<< endl;
}
```


<Br><Br><Br><Br><Br>
```cpp=
#include<iostream>
using namespace std
int main()
{
int year;
cin>>year;
if(year(1)_____ 400 _____ 0)//4.
cout<<"閏年";
else if(year(1)_____ 100 (2)_____ 0)//3.
cout<<"平年";
else if(year(1)_____ 4 (2)_____ 0)//2.
cout<<"閏年";
else
cout<<"平年";
return 0;
}
```


<Br><Br><Br><Br><Br><Br><Br>
```cpp=
#include <iostream>
using namespace std;
int main()
{
int a,b,c,max;
cin>>a>>b>>c;
if(a<b)
{
max=b;
b=a;
a=max;
}
if((1)_______)
{
(2)_______;
(3)_______;
(4)_______;
}
//比邊常大小
if(a>=b+c)
{
cout<<"無法成為三角形";
}
else if((5)_______)
{
cout<<"為正三角形";
}
else
{
cout<<"為三角形"
}
return 0;
}
```
# 迴圈
我們常常需要電腦幫我們進行簡單卻<font color="#f00">**大量、高重複性**</font>工作,直到達成某個條件為止的指令,這個指令的語法我們就稱之為 1 )____________ 。**迴圈**屬於電腦科學領域中常見的流程控制 ,它只需要寫一次就能讓程式碼連續執行多次。
<Br><Br><Br><Br><Br><Br>
# for 迴圈的語法與架構
for迴圈常用於有<font color="#f00">**確定**</font>重複次數的迴圈,同時 for 後面接著小括弧,包含了三項基本任務,如下所示

⮚[ A ]: 設定迴圈初始值
⮚[ B ]: 條件判斷
⮚[ C ]: 程式區塊
⮚[ D ]: 變更判斷對象內容
| 流程圖解釋 | 流程圖架構 |
| -------- | -------- |
| 先做A → 檢查 B 條件是否成立→成立就進入 C→ 再來做 D→檢查 B 條件是否成立→成立就進入 C→ 再來做 D……→檢查 B 條件是否成立→不成立 就離開迴圈|  |
### 範例:輸出1~3階乘
```cpp=
#include <iostream>
using namespace std;
int main()
{
int fact=1,x;
for(x=1;x<=3;x++)
{
fact*=x;
cout<<x<<"階乘 ="<< fact<<endl;
}
return 0;
}
```

```cpp=
#include <iostream>
using namespace std;
int main()
{
int i,sum=0;//i負責計數,sum負責加總的總數
for(i=1;i<=100;i++)
{
if(i%2!=0)
{
sum+=i;
}
}
cout<<"總和為:"<<sum<<endl;
return 0;
}
```
# 巢狀迴圈
迴圈也可以是巢狀(Nested) 的!所謂巢狀的迴圈是指迴圈中包含其他的迴圈,由於我們利用程式碼縮排的方式,使該段程式碼凹陷進去,看似巢的樣子,故稱巢狀。以下我們來試著印出九九乘法表吧~~
```cpp=
#include <iostream>
using namespace std;
int main()
{
int x,y;
for(y=1;y<=9;y++)
{
for(x=1;x<=9;x++)
{
cout<<x<<"*"<<y<<"="<<x*y;
cout<<" ";
}
cout<<endl;
}
return 0;
}
```
<Br><Br><Br>
#### 輸出結果


<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>
```cpp=
#include <iostream>
using namespace std;
int main()
{
int i,j,num;
cout<<"你想要的階層數量:";
cin>>num;
for(i=1;i<=num;i++)
{
for(j=1;(2)_______;j++)
{
cout<<"*";;
}
cout<<endl;
}
return 0;
}
```
# while迴圈的語法與架構
while迴圈常常用於<font color="#f00">**不確定**</font>重複次數的情況下,while 後面接的小括弧是迴圈結束的條件測試,通常是運算式。它會在迴圈開始前進行迴圈結束條件的測試。另外,因為 while 迴圈的括弧內**只包含迴圈的中止條件**,所以其他有關控制變數的初始設定及調整,需要放在其他地方。


### 範例:1~100整數和
```cpp=
#include <iostream>
using namespace std;
int main()
{
int i,sum=0;
while(i<=100)
{
sum+=i;
i++;
}
cout<<sum;
return 0;
}
```

```cpp=
#include <iostream>
using namespace std;
int main()
{
int ans=5,guess;
cout<<"輸入你想猜的數字:";
while((1)___________)
{
if(ans>guess)
{
cout<<"猜大一點";
}
else if (ans<guess)
{
cout<<"猜小一點";
}
else{
cout<<"猜中了";
break;
}
}
return 0;
}
```
<Br><Br><Br><Br><Br><Br>
# do while 迴圈
do while 迴圈屬於<font color="#f00">**後測式**</font>迴圈,意思是迴圈會先執行一次程式,然後才會進行結束條件測試。除此之外,與 while 迴圈並無太大的差別 。


<Br><Br><Br><Br><Br><Br><Br><Br><Br>
### 範例:輸出1~30的奇數
```cpp=
int i=1;
do//先做過 do 中的程式一次,再判斷 i 是否大於 30
{
cout<i<" ";
i+=2;
}while(i<=30);//記得要加上分號
```
# Break & Continue用法
break可以用在 for 以及 while 迴圈中,當程式達成某個條件之後,需要
1 )__________ 迴圈時使用 。

```cpp=
#include <iostream>
using namespace std;
int main()
{
int total_money=0;
int month_money;
while( cin >> month_money )
{
total_money += month_money;
cout << "total money :" << total_money << endl;
if( total_money >= 3000 )
{
break;
}
}
cout << "可以買拍立得了!" << endl;
return 0;
}
```
continue可以在 for 以及 while 迴圈中 2 )_________ 執行一次,然後進行下一輪的指令,**並不會終止迴圈**。迴圈碰到 continue 時,就像直接跳到迴圈最後右大括弧的地方,重新進行迴圈的結束條件測試,如果測試結果通過,迴圈就會繼續執行 。
### 範例:
```cpp=
#include <iostream>
using namespace std;
int main()
{
int i;
for(i =1;i<=10;i++)
{
if(i ==5)
continue;
cout<<i<<" ";
}
return 0;
}
```
### 寫出輸出結果

<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>

```cpp=
#include<iostream>
using namespace std;
int main()
{
int i,sum=0;
for(i=1; i<= 30; i++)
{
if(i%5==0)
(1)__________;
sum+=i;
if(sum>=200)
(2)__________;
cout<<i<<"+";
}
cout<<i<<"="<<sum;
return 0;
}
```
<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>
# 陣列 Array
在前面的章節中我們學習到了如何宣告變數及運算 但當我們要一次宣告多個變數時我們可能會像以下的方式宣告
```cpp=
int x0;
int x1;
int x2;
int x3;
```
但如果像以上這樣宣告變數的話會使得程式缺乏效率且冗長,更重要的是
這樣的宣告方式會顯得這四個變數是獨立的 而無法看出他們之間的關係。
所以在這裡我們要學習一個有系統宣告變數的方法就是1)____________。
## 一維陣列宣告語法

* **資料型態**:可以是之前我們介紹的型別 ex: int、float 或是double....
* **陣列名稱**:陣列名稱跟我們在變數命名的時候一樣,而後面中括弧的數字大小就是,要建立陣列的大小
* **陣列的儲存空間是從0開始編號**: 比方說int x[3]就是代表宣告一個叫做x的陣列,總共占用3個位置,編號分別是 **x[0]**、x[1]、x[2],每一個位置都能存一個整數。
### 範例: 陣列宣告
```cpp=
int x[3];//宣告一個整數陣列x,可以存三個整數變數
```
### 示意圖

瞭解了陣列中的每一個變數應該怎麼呼叫之後,就像賦值給變數一樣,我們
也要學習如何為陣列中的每一個變數賦值,而賦值的方法有以下幾種:
<Br><Br><Br><Br><Br><Br>
### 範例:陣列賦值(法一)
```cpp=
int x[3]={1,4,8};//宣告一個整數陣列,在這個陣列中x[0]=1、x[1]=4、x[2]=8
bool p[2]={true,false};//宣告一個布林陣列,在這個陣列中p[0]=1,p[1]=0
```
但是有時候,我們不會那麼完整地給予陣列值,像是以下範例:
### 範例:陣列賦值(法二)
```cpp=
int X[3];//宣告一個整數陣列X ,這個陣列並沒有初始值
float y[3]={4,6};// 宣告一個小數陣列y,而這個陣列中只有前兩個變數有賦值,所以y[2]為0
int q[3]={};// 宣告一個整數陣列 q,而這個陣列中的三個元素都是 0
int c[3]={10,11,12};
int c[]={10,11,12};//宣告一個整數陣列 c ,程式會自動判定陣列 c 有三個元素
//第五行跟第六行的結果是一樣的!
```
除了自己手動賦值給陣列,當我們需要<font color="#f00">**有規律地**</font>賦值或是當陣列有太多項
時,我們也可以利用<font color="#f00">**迴圈**</font>來完成賦值哦!假設現在我們需要一個 10 格陣列
,而每一個變數的值為其索引值,那我們可以透過以下方法達成:
### 範例:利用迴圈賦值
```cpp=
int x[10];
for(int i=0;i<10;i++)
{
x[i]=i;
}//宣告一個整數陣列x,而這個陣列中 x[0]=0,x[1]=1, ... ,x[9]=9
```
最後,當我們成功地利用將陣列賦值來解決問題後,就要學習如何將<font color="#f00">**陣列值輸出**</font>。但你可能會想說:那不就直接 cout 出來就好了嗎? Nonono! 這樣是行不通的!陣列沒辦法像變數一樣可以直接輸出,我們必須利用為陣列賦值的方法,也就是利用<font color="#f00">**迴圈**</font>!以下我們接續上一個範例,將陣列輸出:
### 範例:利用迴圈輸出陣列內容
```cpp=
for(int i=0;i<10;i++)
{
if(i!=9)
cout<<x[i]<<",";
else
cout<<x[i];
}
```
### 輸出結果



瞭解了如何為陣列賦值及輸出陣列之後,我們接下來要學習如何讓使用者自行輸入陣
列的元素。其實方法和輸出陣列非常的相似哦!以下來試試看如何讓使用者輸入自己的學測成績!
<Br><Br><Br><Br><Br><Br>
### 範例:使用者自行輸入陣列
```cpp=
int grade[5]={};//宣告一個整數陣列grade,準備讓使用者輸入資料
for(int i=0;i<5;i++)
{
cin>>grade[i];//利用迴圈讓使用者依序輸入自己的學測各科成績
}
```
有時候我們需要讓程式自行計算陣列的大小,也就是裡面共有幾個元素。這時候我們就需要用到一個指令叫做 3)________________,這個指令可以幫助我們計算陣列裡的元素共佔了多少 4) ________________,進而計算陣列中元素的個數。以下讓我們示範這個指令的使用方法:
### 範例:sizeof()指令用法
```cpp=
int num[1]=0;
cout<<sizeof(num[1]);//輸出的結果為4
```
看到現在的你一定有個疑問:那就是為甚麼明明num 陣列中只有一個元素,但輸出結果卻是 4 呢?這是因為我們剛剛提過的, sizeof 指令幫助我們計算的是**位元組**,而非元素個數。舉上面例子來說,因為電腦會利用 4 個位元組來儲存一個整數,所以輸出結果才會是 4 。所以如果我們要利用 sizeof指令來幫助我們計算元素個數的話,我們還需要多做一個處理。也就是把sizeof(陣列)的值除以sizeof(陣列中變數的型態),以下讓我們示範:
### 範例:sizeof()指令應用
```cpp=
int num[3]={0,1,2};
cout<<sizeof(num)/sizeof(int);//也就是 12/4 ,所以輸出結果為 3
```
看完以上的範例,聰明的你應該也有猜到,其實除數不一定要放sizeof 陣列中變數的型態!只要是陣列中任何一個存在的值就可以了。下面附上常用的資料型態所佔的位元數。不用背起來,因為我們只要知道怎麼除就可以得到我們想知道的陣列中元素個數。


```cpp=
#include <iostream>
using namespace std;
int main(){
int score[5];
int i,sum;
for(i=0;i<5;i++)
{
cin>>score[i];
}
for(sum=0,i=0;i<5;i++)
{
sum=sum+score[i];
}
cout<<"總成績"<<sum<<" "<<"平均成績"<<sum/5 ;
return 0;
}
```
以上學習過的陣列都屬於5)__________,但當我們如果需要一次儲存每個人的身高及體重,或是多個家具的長、寬、高,上述這種一筆資料內含多變數的時候,我們就可以使用 6)___________ 來儲存資料。以下我們皆以二維陣列做示範。
## 二維陣列宣告語法

<Br><Br><Br><Br><Br><Br><Br>
**Hint**
> 我們可以把二維陣列想像成,多個一維陣列**疊在一起**
> 每一條水平代表是一個**列(row)**
> 每一條垂直代表是一個**行(column)**
組合後的儲存空間就跟一個表格一樣
簡單示意圖

### 範例:二維陣列宣告
```cpp=
int body[2][3];
float items[9][9];
```
同樣地,宣告完陣列之後,我們需要為陣列賦值,而賦值的方式同樣有兩種,
分別是**直接賦值**及利用**迴圈賦值**。
### 範例:二維陣列賦值
```cpp=
int grade[3][2]={{70,80},{80,90},{90,100}};
/*
宣告一個二維陣列grade,此陣列中共有3個小陣列,
而每個陣列中皆有 2 個元素,整個陣列共有6個元素
*/
int grade[][2]={70,80,80,90,90,100};
/*
第六行的結果跟第一行是一樣的,也就是說,當我們在為多維陣列賦值時,
第一個大小是不需要的。
*/
bool x[2][2]={true,false,false,false};
//宣告一個二維陣列x,在陣列中,x[0][0]=1,x[0][1]=0,x[1][1]=0,x[1][1]=0
```
除了可以手動直接賦值之外,我們仍然可以利用迴圈賦值。如下:
### 範例:二維陣列迴圈賦值
```cpp=
int students [3][2];
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<2;j++)
cin>>students[i][j];
}
```
而輸出二維陣列的方法也同樣是利用迴圈,我們接續上一個範例:
```cpp=
for(int i=0;i<3;i++)
{
cout<<"Student"<<i+1<<":";
for(j=0;j<2;j++)
{
if(j==1)//如果輸入到每位學生最後一個成績時,需要換行
cout<<students[i][j]<<endl;
else
cout<<students[i][j]<<",";
}
}
/*
假設在上個範例中使用者輸入: 50,60,70,80,90,100 ,則在這裡輸出的
結果為:
*/
Student 1:50,60
Student 2:70,80
Student 3:90,100
```



```cpp=
#include <iostream>
#define Row 2//定義列的個數
#define Col 3//定義行的個數
using namespace std;
int main(){
int i,j;
int A[Row][Col]={{3,2,4},{1,2,3}};
int B[Row][Col]={{5,4,2},{4,7,2}};
int C[Row][Col]={0};
for(i=0;i<Row;i++)
{
for(j=0;j<Col;j++)
{
C[i][j]=A[i][j]+B[i][j];
}
}
cout<<"Matrix C = A + B"<<endl;
for(i=0;i<Row;i++)
{
for(j=0;j<Col;j++)
cout<<C[i][j];
cout<<endl;
}
return 0;
}
```
### 輸出結果

<Br><Br><Br><Br>
**Hint**
> 這邊我們使用Define的用法,是常數的概念(相比一般我們宣告的變數),如果我們Define好一個數值,寫code的時候如果要改數字就不用每個地方動,只要動Define的數字就好。
# 字元與字串
字元可以用來表示「一個」符號、數字、字母等等,而要表示一個字元需要以 1)__________ 來夾住要表示的字元 。
### 範例:字元宣告
```cpp=
char x='A';// 宣告一個字元x,而這個字元表示 'A' 這個字母
char y='!';// 宣告一個字元y,而這個字元表示 '!' 這個符號
```
而字元在電腦中是以8 個位元組成的,而一個位元又可以儲存 0 or 1 ,所以總計可以儲存 2^8 種,也就是 256 種字元,而字元與數字對應的關係我們稱為2)______________。
### ASCII
char變數就是儲存 ASCII 裡的一個整數編號( 0 ~ 127 )
分成 **(1)可顯示** **(2)不可顯示** 兩類
* **半形字(可顯示)**
>編號32~126 一個整數編號 會對應到 一個半形字
* **控制字元(不可顯示)**
>編號0~31、127 一個整數編號會對應到一個控制字元
>ex:整數編號0->控制字元的意義是"\0" 空字元(NULL)

### 範例:ASCII碼&字元輸出
```cpp=
for(int i=32;i<126;i++)
cout << i << ” ” << char(i) << ” ”<<endl;
```
### 輸出結果

在上面的例子中,我們是將 ASCII 所代表的字元輸出,相反的我們也可以將
字元所代表的 ASCII 碼輸出
### 範例:輸出字元的 ASCII 碼
```cpp=
cout<<(int) '!';// 輸出結果為 ! 的 ASCII 碼: 33
cout<<(int) 'a';// 輸出結果為 a 的 ASCII 碼: 97
cout<<(int) '8';// 輸出結果為 8 的 ASCII 碼: 56
```
而接下來我們要學的**字串**,其實就是用陣列裝的許多字元 形成一個字串
宣告方式基本上跟前面提到的陣列宣告方式幾乎一樣 。
### 範例:宣告字元陣列
```cpp=
char name[]={'A','H','S','N','C','C','U'};//宣告name這個陣列裡存了7個字元
char name1[]={"Justin"};//宣告name1這個陣列裡存了6個字元
```
### 補充
> 其實在上面範例中的name1[ ] 字串長度是 7 ,原因是當你像 name1[ ] 這樣以雙引號宣告字串時,電腦會自動幫你在字串的尾巴加入一個 '\0' 的空字元。沒錯,這就是我們剛剛學到 ASCII 碼中那些不可顯示的控制字元之一,而這個空字元就是告訴電腦字串只到這裡就結束了唷。
> **示意圖**
>
> 
學完以字元陣列宣告完字串後,我們接下來要學另一種字串的宣告方式,也就是以字串的英文<font color="#f00">**string**</font>來宣告字串!
### 範例:宣告字串(string)
```cpp=
string name="AHSNCCU"//與上面char name[]={'A','H','S','N','C','C','U'}一樣
string name1="Justin"//與上面char name1[]={"Justin"};一樣
string empty(name)//宣告了 empty 這個字串,並將 name 元素複製到 empty裡面
```
那在宣告字串之後,我們也可以利用一些運算子或是函數來把字串增減、插入或是比較兩字串以及檢測字串中有幾個字元等等,而其中的比較兩個字串的方式是以字元的 3)__________ 從第一個字元開始互相比較。若前者大於後者,則會輸出 1 ,相反則是輸出-1,若比到最後一個字元都還是一樣話,則會輸出 0 ,那我們就看以下範例來讓你們更了解如何比較字串吧。
### 範例:string字串比較
```cpp=
string a="abc123",b="aaa123",c="abc123";
cout<<b.compare(a)<<endl;//輸出的結果為-1,因為'b'的ASCII 碼是98,
//'a'的ASCII 碼是97,可得'b'>'a',所以輸出-1。
cout<<a.compare(b)<<endl;,//輸出的結果為1,因為'b'>'a',前者大於後者
cout<<a.compare(c)<<endl;//輸出結果為 0 ,由於 兩個字串從第一個
//比到最後一個字元的 ASCII 值都一樣,所以電腦會輸出 0 。
```
PS: 此種比較法只適用於以 string 宣告的字串 。
那如果是**字元陣列**型態的字串,我們可以利用 strcmp (str 1 ,str 2) 來去進行比較一樣是從第一個字元以 4)___________ 來進行比較,若前者大於後者 則輸出 1 ,相反則是輸出 -1,而同樣的話一樣輸出 0 接著一樣用範例來讓你們知道如何利用字串比較 。
### 範例:字元陣列(字串)比較
```cpp=
char a[]="aaa123",b[]="abc123",c[]="aaa123";
cout<<strcmp(a,b);//輸出結果為-1;
cout<<strcmp(b,a);//輸出結果為1;
cout<<strcmp(a,c);//輸出結果為0;
```
大家應該還記得在前面的陣列,有學到 **sizeof** 這個指令嗎 這個指令在字串中也可以使用歐,而且很方便的是一個字元就占一個位元。也就是說,字串中有幾個字元 sizeof 就會告訴你正確的字元數量給你 。
### 範例:字串大小
```cpp=
char name[]="Justin";
char name1[]={'J','u','s','t','i','n'};
cout<<sizeof(name);
//輸出結果為7,原因是前面的補充有說到,
//電腦會在最後自動加空字元,所以總共是'J'+'u'+'s'+'t'+'i'+'n'+'\0'=7
cout<<sizeof(name1);
//輸出結果為 6 ,因為 name1 這種宣告方式,
//電腦不會自動幫你加空字元,所以總共是 ’'J'+'u'+'s'+'t'+'i'+'n'=6 。
```
除了知道字串的大小,我們也可以求字串的長度,需要用的的是**strlen** 這個函式,它可以準確地告訴你這個字串中有多少個字元。但請注意,**<font color="#f00">strlen 並不包含 '\0' 這個空字元,且 strlen 只適用在字元陣列中。</font>**
### 範例:字串大小(Strlen)
```cpp=
char name[]="Justin";
char name1[]={'L','i'};
cout<<strlen(name)<<"/"<<strlen(name1);
//輸出結果為 6/2
```



```cpp=
#include <iostream>
using namespace std;
int main()
{
char x;
while( cin >> x )
{
if( ('a' <= x )&& (x <= 'z') )
{
cout << "是小寫字母" << endl;
}
if( ('A' <= x )&& (x <= 'Z') )
{
cout << "是大寫字母" << endl;
}
if( ('0' <= x) && (x <= '9') )
{
cout << "是數字" << endl;
}
}
}
return 0;
```
<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>
# 函式 Function
當我們在寫一個較大型的程式時,可能會遇到有特定功能的一小段程式重複出現,導致主程式裡過於雜亂,很難閱讀與除錯,這時我們可以使用函式來幫助我們維持程式碼的簡潔性,也更方便我們維護及撰寫 。
# 函式的定義

# 函式的呼叫

### 範例:C++中的函式
```cpp=
//定義函式
int fun(int x)//回傳值的資料型態 函式名稱(參數型態 參數名稱)
{
x=x+1;//函式內容
return x;//回傳值
}
//呼叫函式
int main()
{
cout<<fun(5);//輸出值=6
}
```
數學上的函式與程式的函式其實長得挺像的,藉由給予函式參數經由運算後產生值。下面介紹函式的構成要素。
* **函式名稱**:由使用者自訂,但不能用保留字或主程式使用的變數名稱。
* **函式內容**:將想運行的程式輸入在這。
* **參數型態及名稱**:在呼叫函式時會將指定資料型態的參數傳入。(依需求可要求不只一個參數,例如int a(int x, char y, string z) 或 void p())
* **回傳值的資料型態與回傳值**:在函式的程式碼運算完之後,會將得到的結果回傳,但每次只能回傳一個值。(若不回傳,則需宣告為 void 。)
### 範例:錯誤命名的函式
```cpp=
int float(int x)//float為保留字
{
x=x+1;
return x;
}
```
**Hint**
> 1.把函式想像成一個專屬於你的鑄造機,它可以做你任何想要的東西,你可以把你的素材丟進去,並且要求他成果出來式你指定的模樣~
> 2.自訂函式一定要**先定義,再呼叫!**
**補充**
>main(主函式),其實也是函式的一種,但特殊的地方在於 main 函式不需要有輸入值,即
>int main(void),而另一種方式是 int main(int argc, char* argv[]),是在使用命令列編譯程式的時候才會用到,所以現在大可放心使用 int main() 。
# 自訂函式與內建函式
函式可以分成**內建函式**與**自訂函式**下面會分別介紹兩者 。
**<font color="#f00">內建函式</font>**,C++ 裡已經內建好許多方便的函式 我們稱這些函式為內建函式,使用前須在程式的開頭引入相對應的函式庫。舉一些常見的函式庫:

<Br><Br><Br><Br><Br><Br>
### 範例:利用內建函式比大小
```cpp=
#include <iostream>
#include <algorithm>//在開頭引入 algorithm 函式庫才能使用 max 函式
using namespace std;
int main()
{
int x=1;y=3;
cout<<max(x,y)<<endl;//函式得到的結果為3
return 0;
}
/* 不使用函式的寫法
if(x > y)
cout << x << endl;
else
cout << y << endl;
*/
```
相較於用if/else 進行判斷 善用函式會是相對簡單又整潔的方式 。
**補充**
> 在http://www.cplusplus.com/reference/ 中可以查詢各種不同函式庫的用法及需要給予的參數。
**<font color="#f00">自訂函式</font>**:自己決定函式的運算內容 須寫在 using namespace std 下方int main() 上方 函式宣告方式如前述。注意若函式已回傳值後便會馬上停止不再運行 return 下方的程式碼。
### 範例:自訂函式
```cpp=
#include <iostream>
using namespace std;
//自訂一個名為math的函式
int math(int x)
{
int y = 5;//此y是宣告在math函式裡,區域變數y的活動範圍
cout << y << endl ; //得到的結果會是 5
y += x;
return y;
y += 1;//這行是不會運行到的
}
int main()
{
int x = 1, y = 3;//此y是宣告在main函式裡,區域變數y的活動範圍
x = math(x);//呼叫函式
cout<< x << "," << y << endl ;// 得到的結果會是 6,3
return 0;
}
```
## 區域變數 & 全域變數
在這兩個函式中都出現了 y 這個變數,但由於這兩個函式的 y 皆為 區域變數 ,意即 y 在每個函式裡皆為獨特的在 math 函式裡,更改 y 值不會更動到 main 函式中的 y 值,即各變數的有效範圍只在宣告該變數的函式中。可在所有函式中使用的 變數則稱為 **全域變數** 可參考下面範例 。
**補充**
> int main(),函式一定要 return 0 嗎?答案是可以不用,但完全不建議。在更進階的應用時,電腦會依主函式傳回的值來判定程式是否成功執行,進而判定下一步的動作。事實上目前使用的開發環境中,若在 int main() 函式中沒有 return 0 ,程式是會預設幫你 return 0 的。

<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>
```cpp=
#include <iostream>
using namespace std;
int Isprime(int x)//印質數表
{
int a=2;
if(x<=1)
return 0;
while(a*a<=x)//只須執行到根號x即可
{
if(!(x%a))
return 0;
a++;
}
return 1;//過程中均未發現因數,此數為質數
}
int main()
{
int num;
while(cin>>num)
{
if(Isprime(num)==1)
cout<<num<<"為質數"<<endl;
else
cout<<num<<"不為質數"<<endl;
}
return 0;
}
```
# 遞迴 Recursive
遞迴是在函式執行中呼叫自己的行為,也就是在函式中再次使用同個函式。
創建一個遞迴函式需要定義兩個要素
1.**基本狀況(終止條件):**
終止遞迴(離開函式)的條件。遞迴函式會不停地呼叫自己,若沒有定義終止條件,函式就會不停地重複運作下去,導致程式執行失敗 。
2.**遞迴步驟:**
決定在什麼條件下再次呼叫自己 也就是進入遞迴的條件。簡單來說,遞迴是把大問題拆成許多比原本還小,但長相差不多的新問題,而這些新問題又可以拆成更多更小的新問題 當問題足夠小時,(也就是基本狀況)便直接解決(回傳值而非繼續呼叫函式)再拿已解出來的答案去解開那些尚未解答的問題。
以下會介紹幾種經典的遞迴範例,包括**階乘**、**費波納契數列**。
<Br><Br><Br><Br><Br><Br>
### 範例:階乘遞迴
```cpp=
階乘是所有小於或等於該正整數的積,計為n! 。例如 4!=4*3*2*1 ,而我們
定義 0!=1 1!=1 。給定一個 n ,請求出 n!=?
#include <iostream>
using namespace std;
unsigned long long fac(int n)//為了存最多位數所用的變數宣告
{
if(n == 0)
return 1;//終止條件
else
return n * fac(n-1);// 遞迴步驟
}
int main()
{
int n;
while(cin >> n)
if(n >= 0)
cout << n << "! = " << fac(n) << endl;
return 0;
}
```
畫個圖來了解一下流程,以4! 為例: 在此次範例中 fac( n)=n!

## 進階學習
**Stack( 堆疊 )** 是一種資料結構,也就是電腦儲存及組織資料的方式。而遞迴運用的概念便是堆疊的特色 先進後出( FILO, First in, Last out),意即最先進入的資料會在最後才被取出(得到值)。想像有一疊堆在一起的書,若想拿到最下面的書(得到最先進入的資料值),便需將壓在那本書上方的書全部移除(得到後加入的資料的所有值),才能達成目的。

其實遞迴在某些情況下與函式有許多相像之處給予進入函式/遞迴的條件,與結束函式/遞迴的中止條件 使程式重複執行。而事實上大部分遞迴的程式都能藉由函式完成 但兩者間各有各的好處及壞處。遞迴能以簡單的形式解決複雜的問題 但相對的較浪費時間 並需要額外的記憶體來儲存每次遞迴得到的結果;函式在撰寫上較為直觀 且執行時間較短 但需花較長的程式碼來表達。下面的**費波納契數列**的範例,將以迴圈 與遞迴做示範,同時更進一步說明遞迴的缺點。

<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>
### 遞迴版
```cpp=
#include <iostream>
using namespace std;
unsigned long long fib(int n)//可存最多位的整數型態
{
if ((1)_______________)
(2)_______________;
if ((3)_________)
(4)_________________________;
}
int main()
{
int n;
while(cin>>n)
{
if(n>=0)
{
cout<<"fib("<<n<<")="<<fib(n)<<endl;
}
}
return 0;
}
```
### 迴圈版
```cpp=
#include <iostream>
using namespace std;
int main()
{
int n ;
unsigned long long fib[94]={0,1};//設第0項為0,第1項為1
for(int i=2;i<94;i++)
fib[i]=fib[i-1]+fib[i-2];
while(cin>>n)
if(n>=0)
cout<<"fib("<<n<<")="<<fib[n]<<endl;
return 0;
}
```

遞迴在運算的過程中會將每個函式獨立運算,換句話說由fib(5) 產生的fib (3) 跟 fib (4) 產生的 fib (3) 兩者會分別存在不同的記憶體位置 也就是圖中兩個 fib (3) 是不能共用的需要分別獨立運算。在越大型的遞迴中,會遇到越多這種多餘的計算,導致規劃給函式的記憶體不敷使用,進而造成程式執行失敗。除了記憶體部份的問題,花費的時間也是一個非常大的問題,假設現在要求第 n 項,而我們以函式被呼叫的次數來衡量效率,經由神秘的數學計算可得到約需要花費 1.618 ^n 的次數。假設現在有一道題目要求第 80 項的費氏數列 遞迴需要執行約莫 52,273,476,241,432,877次 相對於迴圈只要跑 80 次就好,差異十分明顯。對於費氏數列的這種暴力展開法,在寫程式的時候要盡量迴避,才不會造成時間上的浪費,還有可能無法求出解。當然,若能將指數形式隨著測資越大而次數成指數成長的遞迴,轉換成線性形式,次數為測資乘上一個常數,遞迴也會是不錯的解決方法。
**補充**
>在演算法中,我們會利用**時間複雜度(time complexity)**來分析程式的執行效率,在費式數列的遞迴中,時間複雜度為接近 O(2^n),而迴圈解法的時間複雜度為 O(n),n為數列的第 n 項。程式執行的效率是以計算步驟的多寡而定,而非計算時間。
<Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br><Br>
# 解答篇

<Br>

<Br>

<Br>

<Br>

<Br>

<Br>

<Br>

<Br>
