# C++ Function --- #### main is a function * 妳可以認為,當你在執行程式時,作業系統直接call main function來執行程式。 * main 就是你最開始接觸到的function ``` cpp int main(int argc, char** argv) { // context } ``` --- #### What is function * 一連串的執行指令 * 對使用者來說,我只需要知道我要給他甚麼輸入並且知道他會做甚麼事情。 * 不需要知道所有的細節 * ![image](https://hackmd.io/_uploads/HJDVFKU-0.png) --- #### Use Math as an example * 如何取得直角三角形的斜邊 * ![image](https://hackmd.io/_uploads/r1slcKI-A.png) ``` cpp double calculateHypotenuse(double a, double b) { return sqrt(a*a+b*b); } ``` --- #### Why do we need functions * 通通寫在main function內好嗎? --- #### Why do we need functions * 通通寫在main function內好嗎? * 不好? 為什麼? 1. Code reuseable 2. Readability 3. Cooperation --- #### Example * 你能快速地知道這段code在幹嘛嗎 ![image](https://hackmd.io/_uploads/S1DO6YU-0.png) --- #### Example * 那這樣呢 * 從main開始閱讀 ![image](https://hackmd.io/_uploads/SkodCKUbA.png) --- #### Example * 他們差在哪 ![image](https://hackmd.io/_uploads/BklI0KL-A.png) --- #### Example * 我們獲得了甚麼 1. Code reuseable * `calculate_gcd` is reused. 2. Readability * We know `a==0` print the gcd and others print the lcm. 3. Cooperation * Engineer A maintains gcd, and Engineer B maintains lcm. --- #### Expression * return_type: 此函數的回傳型態,當你執行完會得到的東西 * function_name: 函數的名稱 * parameters: 此函數的輸入 * context: 如何處理你的input並得到回傳值 * return: 當回傳型態不為void時 則必須寫return ``` cpp return_type function_name(parameters) { // execution context return ...; // 假如return-type不是void時 必須return; } ``` --- #### Example - calculate_gcd * return_type: 回傳一個integer * function_name: 名稱很明確,我要計算最大公因數 * parameters: 兩個型態為integer的參數,在function內代號為x,y * context: 使用while loop來計算gcd * return: 將得到的gcd返回 ``` cpp int calculate_gcd(int x, int y) { int temp; while(y != 0) { temp=x % y; x=y; y=temp; } return x; } ``` --- #### What does Machine do when calling function ![image](https://hackmd.io/_uploads/Hy_yV9Ib0.png) --- #### Use stack when register is lack ![image](https://hackmd.io/_uploads/r19wHcUbC.png) --- #### Local Variable * 所有定義在function內的變數都是Local Variable * 請問average的a,b,avg跟main中的a,b,avg有甚麼關係嗎? * average的a,b,avg屬於average這個function的local variable * 反之main中的a,b,avg也是如此 ![image](https://hackmd.io/_uploads/SJr5v5IW0.png) --- #### Local Variable * 會在進入function的時候分配記憶體給他們,並在離開function時釋放記憶體 * 進入average後,系統會分配綠色框框中的三個位置給average的a,b,avg使用,並移動stack pointer至下方位置。 * average執行完以後,綠色框框中的位置被釋放,stack pointer被往上移動 ![image](https://hackmd.io/_uploads/r1Afu58b0.png) --- #### Call by Value & Call by Reference * In C language, always use **Call by Value** * 傳送是用複製的方式傳值,修改不會改到原本的變數 * C++ add **Call by Reference** feature. * 傳送是用別名的方式傳送,修改會改到原本的變數 * Keyword: & in parameters * example: `void fun(int& a);` * 請問會印出甚麼東西來? ![image](https://hackmd.io/_uploads/ryRLF9UZR.png) --- #### Two way to define function 1. declare and define together ``` cpp int average(int a,int b) { return (a+b)/2; } int main() { int a = average(1,2); } ``` 2. declare first and define later ``` cpp int average(int a, int b); int main() { int a = average(1,2); } int average(int a,int b) { return (a+b)/2; } ``` --- #### Pass the array in the parameters * 1D array: 你可以選擇要不要指定array的長度,如果不指定長度的話會有風險。 ``` cpp void fun(int a[], int b[3]); ``` * multi-dimention array: 只允許第一個中括號內留空格 ``` cpp void fun(int a[1][2]); // ok void fun(int a[][2]); // ok void fun(int a[1][]); // compile error void fun(int a[][]); // compile error ``` --- #### Pass the array in the parameters * Special case * Array is **copied by value**, but modify will affect the original array. * 理由是因為我們複製的東西是**指標**而不是整個array,細節會在之後的章節講到。 ![image](https://hackmd.io/_uploads/HJgcoqLWC.png) --- #### Recursion * The function call its self recursively. * Loop <==> Recursion * Loop 跟 Recursion 理論上是可以互換的 * Recursion的缺點 * 遞迴太多層的話stack會不夠用而導致程式終止 * call function本身會有一定的性能損失(MIPS的jmp指令) --- #### Recursion * 既然這樣為何我們還要用遞迴呢 * 適用於Dynamic Programming以及Divide and conquer的思考邏輯 * 都是將問題拆解成小問題以後,先解出小問題再來煩惱大問題 ``` cpp int factorial(n) { if (n==1) { return n; } else { return factorial(n-1) * n; } } int main() { std::cout<<"5! = "<<factorial(5)<<"\n"; // 5! = 120 } ``` --- #### Recursion * 那要怎麼寫一個recursion呢 1. 將問題分解好 * 我們要計算n! 只需要將n * (n-1)! 即可 2. 一個正確的終止條件,防止無限loop下去 * 當n足夠小而我們已經確定已知解答的時候,就可以設他為中止條件 * n=1的時候 1!=1是大家都知道的 ``` cpp int factorial(n) { if (n==1) { return n; } else { return factorial(n-1) * n; } } ``` --- #### Practice * Sum of two prime * input: a integer * output: print all the solution * Example: ![image](https://hackmd.io/_uploads/HJepgs8-R.png) * Compiler Explorer: [Link](https://godbolt.org/z/8KKWKhrdP) * ANS: [Link](https://godbolt.org/z/ec4ae51r1) * 請使用一個function去判斷是否為質數 --- #### Practice 2 - Recursion * 請使用recursion寫出輾轉相除法得到兩個數的最大公因數 * 分解問題: a=18, b=14 輾轉一次後變成 a=14, b=4(18%14),(18,14) 跟 (14,4)的解答是一樣的 * 終止條件: 當b變成0的時候 --- #### Practice 2 - Recursion * 請使用recursion寫出輾轉相除法得到兩個數的最大公因數 * 請完成gcd這個function ![image](https://hackmd.io/_uploads/B1M4uKBxR.png) * 如果成功的話會印出 ![image](https://hackmd.io/_uploads/SJTH_KrlR.png) * 如果失敗的話會印出 ![image](https://hackmd.io/_uploads/BJRPuFSeC.png) * [連結](https://godbolt.org/z/qj1PGoTe9) * [ANS](https://godbolt.org/z/c8cb6GMcP)
{"contributors":"[{\"id\":\"09379b25-db04-47a4-8912-78e722b7a548\",\"add\":5856,\"del\":382}]","slideOptions":"{\"theme\":\"white\"}","title":"C++ Function"}
    217 views