---
# System prepended metadata

title: C++學習筆記

---

# C++學習筆記

:::info
**Zong Yan** & **You Jun** 
:::

---
## :book:學習內容

### :small_blue_diamond: 基本輸入輸出、變數、資料類別
### :small_blue_diamond: if判斷、switch判斷
### :small_blue_diamond: for迴圈、一維陣列
### :small_blue_diamond: while迴圈、迴圈控制(contunu、break))
### :small_blue_diamond: 多維陣列、多重迴圈
### :small_blue_diamond: function函式
### :small_blue_diamond: 字串(string)、常用字串函數
### :small_blue_diamond: struct結構
### :small_blue_diamond: 遞迴
---
## :books:學習方式

```mermaid
graph LR
看資料做題目-->會;
看資料做題目-->不會;
會-->特殊;
會-->不特別-->有印象就好;
特殊-->解題報告
不會-->看看其他人的解題報告;
看看其他人的解題報告-->了解概念並自己做一次-->會;

```

---

## :speak_no_evil:基本輸入輸出、變數、資料型態

:::success
非常直觀
:::

### :computer:輸入/輸出
```c++=
#include <bits/stdc++.h>  //標頭檔

using namespace std;

int main()
{
    int n; //宣告整數n
    cin>>n; //輸入n
    cout<<n<<endl; //輸出
    
    
    return 0; //記得不要消失就好
}
```
#### :nerd_face:
標頭檔  
可以把它想成圖書館，每個書櫃都裝不同類型的書，當你要用書時，就會去那類的書櫃尋找，這時```include <    >```就像去那個書櫃。\
標頭檔有超多種，我覺得很難記:relieved:有個很好用的東西```#include <bits/stdc++.h>```包括了所有標頭檔案，很好用:smirk: 



### :desktop_computer: 資料類型 


|表示方法|範圍|用途|
|:--:|:--:|:--:|
|int|-2,147,483,648 ~ 2,147,483,647|放整數|
|unsigned int|0 ~ 4,294,967,295|放整數|
|short|-32,768 ~ 32,767|放整數|
|long long|-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807|放整數|
|unsigned long long|0 ~ 18,446,744,073,709,551,615|放整數|
|char||放字元|
|float|10^-38^ ~ 10^38^|放浮點數(7位)|
|double|10^-308^ ~ 10^308^|放浮點數(15位)|

#### :nerd_face:
使用方式: 表示方法 資料名稱

***例*** : 宣告一個整數(<2147483647)
```int n;```  
:grimacing:注意!!!避免溢位

