<!-- 簡報宣告 -->
# C++ & python 語法
#### 第2週社課
## 講者:鄭勝宇、郭久銘
---
# C++
----
## ——————目錄—————
- 資料型別、變數、操作符號
- 基礎I/O
- 判斷句
- for、while迴圈及其控制
(還有do...while...)
- 陣列
- 結構 struct
- 函數、inline函數
- pointer、pointer array
----
<!-- https://hackmd.io/@niter/HJjhdnkgj#/1/1 -->
<!-- -->
## 資料型別
這裡介紹c++ 的基本型別們
先介紹整數家族
* short $\small(-32768,32767)$
* int $\small(-2147483648, 2147483647)$
常用,8bytes
* long$\small(-2147483648, 2147483647)$
用不到,佔的bytes數跟作業系統有關
----
## 資料型別
這裡介紹c++ 的基本型別們
先介紹整數家族
* long long $\small(-2^{63} , 2^{63}-1)\approx(-9\times10^{18}, 9\times10^{18})$
通常題目數字給在$10^9$以上的時候就得用
* __int128
處理極大數字的時候才用到,如果會py其實可以不用cpp,輸出輸入還得自己寫,很多編譯器過不了,含codeblocks,ZJ可
這些整數型別前面加一個unsigned就可以翻倍儲存
----

----

----
## 資料型別
接著是浮點數家族,會有浮點數誤差!!!
實作方式是科學記號
* float $\small\approx(-1.7\times10^{38}, 1.7\times10^{38})$
幾乎用不到
* double $\small\approx(-3.4\times10^{308}, 3.4\times10^{308})$
記得!!會有浮點數誤差!!!
$1+2=3.000000004$
----

----
## 資料型別
再來是char和string
* char $(-128,127)$ 1個byte
用單引號,除了要一個字一個字讀的題目,不然根本用不到
* string
用雙引號,其結構大小等價於$sizeof(char)\times s.size()$
----
## @ 題外話 ASCII碼
歪國人把英文字母還有常用符號塞進了一個char個大小裡面,紅色框框代表記一下


