<!-- 簡報宣告 --> # C++ & python 語法 #### 第2週社課 ## 講者:鄭勝宇、郭久銘 --- # C++ ---- ## ——————目錄————— - 資料型別、變數、操作符號 - 基礎I/O - 判斷句 - for、while迴圈及其控制 (還有do...while...) - 陣列 - 結構 struct - 函數、inline函數 - pointer、pointer array ---- <!-- https://hackmd.io/@niter/HJjhdnkgj#/1/1 --> <!-- --> ## 資料型別 這裡介紹c++ 的基本型別們 先介紹整數家族 * short&nbsp;$\small(-32768,32767)$ * int &nbsp; &nbsp;$\small(-2147483648, 2147483647)$ 常用,8bytes * long$\small(-2147483648, 2147483647)$ 用不到,佔的bytes數跟作業系統有關 ---- ## 資料型別 這裡介紹c++ 的基本型別們 先介紹整數家族 * long long &nbsp;$\small(-2^{63} , 2^{63}-1)\approx(-9\times10^{18}, 9\times10^{18})$ 通常題目數字給在$10^9$以上的時候就得用 * __int128 處理極大數字的時候才用到,如果會py其實可以不用cpp,輸出輸入還得自己寫,很多編譯器過不了,含codeblocks,ZJ可 這些整數型別前面加一個unsigned就可以翻倍儲存 ---- ![](https://i.imgur.com/CjVNfkw.png) ---- ![](https://i.imgur.com/GqXu93v.png) ---- ## 資料型別 接著是浮點數家族,會有浮點數誤差!!! 實作方式是科學記號 * float &nbsp;$\small\approx(-1.7\times10^{38}, 1.7\times10^{38})$ 幾乎用不到 * double &nbsp;$\small\approx(-3.4\times10^{308}, 3.4\times10^{308})$ 記得!!會有浮點數誤差!!! $1+2=3.000000004$ ---- ![](https://i.imgur.com/en2pRsH.png) ---- ## 資料型別 再來是char和string * char $(-128,127)$ 1個byte 用單引號,除了要一個字一個字讀的題目,不然根本用不到 * string 用雙引號,其結構大小等價於$sizeof(char)\times s.size()$ ---- ## @ 題外話 ASCII碼 歪國人把英文字母還有常用符號塞進了一個char個大小裡面,紅色框框代表記一下 ![](https://i.imgur.com/ulaLIBl.png) ![](https://i.imgur.com/12OYn8a.png) 接下來就是變數 ---- ## 變數 宣告語法 ``` 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 模組 ---- ## 運算相關函數 ![](https://i.imgur.com/0g73EKX.png) ---- ## 角度相關函數 ![](https://i.imgur.com/0AIjVbn.png) ---- ## 內建常數 ![](https://i.imgur.com/iPkdIpo.png) ---- ## 大數運算(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) ![](https://i.imgur.com/9vG97hg.png) ---- ## 數字輸出 當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}]"}
    514 views