[link:zerojudge c221](https://zerojudge.tw/ShowProblem?problemid=c221 "前往")

:::warning
駭客題:這題很酷  
//奇妙的緣分遇到這題
```c++=
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
cout<<a+b<<'\n';
}
```

題目:請輸出一組合法的a,b，使上述程式輸出錯誤答案  

可以看到範圍是int  
只需要讓他超出範圍，a+b答案就錯了  
```
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<2147483645<<" "<<5<<'\n';
}
```

原本我以為這題很簡單，結果一開始看到很錯愕  
溢位(overflow) :+1: 

:::
<br>


## :speak_no_evil:if判斷、switch判斷  

:::success
~~能用if 我就不用switch~~，還有一個三元運算子
:::

### if語法
```c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
   
    if(條件) 
    {
        如果條件成立執行的動作
    }
    else
    {
        如果條件不成立執行的動作
    }
    return 0;
}
```
[link: zerojudge c461](https://zerojudge.tw/ShowProblem?problemid=c461 "前往")

:::warning
題目敘述去zerojudje看  
有a,b兩數(0和1)  
AND:使用```(a&b)```當兩數皆為1，結果為1，其餘為0  
OR:使用```(a|b)```當兩數其一為1，結果為1，其餘為0  
XOR:使用```(a^b)```當兩數不相同，結果為1，其餘為0  
接下來就加上if判斷  
!!!注意運算子優先順序  
[參考連結](http://programingman.blogspot.com/2015/01/cc.html "前往")
```c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    int m,n;
    bool a;
    while(cin>>m>>n>>a)
    {
        bool f=0; //判斷是否有結果
        if(m)m=1;
        if(n)n=1;
        if((m&n)==a)
        {
            cout<<"AND"<<"\n";
            f=1;              //有結果
        }
        if((m|n)==a)
        {
            cout<<"OR"<<"\n";
            f=1;
        }
        if((m^n)==a)
        {
            cout<<"XOR"<<"\n";
            f=1;
        }
        if(f==0)             //沒有
            cout<<"IMPOSSIBLE"<<"\n";
    }
    
    return 0;
}
```
:::

### switch語法
```c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    switch(要判斷的東西)
    {
        case 第一種結果:
        執行的動作
        break;   //很重要
        
        case 第二種結果:
        執行的動作
        break;
        .
        .
        .
        case 第n種結果:
        執行的動作
        break;
        
        default: //結果都不成立
        執行的動作
        break;
        
    }
    return 0;
}
```
### 三元運算子(適當使用能省很多行)
```c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    cout<<(條件 ? 如果條件成立執行的動作 : 如果條件不成立執行的動作 );
    return 0;
}
```
---


## :speak_no_evil:for迴圈、一維陣列
:::success
陣列的第一個位置是0!:no_mouth::no_mouth::no_mouth:
:::
### for迴圈語法



``` c++=
#include<bits/stdc++.h>

using namespace std;

int main()
{
    for(初始值;條件;調整)
    {
        執行的動作;
    }
    return 0;
}
```
### 一維陣列

| 0   | 1   | 2   | 3   | 4   | 5   | 6   | 7   | 8   | index(索引值)    |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|  1   |  3   |  5   |  7   |  9   |  11   |  13   |   15  |  17   |  value(存放的內容)   |

```c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
宣告一維陣列
int a[5];  //初始值不確定，陣列大小為5
int b[5]={}; 
int c[5]={0}; //後面會全部填0
int d[5]={0,0,0,0,0}  //初始值全部是零
int e[]={0,0,0,0,0}   //陣列大小為5

return 0;
}

```
### :bookmark: 
10~13簡單來說，只要有給初始值，後面沒給的全部自動填0

## :speak_no_evil:While迴圈，進階迴圈控制(continue,break)
:::success
while迴圈常用在不確定迴圈次數;for迴圈常用在已知迴圈次數
:::
### while語法(先判斷條件才執行動作)
``` c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    初始值
    while(條件)
    {
        執行的動作;
        調整;
    }
   return 0;
} 
``` 

### do while語法(一定先執行一次動作再判斷條件)
``` c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    初始值
    do
    {
        執行的動作;
        調整;
    }while(條件);  //這裡要加分號
   return 0;
} 
``` 
### 進階迴圈控制(continue,break)
#### continue:如果條件成立，直接跳到下一次迴圈
#### break:如果條件成立，結束所在的迴圈
---
#### continue
``` c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    int sum=0;
    for(int i=1;i<=10;i++)
    {
        if(i%2==0)   //如果i是偶數，底下的動作不會執行，直接跳到下一次迴圈
        {
            continue;
        }
        sum+=i;
    }
    cout<<sum;
    return 0;
}
```
#### break
``` c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,sum=0;
    while(cin>>n)
    {
        if(n==0)
        {
            break;   //只要n=0，就結束迴圈
        }
        sum+=n;
    }
     cout<<sum;       
    return 0;
}
```
## :speak_no_evil:多維陣列、多重迴圈 
:::success
這個東西很... :exploding_head: :exploding_head::exploding_head:
:::
### 多重迴圈
``` c++=
#include <bits/stdc++.h>

using namespace std;

int main()
{
    for(int i=1;i<=9;i++)  //外圈
    {
        for(int j=1;j<=9;j++) //內圈
        cout<<i<<"*"<<j<<"="<<i*j<<endl; //外圈跑一次，內圈跑九次
    }
     return 0;
}
```
### 二維陣列(直行橫列) (i,j)
| (0,0) | (0,1) | (0,2) | (0,3) |
| ----- |:----- | ----- |:----- |
| (1,0) | (1,1) | (1,2) | (1,3) |
| (2,0) | (2,1) | (2,2) | (2,3) |
| (3,0) | (3,1) | (3,2) | (3,3) |


io加速
```c++=
std::ios::sync_with_stdio(false);
std::cin.tie(0);
```
## :speak_no_evil:function函式
:::success
重複使用
:::
### 語法
``` c++=
回傳值類型 函式名(輸入值類型 a,輸入值類型 b)    //用,分隔
{
    .
    .
    .
    return 回傳值;
}

int sum(int a,int b)
{
    return a+b;      //回傳兩值相加
}
/*回傳值類型
void:無回傳值
auto:從return句推斷類型
*/

int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        cout<<sum(a,b)<<"\n";    //呼叫sum函式
    }
    
    return 0;
}
```
## :speak_no_evil:字串(string)、常用字串函數
:::success
字元陣列，就是把很多字排成陣列
:::

### 語法
```c++=
宣告
string str1;    //內容為空字串
string str2="XXX";    //字串是XXX
//上面={'X','X','x','\0'}後面會加一個空字元

讀入
string str1;
cin>>str1;    //輸入I am back
cout<<str1;   //顯示只有I,因為C++判定cin的時候，空白被當成定界符

getline(cin,str1);    //可以讀入整行字串
cout<<str1;//顯示I am back 

getline(cin,str1,'#');    //讀入整行字串，遇到#停止 輸入hey hey #ahh
cout<<str1;    //輸出僅有hey hey，因為遇到#停止了

string s;
getline(cin, s, EOF);     //全

字串可相加
string str1="C++";
string str2="is cool";
string str3=str1+str2; //C++is cool

可利用索引值找相對應的字元
str1="I like C++";
str1[0]='I'
str1[1]=空白
str1[2]='l'

遍歷字串每一個字元
string str1;
for(int i=0;i<str1.size();i++)
cout<<str1[i]<<"\n"

for(auto ch : str1)    //auto自動判斷變數類型(C++11)
cout<<ch<<"\n"
```
---
### size(),length()取得字串長度，empty()判斷字串長度是否為零
```c++=
str1="I like C++";
str1.size()=10
str1.length()=10

str1="I like C++";
str2="";
str1.empty=0   //如果字串為空輸出1，不為空則輸出0
str2.empty=1
```
---
### substr利用索引值和指定長度尋找子字串，resize修改字串長度和內容
```c++=
substr(索引值，指定長度)
str1="I like C++";
cout<<str1.substr(2,4);    //顯示like

resize(修改長度，新增字元)
str1="I like C++";
cout<<str1.resize(str1.size()+2,'-');    //顯示I like C++--
注意 string str2=str1.resize(8);   //此行錯誤(resize沒有回傳值)
```
---

### strungstream字串流(型態的轉換)
``` c++=
string str;
stringstream ss;
cin>>str;    //999
str+=1;    //錯誤，string 不可直接加數字

int n;    //如果str要輸入小數就用double
ss<<str;    //str放入ss
ss>>n;    //ss給n數字
n+=1;
cout<<n;    //1000

string s="2 4 8";
stringstream ss(s);    //
int a=0,b=0,c=0,d=0;
ss >> a;    //第一個字轉成int給a
ss >> b;    //第二個字轉成int給a
ss >> c;
ss >> d;
cout << a << " " << b << " " << c << " " << d << "\n";    //2 4 8 0 轉出的不會重複
cout <<ss.str();    //2 4 8 ss.str() 直接印出ss中的字串

string s=" 2 4 8"
stringstream ss(s);
string st="1";
ss << st;    //ss 1 4 8    //2被覆蓋

string s=" 2 4 8";
stringstream ss;
ss<<s;
string st="1";
ss << st;    //ss 2 4 81 沒有空格

//stringstream沿用需清空之前的資料
ss.str("");    //只用這個會讀到EOF
ss.clear();    //只用這個會僅清掉EOF接續之前放入的資料
//少一行都會出錯

```


## :speak_no_evil:struct結構

:::success
把多個項目包起來
:::

### 語法
```c++=
struct someone{
    char name[10];
    int age;
    int height;
    int weight;
};

int main() {
    struct someone s1,s2;    //宣告
    strcpy(s1.name, "Lisa");    //把"Lisa"複製到s1的name
    s1.age = 18;
    s1.height = 155;
    s1.weight = 40;
    cout<<"name:"<<s1.name<<"\n";    //name:Lisa
    cout<<"age:"<<s1.age<<"\n";    //age:18
    cout<<"height:"<<s1.height<<"\n";
    cout<<"weight:"<<s1.weight<<"\n\n";
    
    strcpy(s2.name, "Gigi");
    s2.height = 155;
    s2.age = 18;
    s2.weight = 40;
    cout<<"name:"<<s2.name<<"\n";
    cout<<"age:"<<s2.age<<"\n";
    cout<<"height:"<<s2.height<<"\n";
    cout<<"weight:"<<s2.weight<<"\n";
    
    return 0;
}
```
## :speak_no_evil:遞迴
:::success
呼叫自己，注意要設停止點
:::
### 語法  
```c++=
//和函式差不多
int f(int n)    //5
{
    if(n==1)
        return 1;
    else 
        return n*f(n-1);
}
int main()
{
    int a=5;
    cout<<f(a);    //120
}
```
```mermaid
graph LR
n=5--呼叫f-->n=4--呼叫f-->n=3--呼叫f-->n=2--呼叫f-->n=1
subgraph 相乘1
n=1-->n=2
end
subgraph 相乘2
n=2-->n=3
end
subgraph 相乘3
n=3-->n=4
end
subgraph 相乘4
n=4-->n=5
end
```
#### 以上程式可得f(a)=1\*2\*3\*4\*5=120

