TCIRC C++教學講義
===
>[name=張皓凱、沈奕呈][time=Oct 15,2021]
###### tags:`tcirc` `社課` `C++` `台中一中電研社`
---
第二節社課
===
[TOC]
---
## 電研
講義都會公告在社網上
[社網:tcirc.tw](https://tcirc.tw/)
[IG:tcirc_39th](https://www.instagram.com/tcirc_39th/)
![ig QRcode](https://i.imgur.com/4hyS6GM.png)
[online judge:judge.tcirc.tw](https://judge.tcirc.tw/)
---
## 資料型態之間的轉換
----
### 數字
不同的資料型態在計算時會發生一些變換,在撰寫程式時必須特別注意以下規則:
1. 當整數和浮點數進行運算時,統一轉換為浮點數運算。否則一律以整數運算
2. 當2個大小不同的整數/浮點數做運算時,較大的型別會被採用。short一律當作int計算
3. 字元做運算時,統一轉換為整數
4. 在賦值時,「計算結果」統一轉換為該變數的資料型態(計算時依舊為原計算模式)利用(資料型態)可作強制轉換
----
```cpp=
#include<iostream>
using namespace std;
int main(){
double a = 5000/3;
//"5000/3" is calclated in int then assigned to double
cout << a << '\n';
double b = 5000.0/3;
//"5000.0/3" is calculated in double then assigned to double
cout << b << '\n';
double c = 2.25;
int d = c;
//double is converted to int before assigning
cout << d << ' ' << c*d << ' ' << (int)(c*d) << '\n';
char k = 'A';
//char is converted to int during compution
cout << k + 5 << ' ' << k + 'A' << ' ' << '\n';
short x = 5000;
cout << x*x << ' '; //short is converted to int during compute
x = x*x; //int is converted back to short during assignment
cout << x << '\n';
}
```
```
/*OUTPUT---
1666
1666.67
2 4.5 4
70 130
25000000 30784
------------*/
```
----
### 數字及字元
可以利用`(int)`及`(char)`對字元及整數進行轉換,轉換結果會依照ASCII碼。若是想要將`'0'~'9'`之間的字元轉換為`0~9`的數字,可以透過`-'0'`來達成。
```cpp=
#include <iostream>
using namespace std;
int main(){
int a = 65;
char b = 'a';
char c = '5';
int d = c;
int e = c - '0';
cout << (char)a << " " << (int)b << endl;
cout << d << " " << e;
}
```
```
/*OUTPUT---
A 97
53 5
------------*/
```
---
## 溢位
既然資料型態有範圍,那如果數字超出了範圍會怎樣?當變數的值超出範圍,我們就稱這個情況為溢位(overflow)。如果我們宣告(int)一個整數i的值為2147483647,值的範圍會落在int的範圍內。但是這時我們使 i+1 便會發生溢位的狀況,這時的i會回到int的最小值-214748348。
---
## bool
bool(布林)是一種邏輯資料型態,所能存放的只有0(false)和1(true),預設數值為0。在賦值時可以設定為true, falae或者是任意數字,當設定為數字時,若數字為非零整數,則變數值為1,若為零,則變數值為0。
----
```cpp=
#include <iostream>
using namespace std;
int main(){
bool a=true;
bool b=0;
bool c=9201.32;
cout << a << " " << b << " "<< c;
}
```
```
/*output---
1 0 1
------------*/
```
---
### 運算
布林值的運算又稱為邏輯運算,常見有`&&`(且)、`||`(或)和`!`(非),其運算結果如下:
| && | 0 | 1 |
|:--------:|:---:|:--------:|
| 0 | <font color="#f00">0</font> | <font color="#f00">0</font> |
| 1 | <font color="#f00">0</font> | <font color="#f00">1</font> |
----
| \|\| | 0 | 1 |
|:--------:|:--------:|:--------:|
| 0 | <font color="#f00">0</font> | <font color="#f00">1</font> |
| 1 | <font color="#f00">1</font> | <font color="#f00">1</font> |
| | 0 | 1 |
|:----:|:----:|:----:|
| ! | <font color="#f00">1</font> | <font color="#f00">0</font> |
----
`&&`跟`||`的寫法與加減乘除相同,而`!`則是加在布林值之前
```cpp=
#include <iostream>
using namespace std;
int main(){
bool a=1;
bool b=0;
bool c=a&&a;
cout << c << " ";
c=!(b||true);
cout << c;
}
```
```
/*output---
1 0
------------*/
```
---
## 比較運算子
比較運算子是用於比較兩邊關係的運算子,以下將列出常用的比較運算子:
----
| 比較運算子 | 意義 |
| -------- | -------- |
| > | 大於 |
| < | 小於 |
| == | 相等 |
| >= | 大於等於 |
| <= | 小於等於 |
| >< | 大於小於,不相等 |
| != | 不相等 |
----
<font color="#f00">注意!</font>
* `=`是設定運算子,如果要比較是否相等要使用`==`
* 若包含兩個字元的比較運算子不可以前後寫相反,例如:`<=`不可以寫成`=<`
---
## 條件式
條件式是我們在程式中用來比較關係時用的,最常見是用於比較兩個數值。結果為布林值,若敘述正確為`true(1)`否則為`false(0)`,其寫法如下:
```
變數/常數 比較運算子 變數/常數
```
----
```cpp=
#include <iostream>
using namespace std;
int main(){
int i=5, j=7;
bool a = i<=6;
bool b = i==j;
cout << a << " " << b << " ";
}
```
```
/*output---
1 0
------------*/
```
---
## 條件敘述 if-else
條件敘述是指程式依照特定條件的真或假而選擇不同的執行路徑,最常見的條件敘述就是if-else。
----
### 基本寫法
當小括號內的條件式或布林值為true時,就會執行大括號內的程式,否則直接繼續執行if後的程式。
```cpp=
if(條件式或bool){
code;
...
}
```
* 小括號後<font color='#f00'>不需要</font>加分號
* 大括號後<font color='#f00'>不需要</font>加分號
* 條件式<font color='#f00'>不需要</font>加分號
* 大括號內的每一行程式都<font color='#f00'>需要</font>加分號
----
```cpp=
#include <iostream>
using namespace std;
int main(){
bool a=false;
if(a){
cout << "a=true";
}
if(7>=6){
cout << "7 >= 6";
}
}
```
```
/*output---
7 >= 6
------------*/
```
---
### else
當小括號內的條件式或布林值為true時,就會執行第一個大括號內的程式,否則執行else後的大括號內程式。
```cpp=
if(條件式或bool){
code;
...
}else{
code;
...
}
```
----
```cpp=
#include <iostream>
using namespace std;
int main(){
int a=5;
int b=10;
if(a>b){
cout << "a>b";
}else{
cout << "a<=b";
}
}
```
```
/*output---
a<=b
------------*/
```
---
### 巢狀if
巢狀if指的是if當中還有if,像鳥巢一樣一層一層的。
```cpp=
if(條件式或bool){
code;
if(條件式或bool){
code;
}
code;
}else{
code;
if(條件式或bool){
code;
}
code;
}
```
----
```cpp=
#include <iostream>
using namespace std;
int main(){
int a=5;
int b=10;
int c=7;
if(a>b){
cout << "a>b and ";
if(b>c){
cout << "b>c";
}else{
cout << "b<=c";
}
}else{
cout << "a<=b and ";
if(b>c){
cout << "b>c";
}else{
cout << "b<=c";
}
}
}
```
```
/*output---
a<=b and b>c
------------*/
```
---
### else if
else if可以把它看成是一種朝狀if的簡寫。當else當中只有if時就可以將if哪出括號外變成else if。
```cpp=
if(condition A){
code A;
}else{
if(condition B){
code B;
}else{
code C;
}
}
```
```cpp=
if(condition A){
code A;
}else if(condition B){
code B;
}else{
code C;
}
```
----
```cpp=
#include <iostream>
using namespace std;
int main(){
int a=19;
int b=10;
if(a>b){
cout << "a>b";
}else if(a==b){
cout << "a=b";
}else{
cout << "a<b";
}
}
```
```
/*output---
a>b
------------*/
```
----
在if-else當中,if是可以單獨存在,else與else if不行。在一組包含if,else if,else的程式當中,if只能有一個並且在最上面,else if可以有無限多個,else只能有一個並且在最後。
---
### 簡寫
----
當if,else if, else後的大括號中只有一行程式時,可以將大括號去掉,直接接在小括號後即可
```cpp=
if(condition){
code;
}else if(conditioin){
code;
}else{
code;
}
```
```cpp=
if(condition)code;
else if(condition)code;
else code;
```
----
當只有if及else,且大括號內接只有一行程式碼時,可以使用`?:`取代。
```cpp=
if(condition){
code A;
}else{
code B;
}
```
```cpp=
(condition)? code A : code B;
```
<font color="#f00">注意:</font>只需要有一個分號
----
```cpp=
if(a>b){
cout << "a>b";
}else{
cout << "a<=b";
}
```
```cpp=
(a>b)? cout << "a>b" : cout << "a<=b";
```
---
### 題目練習:[b013: 閏年問題](https://judge.tcirc.tw/ShowProblem?problemid=b013)
### 題目練習:[b014: 串串的三角形](https://judge.tcirc.tw/ShowProblem?problemid=b014)
---
## switch(補充)
有天串串的朋友電電,出了一道題來為難整天埋頭寫程式的串串
- 當數字=1,執行I
- 當數字=2,執行H和I
- ...
- 當數字=9,執行A.B.C...I(九個)
- 如果是3.4.6.7則執行三次A
- 其他數字則不執行
----
當條件很零散,或多種條件做同一件事情的時候
寫那麼多if是不是很累?
試試switch吧!
```cpp=
#include<iostream>
using namespace std;
int main(){
//成績等第分級
int x;
while(cin>>x){
switch(x/10){//別忘了int除int會捨去餘數
case 10:
case 9:{//90~99和100分
cout<<"excellent";
break;
}
case 8:{//80~89分
cout<<"great";
break;
}
case 7:{//70~79分
cout<<"good";
break;
}
case 6:{//60~69分
cout<<"so so";
break;
}
default:{//其他(不及格)
cout<<"bad";
break;
}
}
cout<<'\n';
}
return 0;
}
```
----
switch的用法:
- switch的條件須為 `int`,`bool` 或 `char` 型態的變數
- 需對應相應型態的case(列舉的方式)
- 3.當符合某個case會執行以下所有case中的程式碼直到 `break;`
- 4.`default` 當所有case都無法對應時執行
----
所以寫switch須特別注意前三點,
<font color="#f00">注意: 千萬記得加break!!!</font> 否則下面的case都會執行
因為switch的第一點限制,條件還要一個一個寫,所以使用switch的頻率比if低很多,但是當條件零散的時侯,switch可以幫你省下很多時間喔!
----
再回來看看一開始的問題
(看來電電學switch的時候在玩電腦😏)
```cpp=
#include<iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
cout<<n<<": ";
switch(n){
case 9: //a~i
cout<<'A'<<' ';
case 8:{//b~i
cout<<'B'<<' ';
cout<<'C'<<' ';
cout<<'D'<<' ';
}
case 5:{//e~i
cout<<'E'<<' ';
cout<<'F'<<' ';
cout<<'G'<<' ';
}
case 2: //H.I
cout<<'H'<<' ';
case 1:{//I
cout<<'I'<<' ';
break;
}
//A*3
case 3:
case 4:
case 6:
case 7:{
for(int i=0;i<3;i+=1)
cout<<'A'<<' ';
break;
}
}
cout<<'\n';
}
return 0;
}
```
----
```
/*input---
9 8 7 6 5 4 3 2 1
------------*/
```
```
/*output---
9: A B C D E F G H I
8: B C D E F G H I
7: A A A
6: A A A
5: E F G H I
4: A A A
3: A A A
2: H I
1: I
------------*/
```
---
## 迴圈(loop)🔄
有時候我們寫程式是因為**重複做類似的事情**會花我們很多時間,而讓電腦去做,可以省下需多時間。
使用**迴圈**可以重複執行某段程式,減少程式複雜性,以下會介紹常見的幾種loop
---
### while
while loop的寫法是 `while(條件){}`
- 每當條件(邏輯判斷式)成立,
就會執行 `{}` 裡面的程式碼一次
- 當條件不成立,
則程式就會略過 `{}` 裡的內容繼續往下跑
----
```cpp=
#include<iostream>
using namespace std;
int main(){
//example 1
int n=9;
while(n){//當數字不等於0在bool運算皆成立
cout<<n;
n--;
}
cout<<'\n';
//example 2
int i=1,grade;
while(i<=5){
cin>>grade;
if(grade>=60)//一行解決不須{}
cout<<i<<":及格"<<'\n';
else
cout<<i<<":不及格"<<'\n';
i++;
}
return 0;
}
```
----
```
/*input---
65 60 59 100 0
------------*/
```
```
/*output---
987654321
1:及格
2:及格
3:不及格
4:及格
5:不及格
------------*/
```
---
### 題目練習:[b017: 病毒的增生](https://judge.tcirc.tw/ShowProblem?problemid=b017)
---
### for
前一頁的第二個while loop花了三行程式碼分別初始化變數、判斷條件、固定對宣告的變數運算
有沒有辦法把這幾個有關連的事寫在一起呢?這時候就用for loop吧!
----
如果程式要做的事情跟執行次數有關的話(比如說第一天花一元,第二天花兩元...或是記錄班上每個座號的身高體重換算BMI)這時候用 `for` 會比 `while` 方便很多
----
for loop的寫法是
`for(初始化;條件;每次迴圈結束後做的事){}`
- 要記得 `for` 的`()` 裡面這三個要素,
還有每個要素之間要用 `;` 隔開,
- 如果不需要某個要素的功能的話
可以不用寫該要素,但是**分號不能省略**!!!
----
```cpp
#include<iostream>
using namespace std;
int main(){
/* compare with while loop
---------while loop example 2----------
int i=1,grade;
while(i<=5){
cin>>grade;
if(grade>=60) cout<<i<<":及格"<<'\n';
else cout<<i<<":不及格"<<'\n';
i++;
}
*/
//------example 2 using for loop--------
for(int i=1,grade;i<=5;i++){
cin>>grade;
if(grade>=60) cout<<i<<":及格"<<'\n';
else cout<<i<<":不及格"<<'\n';
}
cout << endl;
//輾轉相除法
for(int x=135,y=35 ; y!=0 ; cout<<x<<' '<<y<<'\n'){
x%=y;
swap(x,y);//交換x,y
}
cout << endl;
//example 4
for(int q=5;q>0;){
q-=2;
cout<<q<<' ';
}
return 0;
}
```
----
```
/*input---
65 60 59 100 0
------------*/
```
```
/*output---
1:及格
2:及格
3:不及格
4:及格
5:不及格
35 30
30 5
5 0
3 1 -1
------------*/
```
---
### 題目練習:[b021: 電電找因數](https://judge.tcirc.tw/ShowProblem?problemid=b021)
---
### do while
前面 `while` 是先判斷條件再執行程式碼,
- 但當無論條件如何,都必須先執行一次loop裡的一次程式碼時,可以使用 `do while`
----
- `do while` 是先執行再判斷條件,保證你可以至少執行一次迴圈裡的程式
- 除非有**一開始就不符合條件**的情況,不然`while`和`do while`跑出來的結果基本上是一樣的
----
```cpp=
#include<iostream>
using namespace std;
int main(){
//example
cout<<"whlie loop: ";
int n=9;
while(n){
cout<<n;
n--;
}
cout<<'\n'<<"do-while loop: ";
int a=9;
do{
cout<<a;
a--;
}while(a);
cout<<'\n';
//compare with example
cout<<"whlie loop 2: ";
n=9;
while(n==8){
cout<<n;
n--;
}
cout<<'\n'<<"do-while loop 2: ";
a=9;
do{
cout<<a;
a--;
}while(a==8);//after do the first time,
//the codition allow you to do the second time
cout<<'\n';
return 0;
}
```
----
```
/*output---
whlie loop: 987654321
do-while loop: 987654321
whlie loop 2:
do-while loop 2: 98
------------*/
```
---
### break/continue
#### break
直接結束迴圈
#### continue
跳過此次迴圈的剩餘程式,直接開始下一次迴圈
----
```cpp=
#include<iostream>
using namespace std;
int main(){
for(int i=0;i<10;i+=1){
if(i==4) continue;
if(i==7) break;
cout<<i<<' ';
}//example 1
cout<<'\n'<<'\n';
int k=10;
while(k--){//先判斷再-1
if(k%2==0) continue;
cout<<k<<' ';
if(k==8) break;//被continue跳過
if(k==3) break;
}//example 2
return 0;
}
```
----
```
/*output---
0 1 2 3 5 6
9 7 5 3
------------*/
```
---
## 區塊
---
## 題目練習
* [b020: 慎思湖的倒影](https://judge.tcirc.tw/ShowProblem?problemid=b020)
* [c003: Ⅲ.相親相愛](https://judge.tcirc.tw/ShowProblem?problemid=c003)
{"metaMigratedAt":"2023-06-16T11:58:40.331Z","metaMigratedFrom":"YAML","title":"C++教學講義-第二週","breaks":true,"slideOptions":"{\"theme\":\"blood\",\"transition\":\"slide\"}","contributors":"[{\"id\":\"6a5475c5-bfd3-428c-9219-c760b9000deb\",\"add\":9404,\"del\":1475},{\"id\":\"a031de8f-38ef-4123-9d53-e13dd69cbbc3\",\"add\":5682,\"del\":592}]"}