# C++ 程式設計
```cpp=
#include<iostream>
using namespace std;
int main(){
//int i;
for (int i=0;i<100;i++){
int j;
}
}
```
## 標頭檔
寫程式前,要先引入函式庫,這樣才可以使用函式庫內的function
```
#include<函式庫名稱>
```
像是要寫C++時,一定要引入`<iostream>`的函式庫
```
#include<iostream>
```
## 命名空間
命名空間又可以當作程式的識別碼,用來區分不同函式庫中相同名稱的function
以下程式碼為例,`cout`和`endl`前的`std`就式命名空間
```cpp=
#include<iostream>
int main(){
std::cout<<"今天天氣真好"<<std::endl;
}
```
每次使用一次`cout`就要寫一次`std`,那這樣寫100次`cout`勢必很麻煩,因此可以直接全域定義程式碼會使用到`std`的命名空間
```cpp=
#include<iostream>
using namespace std;
int main(){
cout<<"今天天氣真好"<<endl;
}
```
## 註解
註解可以用來解釋程式碼,提高程式碼的可讀性,有 **單行註解** 或是 **多行註解** ,註解中的所有文字都會被編譯器忽略。
### 單行註解
在`//`後的所有文字都會被當註解
```
//註解文字
```
### 多行註解
在`/*`到`*/`之間的所有文字都會被當註解
```
/*
註解文字
註解文字
註解文字
*/
```
## 數據類型
### 類型
C++常見的數據類型有6個
| 關鍵字 | 名稱 |
|:------:|:------------:|
| bool | 布林值 |
| char | 字元 |
| string | 字串 |
| int | 整數 |
| float | 浮點數 |
| double | 雙精度浮點數 |
| void | 無值 |
### 修飾符
數據類型又有一個或是多個類型修飾符可以使用:
* singed 有號
* unsigned 無號
* short 短型
* long 長型
各類數據類型,占用大小,值的範圍參考下表
| 類型 | 修飾符+類型 | 占用大小(位元組) | 範圍 |
|:------:|:------------------:|:----------------:|:----------------------------:|
| bool | bool | 1 | 1是true 0是false |
| char | char | 1 | -128 ~ 127 參考[ASCII碼](https://zh.wikipedia.org/wiki/ASCII) |
| | signed char | 1 | -128 ~ 127 |
| | unsigned char | 1 | 0 ~ 255 |
| int | int | 4 | -2^31^ ~ 2^31^-1 |
| | signed int | 4 | -2^31^ ~ 2^31^-1 |
| | unsigned int | 4 | 0 ~ 2^32^ |
| | short int | 2 | -32768 ~ 32767 |
| | signed short int | 2 | 0 ~ 65535 |
| | unsigned short int | 2 | -32768 ~ 32767 |
| | long int | 4 | -2^31^ ~ 2^31^-1 |
| | signed long int | 4 | -2^31^ ~ 2^31^-1 |
| | unsigned long int | 4 | 0 ~ 2^32^ |
| float | float | 4 | ±3.4×10^-38^ ~ ±3.4×10^38^ |
| double | double | 8 | ±1.7×10^-308^ ~ ±1.7×10^308^ |
### string
`string` 比較特別,他個概念就是多個字元組成的字串變數。
字元要使用單引號`''`,引號中間只能有一個字元
字串要用雙引號`""`,引號中間可以有多個字元
## 變數
### 定義
定義變數時,要先指定一個數據類型,再寫下變數名稱。
```
型態 名稱;
```
舉例:
```
int a;
float b;
double c;
string d;
```
如果有多個同數據類型的變數,可以寫在同行用逗號隔開。
```
int a,b,c;
```
### 初始化
在定義變數時可以指定一個初始值讓變數初始化,初始化由一個等號和一個常量組成。
```
型態 名稱 = 初始值;
```
舉例:
```
int a = 3, b = 4;
float c = 0.6;
char d = 'x';
string e = "test";
```
字元需用單引號`''`來表示
當變數沒有做初始化時,系統會自動初始化變數,參考下表:
| 類型 | 初始化默認值 |
|:------:|:------------:|
| int | 0 |
| char | '\0' |
| string | "\0" |
| float | 0 |
| double | 0 |
### 常數
如果初始化定義的變數值不會更改時,可以使用`const`的修飾符,該變數值就無法有任何改變
```
const 型態 名稱 = 初始值;
const int a = 10;
```
### 算數運算符
| 運算符 | 描述 | 範例 |
|:------:|:----------------:|:-----:|
| + | 兩數相加 | a + b |
| - | 前數減後數 | a - b |
| * | 兩數相乘 | a * b |
| / | 前數除後數 | a / b |
| % | 前數減後數的餘數 | a % b |
| ++ | 整數值+1 | a++ |
| -\- | 整數值-1 | a-\- |
實作:
```cpp=
#include <iostream>
using namespace std;
int main(){
int a = 20;
int b = 10;
int c ;
c = a + b; //可以自行更換運算符
cout << "c 的值是 " << c << endl ;
}
```
### 賦值運算符
| 運算符 | 描述 | 範例 |
|:------:|:--------------------------------------:|:------------------------:|
| = | 把右邊的值賦給左邊變數 | c = 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) |
## 變數作用域
### 區域變數
變數只能在該區域才能使用,不同區域的變數可以有相同名稱。
```cpp=
#include<iostream>
using namespace std;
int main(){
int a=10,b=5;
}
void test(){
int a=5;
}
```
在`main`函式裡面的`a`和`test`函式裡面的`a`式兩個獨立的變數,互不影響。
`main`函式裡面的`b`不會在`main`函式以外的地方被讀到。
### 全域變數
變數在整個程式裡面式共通的,任何區域的程式碼的可以去更改全域變數的值
```cpp=
#include<iostream>
using namespace std;
int a = 20;
int main(){
int b=5;
}
void test(){
int c=5;
}
```
全域變數使用的名稱在區域變數宣告時就不能再次使用。
## 輸入輸出
### 標準輸出流cout
`cout`要與流插入運算符`<<`,使用,方式如下
```cpp=
#include <iostream>
using namespace std;
int main( )
{
char name[50] = "aura";
cout << name ;
}
```
不同的數據要一起輸出時要用`<<`隔開,方式如下
```cpp=
#include <iostream>
using namespace std;
int main( )
{
char word[50] = "number = ";
int num = 21;
cout << word << num ;
}
```
變數也可以直接做運算
```cpp=
#include <iostream>
using namespace std;
int main( )
{
int a = 21 , b = 13;
cout << "a + b = " << a+b ;
}
```
換行可以用`endl`,等同`'\n'`
```cpp=
#include <iostream>
using namespace std;
int main( )
{
cout << "一二三" << endl << "四五六";
}
```
### 標準輸出流cin
`cout`要與流提取運算符`>>`,使用,方式如下
```cpp=
#include <iostream>
using namespace std;
int main( )
{
int a;
cin >> a;
cout << "a = " << a << endl ;
}
```
可以進行多數據輸入,每個變數用`>>`隔開
```cpp=
#include <iostream>
using namespace std;
int main( )
{
int a, b ;
cin >> a >> b;
cout << "a = " << a << endl ;
cout << "b = " << b << endl ;
}
```
## 判斷
### if
如果有符合條件,就會執行`if`內的程式碼
```
if(條件式){
...
}
```
### if...else
如果有符合條件,就會執行`if`內的程式碼,反之不符合的話,會執行`else`內的程式碼
```
if(條件式){
...
}
else{
...
}
```
### 多if
如果有符合條件,就會執行`if`內的程式碼,如果不符合,會去檢查`else if`的條件,不符合就在往下檢查,直到`else`或是沒判斷式。
`else if` 可以是多個但第一個一定要是`if`。
```
if(條件式){
...
}
else if(條件式2){
...
}
else{
...
}
```
### switch
```
switch(變數名稱 或 運算式) {
case 數字 或 字元:
程式碼1
break;
case 數字 或 字元:
程式碼2
break;
default:
程式碼3
break;
}
```
switch後面括號可以直接放變數或是運算式
```
switch(a){
...
}
switch(x-y){
...
}
```
當你的變數或是運算有符合`case` 後面的數值,就會進入該`case`執行程式碼
後面的`break`是用來跳出switch,不然會繼續找`case`
```
switch(a){
case 1:
//當如果 a=1 就會執行這裡的程式碼
break;
case 2:
//當如果 a=2 就會執行這裡的程式碼
break;
}
```
如果你有多個條件要進入同一段程式碼,可以這樣寫
```
switch(a){
case 1: case 3:
//當如果 a=1 或 a=3 就會執行這裡的程式碼
break;
case 2:
//當如果 a=2 就會執行這裡的程式碼
break;
default:
//當如果 a不等於1或2 就會執行這裡的程式碼
break;
}
```
`default`是當`case`都不成立時就會執行的段落,必須放在最後面
```
switch(a){
case 1:case 3:
//當如果 a=1 或 a=3 就會執行這裡的程式碼
break;
case 2:
//當如果 a=2 就會執行這裡的程式碼
break;
}
```
### 關係運算符
| 運算符 | 描述 | 範例 |
|:------:|:--------------------:|:------:|
| == | 兩數是否相等 | a == b |
| != | 兩數是否不相等 | a != b |
| > | 前數是否大於後數 | a > b |
| < | 前數是否小於後數 | a < b |
| >= | 前數是否大於等於後數 | a >= b |
| <= | 前數是否小於等於後數 | a <= b |
回傳值為1(`true`)或是0(`false`)
舉例:
```cpp=
#include <iostream>
using namespace std;
int main()
{
int a = 20;
int b = 10;
int c ;
if( a == b ){ //括號內可自行更換運算符
cout << "a 等於 b" << endl ;
}
}
```
### 邏輯運算符
| 運算符 | 描述 | 舉例 | 範例 | 程式碼 |
|:------:|:------------:|:----------------:|:-------------------------:|:------------:|
| && | 且運算符 | X條件 && Y條件 | a大於b 和 b大於c | a>b && b>c |
| \|\| | 或運算符 | X條件 \|\| Y條件 | a小於b 或 a小於c | a<b \|\| a<c |
| ! | 否(非)運算符 | !X條件 | 非a大於b(等同 a小於等於b) | ! a>b |
## 循環
### for
```
for(起始式; 條件式; 更新式){
...
}
```
起始式:進入迴圈第一次會執行的動作
條件式:每輪執行前,會做一次檢查,如果成立就繼續迴圈,直到條件式不成立
更新式:每當執行完一輪,就會執行一次更新式
實作:
```cpp=
#include<iostream>
using namespace std;
int i;
int main(){
for(i=1;i<=10;i++){
cout<<i<<endl;
}
}
```
> i會從一開始(i=1),如果小於等於10(i<=10),就會執行i+1(i++),直到i不小於等於10
### while
```
while(條件式){
...
}
```
進入迴圈前會先檢查條件,成立後才會進入迴圈,迴圈會一直執行條件式不成立為止
實作:
```cpp=
#include<iostream>
using namespace std;
int i = 10;
int main(){
while(i<10){
cout<<"有進入迴圈"<<endl;
}
}
```
> 在while迴圈裡,只要i一直小於10,那就會一直在迴圈裡面循環,直到i不小於10。
### do...while
```
do{
...
}while(條件式)
```
迴圈會先執行一次,才會檢查條件,之後會一直執行條件式不成立為止
實作:
```cpp=
#include<iostream>
using namespace std;
int i = 10;
int main(){
do{
cout<<"有進入迴圈"<<endl;
}while(i<10)
}
```
> 在while迴圈裡,只要i一直小於10,那就會一直在迴圈裡面循環,直到i不小於10。
### break
在迴圈裡面執行到一半,要直接跳出迴圈時,可以使用`break`直接跳出,會跳離離他最近的迴圈
```cpp=
#include<iostream>
using namespace std;
int i = 1;
int main(){
while(i<10){
cout<<i<<endl;
if(i == 4){
break;
}
i++;
}
}
```
## 函式
一般來說,除了有主函式`main()`以外,也可以自訂自己的函式,當如果有同一區段的程式會需要多次的重複執行,自訂函式就可以讓你的主函式美觀一點。
### 宣告
```
回傳型態 名稱(引數){
副程式程式碼
}
Ex:
void test1(){
副程式程式碼
}
```
### 回傳型態
一般用於回傳數值給呼叫的地方,如果沒有要回傳值可以用 void 。
常見型態:
| 程式碼 | 名稱 |
|:------:|:------------:|
| void | 不會回傳東西 |
| int | 回傳整數 |
| char | 回傳字元 |
| double | 回傳浮點數 |
### 名稱
副函式可以有多個,名稱可以自訂,但有些像是主程式的main名稱是不能用的,
如果遇到不行使用的名稱編譯器會跟你講,不用擔心
### 參數&引數
引數可有可無,可以有多個引數,用於攜帶數值到副程式
在主程式的變數和副程式的變數名稱互不影響,即使取相同名稱也是不一樣的東西
呼叫函式時,提供給函式的資料叫做引數(argument),接受引數的叫做參數(parameter)
```cpp=
#include<stdio.h>
#include<stdlib.h>
//一個引數
void test1(int a){
//副程式程式碼
}
//多個引數
void test2(int a,char b,int c){
//副程式程式碼
}
//沒引數
void test3(){
//副程式程式碼
}
int main(){
int k=10,v=30;
char c='a';
test1(k);
test2(k,a,v);
test3();
}
```
<font color=#FF0000>注意,副函式宣告需要在main函式之前</font>
程式執行只會先從main函式執行,當有呼叫到副函式才會跳到副函式。
### 回傳值
回傳數值要用`return`,但要回傳的值資料型態要跟宣告副函式時的資料回傳型態一樣,
只要執行到`return`就會直接跳回到呼叫副程式的地方
參考以下程式碼。
```cpp=
#include<stdio.h>
#include<stdlib.h>
int add(int x,int y){
int z=x+y;
return z;
}
int main(){
int a=10,b=30,d;
d=add(a,b);
//執行後d會等於40
}
```
## 數字
要使用這些數學函式時,需要引用數學頭文件
```
#include <cmath>
```
常用的數學函式:
| 函數 | 回傳值型態 | 描述 |
|:------------------:|:----------:|:------------------------------------:|
| sin(double) | double | 正弦 |
| cos(double) | double | 餘弦 |
| tan(double) | double | 正切 |
| log(double) | double | 自然對數 |
| pow(double,double) | double | 前數為x,後數為y,函數會回傳x的y次方 |
| sqrt(double) | double | 平方根 |
| round(double) | int | 將小數四捨五入成整數 |
| abs(int) | int | 絕對值 |
| fabs(double) | double | 絕對值 |
### 隨機數
要使用這些隨機函數時,需要引用時間頭文件,這樣隨機函數才會隨著時間有變化,不然`rand()`
結果會固定。
```cpp=
#include <iostream>
#include <ctime>
using namespace std;
int main ()
{
int i,j;
// 設定種子
srand( (unsigned)time( NULL ) );
// 執行10次
for( i = 0; i < 10; i++ ){
j= rand();// 產生隨機數字
cout << j << endl;
}
return 0;
}
```
## 陣列
C++支援陣列數據結構,可以存放固定大小相同類型的集合。
### 宣告
宣告一個陣列,需要指定元素類型、數量
```
變數型態 陣列名稱 [ 陣列大小 ]
```
Ex.宣告一個類型為int,元素數量為5,名稱為a的陣列
```
int a[5];
```
陣列有 n 個空間,那編號就是是 0 ~ n - 1
| 編號 | a[0] | a[1] | a[2] | a[3] | a[4] |
|:----:|:----:|:----:|:----:|:----:|:----:|
| 數值 | 0 | 0 | 0 | 0 | 0 |
### 初始化
在C++中,可以逐個初始化陣列內的元素
`{}`大括號內的元素數量,不能超過`[]`中括號內的數字
```
int a[5] = { 2 , 1 , 4 , 5 , 3 };
```
| 編號 | a[0] | a[1] | a[2] | a[3] | a[4] |
|:----:|:----:|:----:|:----:|:----:|:----:|
| 數值 | 2 | 1 | 4 | 5 | 3 |
如果確定陣列內的元素數量和值,可以直接宣告,此時`[]`中可以不用打數字
```
int a[] = { 2 , 1 , 6 , 8 , 4 , 3 };
```
| 編號 | a[0] | a[1] | a[2] | a[3] | a[4] | a[5] |
|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
| 數值 | 2 | 1 | 6 | 8 | 4 | 3 |
### 數值修改
有一個陣列如下:
```
int a[] = {1,2,3};
```
| 編號 | a[0] | a[1] | a[2] |
|:----:|:----:|:----:|:----:|
| 數值 | 1 | 2 | 3 |
修改數字
```
a[1]=7;
```
| 編號 | a[0] | a[1] | a[2] |
|:----:|:----:|:----------------------------:|:----:|
| 數值 | 1 | <font color=#FF0000>7</font> | 3 |
## 字串
C++有兩種字串的表示法
* 字元陣列
* string 類型
### 字元陣列
字元字串是一些字元和結尾為`\0(又稱為null)`結尾組成的陣列
### * 定義
宣告一個類型為char(字元),元素數量為6,名稱為word的陣列
```
char word[6] = { 'H', 'e', 'l', 'l', 'o', '\0' };
```
同樣的也可以寫成這樣:
```
char word[] = "Hello";
```
C++編譯器在初始化字元陣列時,會自動把`'\0'`放在尾端
| 編號 | word[0] | word[1] | word[2] | word[3] | word[4] | word[5] |
|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
| 數值 | 'H' | 'e' | 'l' | 'l' | 'o' | '\0' |
範例:
```cpp=
#include <iostream>
using namespace std;
int main ()
{
char word1[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char word2[] = "Hello";
cout << word1 << endl;
cout << word2 << endl;
return 0;
}
```
這兩種執行結果會一樣
有一些函式可以用來控制字串
| 函式 | 說明 |
|:----:|:----:|
| strcpy(s1, s2); | 複製字串2(s2)到字串1(s1) |
| strcat(s1, s2); | 把字串2(s2)連接到字串1(s1)的尾端 |
| strlen(s1); | 回傳字串1(s1)的長度 |
| strchr(s1, c); | 回傳字元c在字串1(s1)第一次出現的位置 |
| strstr(s1, s2); | 回傳字串2(s2)在字串1(s1)第一次出現的位置 |
### string 類型
string除了有上述字元陣列的功能,引入`<string>`的頭文件,還有增加其他更多個功能可以使用。
```cpp=
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;
// 複製str1到str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// 連接str1和str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// str3的字串長度
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}
```
## 指標
### 指標是什麼?
平常程式執行時
```
int main(){
int a = 18;
int b = 7;
int c = 50;
int d = 100;
int e = 12;
}
```
以 `int a = 18;` 為例,程式執行時,處理器會去跟記憶體要一塊空間,把18這個資料放進去。
| 變數型態 | 位元組 |
|:--------:|:------:|
| bool | 1 |
| char | 1 |
| int | 4 |
| long | 8 |
| float | 4 |
| double | 8 |
一塊空間的大小,會隨著資料型態產生變化,把記憶體比喻成一棟大樓,一個位元組為一層樓,像是一個`int`變數就需要4層樓才能存放。
以上述程式碼舉例,存放在記憶體內就長這樣
| 記憶體位址(起始位址) | 數值 |
|:----------:|:-----------:|
| 0x0012FF6c | ... |
| 0x0012FF70 | 18 |
| 0x0012FF74 | 7 |
| 0x0012FF78 | 50 |
| 0x0012FF7c | 100 |
| 0x0012FF80 | 12 |
| 0x0012FF84 | ... |
註1:記憶體位址是由處理器分配的,每次執行程式時記憶體位址都可能不一樣。
註2:記憶體位址為16進位。
<br><br>
也就是說,當我們宣告一個變數時,會有三個元素:
| 變數位址(起始位址) | 變數數值 | 變數名稱 |
|:----------:|:-----------:| :---: |
| 0x0012FF70 | 18 | a |
除禮器會向記憶體要一塊空間來儲存變數,這個儲存空間有一個起始位址。加上這個變數的名稱a與變數值18。
通常會把變數的位址,稱為「指向該變數的指標」。
### 取址
在`C++`中取址的方式就是放`&`在變數前面
```cpp=
#include<iostream>
using namespace std;
int main(){
int a = 18;
cout << "變數 a 的值:" << a << endl;
cout << "變數 a 的記憶體位址:" << &a << endl;
}
```
這個程式中,宣告了一個 int 整數 a,並印出「&a」的值,知道 a 所在的記憶體位址
### 取值
利用`*pointer`的方式去讀取該位址的值
```cpp=
#include<iostream>
using namespace std;
int main(){
int a = 18;
cout << "變數 a 的值:" << a << endl;
cout << "變數 a 的記憶體位址:" << &a << endl;
cout << "變數 a 的位址的值:" << *&a << endl;
}
```
也可以說,`*&a`和`a`是等價的。
### 指標變數
當今天有了指標,就會需要存放指標的變數
平常程式執行時
```
int* pointer
```
宣告時,用`*`來表示 pointer 這個變數是個指標
```
int b;
b = 2;
int* pointer;
pointer = &b;
```
`&`是用來把變數的地址取出來,
<font color=#FF0000>注意,不能寫成`pointer = b;`, pointer 是專門存放地址的變數。</font>
```
pointer = &b;
```
又稱:指標變數 pointer 指向了變數 b
當要取指標變數的值時,也等同於取變數b的值
```cpp=
#include<iostream>
using namespace std;
int main(){
int b = 18;
int* pointer = &b
cout << "變數 b 的值:" << b << endl;
cout << "變數 b 的記憶體位址:" << &b << endl;
cout << "變數 pointer 的值:" << pointer << endl;
cout << "取 pointer 位址的值:" << *pointer << endl;
}
```
## 數據結構
###### tags: `C/C++`
## 存儲