接下來就是變數
----
## 變數
宣告語法
```
datatype variable_name;
datatype variable_name = initial_value;
```
例如
```
unsigned long long ten = 11;
double e = 2.718281828459045;
char c = 'V';
```
----
## 操作符號
* 算數運算符:+, -, *, /, %
* 遞增運算符:++, \-\-
* 邏輯運算符:!, ||, &&
* 位元運算符:<<, >>, |, &, ~, ^
* 指標運算符:*, &
* 取值運算符:[ ]
----
## 基礎I/O
基礎input and output
常用的就幾個而已,直接上程式碼
```cpp
int x;
char c;
long long q;
cin >> x >> c >> q;
cout << x << " " << c << " " << q << "\n";
```
scanf和printf自己查,還有cin優化(都很重要)
----
## 輸入直到EOF
```cpp
int in;
while(cin >> in){
// do something
}
```
----
## 判斷句
語法如下
```cpp
if (statement) {
...
} else if (statement) {
...
} else if (statement) {
...
} else {
...
}
```
----
## for 迴圈
語法
```cpp
for (initial; if_true; do_every_time) {
...
}
```
例如
```cpp
for (int i = -5; i < 5; ++i) {
cout << (i << 2 | 1);
}
```
----
## while 迴圈
在進入迴圈之前與每圈結束時判斷條件是否成立
如果條件不成立就跳出迴圈
語法
```cpp
while (statement) {
...
}
```
例如這個輸入很常用的
```cpp
int x;
while (scanf("%d", &x) != EOF) {
cout << x;
}
```
----
## do... while...
和while 很像,只是它會先做一次才判斷條件
注意分號!!!
```cpp
int x = -10;
do {
cout << x;
} while (scanf("%d", &x) != EOF);
```
----
## 陣列
把同一個資料型別的東西叫做同一個東西,然後用取值運算符拿裡面的東西
```cpp
int dp1[];
int dp2[10];
long long dp3[] = {1, 2, 4, 2, 3, 5, 8, 1, (long long)-3*10e10, (long long)10e15};
char dp4[5] = {'r', 'p'}; // 前兩項是r和p
int dp5[10] = {0}; // 整個陣列都是0
int dp6[10] = {1}; // 只有第一項是1
cout << dp3[8] << ' ' << dp5[7];
// 聰明的各位請直接在一秒內說出輸出是什麼
```
----
## 陣列輸入
```cpp
int n;
cin >> n;
int a[n];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
```
----
## 結構 struct
語法
```cpp
struct Name {
typename var1;
...
};
```
使用時機:當你想把一坨東西包在
一起做成陣列的時候,例如:
```cpp
struct people {
string name;
int age, social_id;
};
people my_array[10];
for (int i = 0;i < 10;i++) {
cin >> my_array[i].name;
cin >> my_array[i].age;
cin >> my_array[i].name;
}
```
----
## 函數
就...函數
語法:
```cpp
typename function_name(typename parament1, ...) {
...
}
```
例如
```cpp
struct Point {
double x, y;
};
double distance(Point A, Point B) {
double dx = (A.x - B.x);
double dy = (A.y - B.y)
return sqrt(dx * dx + dy * dy);
}
```
這邊只簡單介紹語法,後面會教如何使用
----
## pointer 指標
指向你的心~~
簡單來說就是指到某一個變數在記憶體中的位置
語法
```cpp
int a = 5;
int *pointer_to_a = &a;
cout << a << ' ' << *pointer_to_a;
//---------------------
float *pointer_to_b;
pointer_to_b = (float*)malloc(sizeof(float));
*pointer_to_b = 10;
cout << b << ' ' << pointer_to_b;
```
----
## pointer array 指標陣列
幾乎沒有人在用的東西(沒
```cpp
struct your_herat {
string me, my_love;
};
int how_much_do_you_love = 1;
you *pointer_to_your_heart =
(your_heart*)malloc(sizeof(your_heart) * how_much_do_you_love);
```
----
## 傳統陣列與指標
C++的傳統陣列其實紀錄的是第一項的指標
```cpp
int a[5] = {0,1,2,3,4};
cout << (*a) << "\n";// 0
```
而指標是可以平移的
```cpp
int a[5] = {0,1,2,3,4};
cout << (*(a+2)) << "\n";// 2
```
----
## c++程式模板
```cpp
#include <bits/stdc++.h>
using namespace std;
// global variables
// functions
int main() {
// I/O and execution
}
```
---
# python
## 製作時間:8hr$\tt+$
----
## ——————目錄—————
- 變數
- 運算符號
- if...elif...else...
- 迴圈(for, while)
- 迴圈的跳出
- 陣列
- 字串處理
- 輸入
- 輸出
----
## ——————目錄—————
- 模組與import的用法
- math 模組
- 大數運算(decimal 模組)
- 神奇的東西($\small\tt eval()$, $\small\tt exec()$)
- 自學
----
## python的使用時機
- 複雜的字串處理
- 大數運算
- 特殊語法(如$\tt\small eval()$)
----
## 變數
變數不須宣告就能直接用,沒有型態限制
```python
a = 1 #整數 int
b = 0.1 #浮點數 float
c = True #布林 bool
d = "abc" #字串 str
e = [1,0.1,'3'] # 陣列 list
```
輸出型別
```python
a = '1'
print(type(a)) # <class 'str'>
a = int(a) # 直接從str轉int,其他型別也有類似的函式
print(type(a)) # <class 'int'>
```
----
## 運算符號(其他的都和C++一樣)
- and
相當於C++的&&
- or
相當於C++的||
- **
**b表示計算$a^b$(整數或浮點數都可以)
- /
浮點數除法(一定輸出浮點數)
- //
整數除法,相當於C++的 /
#### 除此之外,python沒有 ++ 和 \-\-
----
## if...elif...else...
----
## for迴圈
```python
# ↓變數名稱 ↓(初始值,上限值,公差)
for i in range(0,5,1):
print(i,end="") # 01234
print() # 換行
# 省略公差
for i in range(0,5):
print(i,end="") # 01234
print()
# 更簡單寫法,初始值預設為0
for i in range(5):
print(i,end="") # 01234
print()
for i in range(0,5,2):
print(i,end="") # 024
print()
for i in range(0,-5,-1):
print(i,end=" ") # 0 -1 -2 -3 -4
print()
c = [1,1,2,3,5,8] # 陣列
for i in c:
print(i,end=" ") # 1 1 2 3 5 8
print()
s = "abc_ab"
for i in s:
print(i,end=" ") # a b c _ a b
```
----
## while迴圈
在進入迴圈之前與每圈結束時判斷條件是否成立
如果條件不成立就跳出迴圈
直接上code
```python
i = 0
while i!=5:
i += 1
print(i,end="") #12345
```
無限迴圈
```python
while True:
# do something
```
----
## continue
跳過本次迴圈,用法同C++,while迴圈也可用
```python
for i in range(0,10):
if i%2==0:
continue
print(i,end="") #13579
```
## break
跳過本次迴圈,用法同C++,while迴圈也可用
```python
for i in range(0,10):
if i==5:
break
print(i,end="") #01234
```
----
## do...while...
python沒有do...while...的語法
不過一樣可以做到相同的功能
```
# 模擬do… while…
x = 0
while True:
print(x) # 0
if x==0:
break
```
```
x = 0
while x!=0:
print(x) # 不輸出
```
----
## 陣列
python的陣列可以儲存不同的資料型態
```python
empty_list = [] # 空陣列
list_a = [1, 2, 3, 4, 5]
""" 取得長度 """
print(len(list_a))
""" 取得元素 """
print(list_a[0]) # 1
# 最後1項
print(list_a[-1]) # 5
# 倒數第2項
print(list_a[-2]) # 4
# slice功能,用法類似for迴圈
print(list_a[0:5:2]) # [1, 3, 5]
print(list_a[0:2]) # [1, 2]
print(list_a[2:]) # [3, 4, 5]
print(s[:-2]) # [1, 2, 3]
""" 加入元素 """
# 加到最後
list_a.append(6)
print(list_a) # [1, 2, 3, 4, 5, 6]
# 組合陣列
list_a.extend(["A","B"]) # [1, 2, 3, 4, 5, 6, 'A', 'B']
# 刪除元素
del list_a[-1]
print(list_a) # [1, 2, 3, 4, 5, 6, 'A']
```
----
## 陣列可能出現的bug
#### 整體的複製與指標的複製
```python=
a = [1,2]
b = a
print(a,b) # [1, 2] [1, 2]
a[0] = 0
print(a,b) # [0, 2] [0, 2]
```
## WTF??
----
我們再加一行
```python=6
print(id(a),id(b)) #取得指標
```
輸出
```
2676735079168 2676735079168
```
### 有點神奇
----
## 指標一樣內容就一樣
如果變數是書的話,那麼指標就是貼在書上的標籤
因為當初的code只複製了陣列的指標
所以出現了這個問題
<br>
正確程式碼
```python
a = [1,2]
b = a[:] # 或是a.copy()
print(a,b) # [1, 2] [1, 2]
a[0] = 0
print(a,b) # [0, 2] [1, 2]
```
----
## 其他沒介紹但很重要的資料結構
#### 請自行搜尋
- set
- dict
- deque
- ~~tuple~~(我從沒用過)
----
## 字串處理
----
## $\tt len()$
取得字串長度
```
s = "abc ab"
print(len(s)) # 6
```
----
## 字串運算
加法(也有+=的語法)
```python
s1 = "123"
s2 = "abc"
s3 = s1 + s2
print(s3) # 123abc
```
乘法(也有*=的語法)
```python
s = "ab" * 10
print(s) # abababababababababab
```
----
## 生成子字串
類似陣列的語法
```python
s = "abcde"
print(s[0]) # a
# 最後1項
print(s[-1]) # e
# 倒數第2項
print(s[-2]) # d
# slice功能,用法類似for迴圈
print(s[0:5:2]) # ace
print(s[0:2]) # ab
print(s[2:]) # cde
print(s[:-2]) # abc
```
----
## $\tt chr()$
將數字轉成字元,例如ASCII字元
但是python能轉換出的字元種類更多
什麼中文字、表情符號都有
```python
for i in range(0,5):
print(chr(65+i),end="") #ABCDE
```
----
## $\tt ord()$
和$\tt chr()$相反,$\tt ord()$能把字元轉成對應的數字
```python
print(ord("A")) # 65
print(ord("好")) # 22909
```
----
## 字元陣列
因為python的字串跟C++不同
它不能當作陣列使用
例如以下的程式(第2行)是不合法的
```python
s = "12345"
s[0] = "A"
```
你會得到
##### TypeError: 'str' object does not support item assignment
的錯誤訊息
----
所以要先把字串轉成陣列
然後才能修改它
```python
s = "12345"
s = list(s)
s[0] = "A"
print(s) # ['A', '2', '3', '4', '5']
```
----
## $\tt .join()$
這個東西可以把字串陣列轉成一個字串
直接示範
```python
a = ['1', '2', '3', '45', '6']
print("".join(a)) # 123456
```
這是它真正的功能
```python
a = ['1', '2', '3', '45', '6']
print("-".join(a)) # 1-2-3-45-6
```
----
## $\tt .strip()$
功能看了就知道
```python
s = "..te..st.."
print(s.strip(".")) # te..st
print(s.lstrip(".")) # te..st..
print(s.rstrip(".")) # ..te..st
```
如果參數留空
則會去除換行符號("\n")和空格
----
## $\tt .replace()$
把子字串A替換成子字串B
第三個參數代表最多替換次數
```python
s = "aaabcde"
print(s.replace("a","x")) # xxxbcde
print(s.replace("a","x",2)) # xxabcde
```
----
## $\tt .split()$
指定一個分隔符來分割字串
並生成一個陣列
若不指定分隔符,就以連續空格作為分隔符
```python
s = "abc abc abc"
print(s.split(" ")) # ['abc', 'abc', '', 'abc']
print(s.split()) # ['abc', 'abc', 'abc']
```
如果分隔符連續出現在原字串中,就會出bug
----
## $\tt .rjust()$
由左邊填充字元直到指定的長度
```python
s = "123"
print(s.rjust(6,"0")) # 000123
print(s.rjust(2,"0")) # 123
```
$\tt\small .ljust()$的方向相反
----
## $\tt .count()$
取得該字串中共出現了幾個子字串
```python
s = "abc abcabcbc"
print(s.count("abc")) # 3
```
----
## 輸入
範例程式
```python
a = int(input()) # 讀取一行輸入(字串),並轉成整數
b,c,d = map(int,input().split()) # 輸入三個整數,以空格間隔
e = list((int,input().split())) # 輸入整數陣列(不限幾個數字)
print(e)
```
範例輸入
```
10
1 2 3
1 2 3 4 5 6 7 8 9
```
範例輸出
```python
[1, 2, 3, 4, 5, 6, 7, 8, 9]
```
----
## 輸入多行直到EOF
```python
while True:
try:
a,b,c = map(int,input().split())
except EOFError:
break
# 主程式由此開始
```
try的用法是偵測到錯誤就跳到except的部分
所以如果不想背EOFError也可以省略
```python
while True:
try:
a,b,c = map(int,input().split())
except:
break
# 主程式由此開始
```
但這樣有可能導致其他錯誤被略過
----
## 輸入優化<!-- sys -->
```python
from sys import stdin # 把這行加在程式一開始的地方
while True:
try:
a,b,c = map(int,stdin.readline().split())
except ValueError:
break
# 主程式由此開始
```
注意readline連最後的換行符號"\n"都讀得到
所以EOF時,會讀到"\n"
然後就會出現
###### ValueError: not enough values to unpack (expected 3, got 0)
的錯誤訊息
----
## stdin.readline( )
如果要讀取一個陣列,在EOF時會讀到空陣列
不會出現ValueError,需要注意
```python
from sys import stdin # 把這行加在程式一開始的地方
while True:
a = list(map(int,stdin.readline().split()))
if a == []:
break
# 主程式由此開始
```
----
## 輸出
```python
a = 1
b = 2
print(1) # 1
print(a) # 1
print(a,b) # 1 2
# 指定間隔,預設間隔為空格
print(a,b,sep="") # 12
# 指定結尾,預設結尾為換行符號
for i in range(0,5):
print(i,end="") # 01234
print()
# 內嵌變數
print(f"a = {a}, b = {b}") # a = 1, b = 2
```
關於浮點數請自行搜尋$\small\tt format( )$函數
----
## 模組與import的用法
----
import可以使用許多「模組」(module)
有很多功能就可以不用自己寫
模組可以用內建的、也可以自己寫
本章的介紹以內建的為主
----
## 如何匯入模組
直接上code,math 就是模組的名稱
```python
import math
print(math.pi) # 3.141592653589793
print(math.sqrt(2)) # 1.4142135623730951
```
你會發現你需要寫很多的 math.···
這樣有點浪費時間,所以我們可以這樣做
```python
from math import pi, sqrt
print(pi) # 3.141592653589793
print(sqrt(2)) # 1.4142135623730951
```
需要用什麼功能就直接引用
----
## math 模組
----
## 運算相關函數

----
## 角度相關函數

----
## 內建常數

----
## 大數運算(decimal 模組)
python的內建乘法是karatsuba($\small O(n^{1.585})$)
對於很大的數可能會TLE
所以我們要使用decimal模組
來得到更高的效率($\small O(n\log n)$)
----
## 物件生成
要先把數字轉成Decimal物件,
才能使用decimal模組的內建功能
可以轉成物件的有整數、浮點數(不建議)、字串
```python
from decimal import Decimal
print(Decimal(0.3))
print(Decimal(10000))
print(Decimal("0.3"))
```
輸出
```python
0.299999999999999988897769753748434595763683319091796875
10000
0.3
```
----
## 設定
decimal模組有一些可以調整的設定
可以直接print出來看,接下來會教如何調整
```
from decimal import getcontext
print(getcontext())
```
輸出(換行以方便閱讀,原本沒有)
```python
Context(prec=28, rounding=ROUND_HALF_EVEN,
Emin=-999999, Emax=999999, capitals=1,
clamp=0, flags=[], traps=
[InvalidOperation, DivisionByZero, Overflow])
```
----
## 精準度
decimal模組可以設定數字的精準度
或者應該說是設定要保留幾位有效位數
```python
from decimal import getcontext, Decimal
getcontext().prec = 5
print(Decimal(1) / Decimal(3)) # 0.33333
getcontext().prec = 10
print(Decimal(1) / Decimal(3)) # 0.3333333333
print(Decimal(1000) / Decimal(3)) # 333.3333333
```
----
## 指數限制
限制一個數的指數(10的幾次方)的上限值
上限值可以修改,而下限值不能
```python
from decimal import getcontext, Decimal
getcontext().Emax = 5 # 設定上限值
print(Decimal(100000) * 10)
```
錯誤訊息
```python
decimal.Overflow: [<class 'decimal.Overflow'>]
```
----
## 浮點數捨入規則
```python
from decimal import getcontext, Decimal
getcontext().prec = 5
getcontext().rounding = "ROUND_FLOOR" #修改這一項
print(Decimal(1) / 3) # 0.33333
print(Decimal(-1) / 3) # -0.33334
```
參考表格(抄自官方document)

----
## 數字輸出
當Emax和prec都設定夠大時
整數一定會一位一位輸出
但浮點數有時會出現科學記號,然後你就會吃WA
範例程式碼在下一頁
----
程式碼
```python
from decimal import Decimal, getcontext
getcontext().Emax = 100000000
getcontext().prec = 100000000
print(Decimal(100000000000) * Decimal(10000000000))
getcontext().prec = 50
print(Decimal(1) / 3)
print(Decimal(1) / Decimal(2147483647))
```
輸出
```python
1000000000000000000000
0.33333333333333333333333333333333333333333333333333
4.6566128752457969241057508271679984532147638747537E-10
```
----
## [ZJ i212 三則運算](https://zerojudge.tw/ShowProblem?problemid=i212)
Code
```python
from sys import stdin
from decimal import Decimal, getcontext
getcontext().Emax = 100000000
getcontext().prec = 100000000
a, x, b = stdin.readline().split()
a = Decimal(a)
b = Decimal(b)
if x == '+':
print(a+b)
elif x == '-':
print(a-b)
else:
print(a*b)
```
----
## 神奇的東西
----
$\tt eval()$函數
```python
a = "1+2*3"
print(eval(a)) # 7
```
[ZJ a21 五則運算](https://zerojudge.tw/ShowProblem?problemid=i212)
```python
try:
while(True):
print(int(eval(input().replace("/","//"))))
except:
pass
```
----
$\tt exec()$函數
直接把字串當作程式碼執行
```python
a = "b = 16"
exec(a)
print(b) # 16
```
----
## 自學
- $\small\tt sort()$函數
- 函數用法 (def)
- fractions模組
---
# 結束
有任何語法問題、不知道要怎麼寫的
歡迎詢問
{"metaMigratedAt":"2023-06-17T08:14:47.044Z","metaMigratedFrom":"YAML","title":"C++ & python 語法","breaks":true,"contributors":"[{\"id\":\"cb3ba034-0769-48f4-b7b5-11c425ef2672\",\"add\":12156,\"del\":1305},{\"id\":\"373dba06-a017-4e8f-ac18-3380b124d683\",\"add\":3868,\"del\":386}]"}