###### tags: `創造力資優課程` ###### tags: `computer` # C 語言課程 # 龍興國中 <font color="#3A33FF">創造力資優班 </font> ==C 語言課程== ![](https://i.imgur.com/ljOlYzv.png) ## 線上<font color="#3A33FF">程式語言</font>編譯平台: [onlinegdb](https://www.onlinegdb.com/) ## 1. C語言初體驗 : - 您可以編輯==程式碼==並在==onlinegdb==中執行並查看結果: :::success ``` #include <stdio.h> int main() { printf("Hello World!"); return 0; } ``` ::: ## 2. 什麼是C語言? - C 是丹尼斯·里奇於 1972 年在貝爾實驗室創建的通用程式 - 儘管它很古老,這是一種非常流行的程式語言。 - C 與 UNIX 密切相關,因為它是為編寫 UNIX 作業系統而開發的。 ## 3. 為什麼要學習 C? - 它是世界上最流行的程式語言之一[2023程式語言排名](https://www.johntool.com/programming-language-rank/) - 如果你懂 C,那麼學習其他流行的程式如 Java、Python、C++、C# 等也沒有問題,因為語法相似 - 與其他程式Java和Python)相比,C 語言執行速度非常快 - C 語言是通用的;它可以在不同硬體上的應用程式運作 - 學習 C 語言對於 ==APCS「大學程式設計先修檢測」== **觀念題**概念比較清楚 ## 4.C 和 C++ 之間的區別 - C++是 C 的擴展開發的版本,兩種語言的語法幾乎相同 - C 和 C++ 的主要區別在於 C++ 支持class和object,而 C 不支持 ## 5.程式範例說明 :::success ``` 1.#include <stdio.h> 2. 3.int main() { 4. printf("Hello World!"); 5. return 0; 6.} ``` ::: - 第 1 行: ==#include <stdio.h>== 是一個**函數庫**,可讓我們呼叫輸入和輸出的各種函數。 - 例如 ==printf()==(在第 4 行)。在 C 語言 **函數庫**中呼叫 ==printf()== 函數功能。 :::success 如果您不了解其 #include <stdio.h>工作原理,請不要擔心。只要把它想像成(幾乎)總是出現在你的 c 程式中的東西。 ::: - 第 2 行: ==空行==。C語言會忽略==空行==。但是我們使用==空行==會更容易讀懂程式內容。 - 第 3 行:另一個總是出現在 C 語言程式中的東西是 ==int main(){ }== 這稱為 ==函數==。大括號 =={ }== 內的任何程式都會被執行 - 第 4 行: ==printf()== 是將資料==輸出==到螢幕的函數。在我們的例子中,它將輸出==Hello World==。 :::warning 請注意:每句 C 語言程式碼都是以分號 ==;== 結尾 ::: - 第 5 行: ==return 0==結束 ==main( )== 函數。 - 第 6 行:不要忘記添加==右大括號== ==}== 以實際結束 main 函數。 ## 6.輸出 - printf()函數用於輸出==數值==或==文字==: ``` #include <stdio.h> int main() { printf("Hello World!"); printf("I am learning C."); return 0; } ``` :::danger 結果: Hello World!I am learning C. ::: - 換行符號 ==\n== ,它強制游標將其位置更改到螢幕中==下一行==的開頭。產生一個新的一行。 ``` #include <stdio.h> int main() { printf("Hello World!\n"); printf("I am learning C."); return 0; } ``` :::danger 結果: ``` Hello World! I am learning C. ``` ::: ## 7.註解 - 註解是用來解釋程式碼,並使其易於了解。它還可用於在測試替代程式碼時暫時停止執行。 - 註釋可以是單行或多行的 - 單行註解:以兩個 ==//== 開頭,編譯器不會執行這一行程式碼 ``` // 向世界問好 printf("Hello World!"); ``` ``` printf("Hello World!"); // 向世界問好 ``` - 多行註釋以開頭 ==/*== 和結尾 ==*/==。 - ==/*== 和之間的任何程式碼或文字 ==*/== 都將被編譯器忽略而不執行: ``` /* 下面的程式碼將會輸「Hello World!」字樣 到螢幕,真是太神奇了 */ printf("Hello World!"); ``` ## 8.變數 - **變數**可儲存被指定的**數據值**。 在 C語言中,不同類型的變數,有規定的==宣告==方式 例如: ==int== 儲存整數,例如 123 或 -123 ; ==float== 儲存浮點數,帶小數點的數字,例如 19.99 或 -19.99 ; ==char== 儲存單個字元,例如'a' or 'B'。字元值用單引號括起來 - 建立變數 a 以int方式並指定值為30 ``` int a = 30; ``` - 也可建立一個**變數**而不直接指定值,之後再指定數值: ``` int a; a = 30; ``` - 輸出 int **變數**的值,必須在函數內部使用格式說明符號 ==%d== 或 ==%i== 用雙引號括起來printf(): ``` int a = 30; printf("%d", a); ``` - 輸出 char **變數**的值,必須在函數內部使用格式說明符號 ==%c== 用雙引號括起來printf(): - 輸出 float **變數**的值,必須在函數內部使用格式說明符號 ==%f== 用雙引號括起來printf(): ``` // 建立變數 int myNum = 5; // 整數 float myFloatNum = 5.99; // 浮點數 char myLetter = 'D'; // 字元 // 輸出變數 printf("%d\n", myNum); printf("%f\n", myFloatNum); printf("%c\n", myLetter); ``` - **加總變數**:要將兩個變數加總,可以使用+ 運算符號 ``` int x = 5; int y = 6; int sum = x + y; printf("%d", sum); ``` - **宣告多個變數**:建立多個變數時,請使用==逗號==分隔 ``` int x = 5, y = 6, z = 50; printf("%d", x + y + z);//112.11.10-903 ``` ## 9.變數的命名規則 - 所有變數都必須指定唯一的識別碼。 - 識別碼可以是短代碼(如 x 和 y)或具描述性的代碼(age、sum、totalVolume)。 ==建議使用==描述性代碼讓程式碼易於理解和容易維護 例如: ``` int minutesPerHour = 60; // 很棒 int m = 60; // OK, 但不是很容易理解變數的內容 ``` - 命名==變數==的一般規則是: 名稱可以包含==字母、數字和下劃線_== 名稱必須以==字母或下劃線 (_) 開頭== 名稱區分==大小寫==(myVar 和 myvar 是不同的變數, 名稱不能包含==空格==或==特殊字符==,如 !、#、% 等。 ==保留字==(如int)不能用作名稱//111.9.28 ## 10.資料型態 - 宣告變數時要指定資料型態,並且在printf()中使用相關格式說明符號顯示: ``` // 宣告變數 int myNum = 5; // 整數 float myFloatNum = 5.99; // 浮點數 char myLetter = 'D'; // 字元 // 顯示列印變數 printf("%d\n", myNum); printf("%f\n", myFloatNum); printf("%c\n", myLetter); ``` ## 11.常數 - 將變數宣告為==常數==,意味只能讀取不可更改 ``` const int myNum = 15; // myNum 永遠是15 myNum = 10; // 錯誤: myNum 不可以再指定其他數值 ``` - 當變數的值永遠固定不能變更時,即可將該==變數==宣告為==常數== ``` const int minutesPerHour = 60;//一小時為60分鐘 const float PI = 3.14; //圓周率=3.14 ``` - 當宣告一個常數時,必須指定數值: :::success ``` const int minutesPerHour = 60; //正確 ``` ::: :::warning ``` const int minutesPerHour; minutesPerHour = 60; // 錯誤 ``` ::: ## 12.運算子 - 例子:我們使用 + 運算子將兩個==數值==相加: ``` int myNum = 100 + 50; ``` - 就像下面的例子一樣,一個==變數==可以和一個==數值==相加,或者一個==變數==相加另一個==變數== ``` int sum1 = 100 + 50; // 答案: 150 (100 + 50) int sum2 = sum1 + 250; // 答案: 400 (150 + 250) int sum3 = sum2 + sum2; // 答案: 800 (400 + 400) ``` ### 算數運算子 | 運算子 | 運 算 | Example | | -------- | -------| -------- | | + | 加法 | x + y | | - | 減法 | x - y | | * | 乘法 | x * y | | / | 除法 | x / y | | % | 餘數 | x % y | | ++| 增加1 | ++x | | - -| 減1| - -x | ### 賦值運算子 - 使用賦值運算子 = 分配 10 給名為x的變數: ``` int x = 10; ``` - 加法賦值運算子 += 將一個==數值==添加到==變數==中: ``` int x = 10; x += 5; //答案是 15 ``` | 運算子 | 例 子 | 等同 | | -------- | -------| -------- | | = | x =5 | x =5 | | += | x +=3 | x=x+3 | | -= | x -=3 | x=x-3 | | *= | x *=3 | x=x*3 | | /= | x /=3 | x=x/3 | | %=| x %=3 | x=x%3 | ### 比較運算子 比較運算子用於比較兩個數值。 注意:比較的結果可能回傳值為 true (1) 或 false ( 0)。 在以下示例中,我們使用==大於==運算子 > 來確定 5 是否大於 3: ``` int x = 5; int y = 3; printf("%d", x > y); // 回傳值為 1 (true) 因為 5 確實會大於 3 ``` | 運算子 | 意義 | 例子 | | -------- | -------- | -------- | | == |等於 |x == y | | != |不等於 |x != y | | > |大於 | x > y| | < |小於 |x < y| | >= |大於或等於 |x >= y| | <= |小於或等於 |x <= y| ### 邏輯運算子 邏輯運算子用於確定==變量==或==數值==之間的邏輯: | 運算子 | 名稱  | 意義  |舉例      | | -------- | -------- | -------- |-------- | |&& |且| 兩者都成立 |x < 5 && x < 10| ||| |或| 兩者其中之一成立 |x < 5 || x < 4 | |! |不是|回傳相反值|!(x < 5 && x < 10)|! |不是|回傳相反值|!(x < 5 && x < 10)| ### Sizeof 運算符 - sizeof運算子找到數據類型或變數的暫存大小 ``` int myInt; float myFloat; double myDouble; char myChar; printf("%lu\n", sizeof(myInt)); printf("%lu\n", sizeof(myFloat)); printf("%lu\n", sizeof(myDouble)); printf("%lu\n", sizeof(myChar)); ``` ## 13.if... else #### 從[比較運算子](https://hackmd.io/RudSoO7PRdOs9-rarcKyhg?both#%E6%AF%94%E8%BC%83%E9%81%8B%E7%AE%97%E5%AD%90)章節中可以知道 C 語言中常用的邏輯條件: - 小於: a < b - 小於或等於: a <= b - 大於: a > b - 大於或等於: a >= b - 等於 a == b - 不等於: a != b #### C語言有以下條件語句: - 使用 if 如果指定條件為==真==,執行指定的==區塊程式==。 - 使用 else 如果指定條件為==假==,執行指定的==區塊程式==。 - 使用 else if 如果第一個條件為假,測試新的==條件==。 - 使用 switch 指定執行多個不同的==區塊程式==。 :::success ### if 的語法 ``` if (指定條件) { // 如果指定條件為真,執行指定此區塊程式。 } ``` ![](https://i.imgur.com/OT0NgD7.png) #### if 的例子 - 在下面的例子中,我們測試 20 是否大於 18。如果條件為true,則印出"20 is greater than 18" - 注意 if 是小寫字母。大寫字母(If 或 IF)會產生錯誤。 ``` if (20 > 18) { printf("20 is greater than 18"); } ``` - 使用變數測試,結果成功 ``` int x = 20; int y = 18; if (x > y) { printf("x is greater than y"); } ``` ::: ### 練習題: ==1.如何判斷一個給定的數字是偶數還是奇數?== - 這是一個經典的C語言程式。 我們將在C語言中學習使用條件語句 if ,將一個整數除以2,如果整除(餘數為零),則該數是偶數,如果不能整除則該數是奇數。 ==2.輸入一個整數後即輸出該數的絶對值== - 不論該整數是正數或負數圴輸出正數 ==3.判斷三條線段是否可圍成一個三角形== - 3,4,5 可 - 6,6,12 不可 - 3,4,8 不可 :::warning ### if ....else 語法 ``` if (指定條件) { // 如果指定條件為真,執行指定此區塊程式。 } else { // 如果指定條件為假,執行指定此區塊程式。 } ``` ![](https://i.imgur.com/QrDtz6P.png) #### 例子 ``` int time = 13; if (time < 12) { printf("早安."); } else { printf("午安."); } // 輸出 "午安." ``` - 在上面的例子中,時間 13 大於 12,所以條件是false。因此,我們執行else區塊程式顯示出“午安”。如果時間小於 12,程式將顯示“早安”。 ::: ### 練習題: ==如何判斷一個給定的數字是偶數還是奇數?== - 這是一個經典的C語言程式。 我們將在C語言中學習使用條件語句if-else。將一個整數除以2,如果整除則是偶數,否則是奇數。 ==在三個數字中,找出最大的一個數字== - i : 3 - J : 4 - K : 5 :::danger ### if...else if...else 的語法 ![](https://i.imgur.com/zTzwZOU.png) ``` if (指定條件1) { // 如果指定條件1為真,執行指定此區塊程式。 } else if (指定條件2) { // 如果指定條件1為假,指定條件2為真,執行指定此區塊程式。 } else { //如果指定條件1為假,指定條件2為假,執行指定此區塊程式。 } ``` - 例子 ``` #include <stdio.h> int main() { int time = 22; if (time < 12) { printf("Good morning."); } else if (time < 20) { printf("Good day."); } else { printf("Good evening."); } // 輸出 "Good evening." } ``` - 在上面的例子中,時間 (22) 大於 12,所以第一個條件是false。語句中的下一個條件 else if也是false,因此我們繼續處理else 條件,因為條件1和條件2 都是false,所以螢幕顯示“Good evening.”。但是,如果時間是 ==14==,程式執行結果會是螢幕顯示“==Good day==”。 ::: ### 練習題 ==1.判斷 3 條線段是否可圍成三角形==: - 若可以圍成三角形則為下列何者1.正三角形,2.等腰三角形,3、直角三角形,4、普通三角形 :::info ### if....else 簡寫法與三元運算子 - 語法 ``` 變數 = (條件) ? True的結果 : False的結果; ``` - 例子 ``` int time = 20; if (time < 18) { printf("Good day."); } else { printf("Good evening."); } ``` - 本例的簡略的表達方式 ``` int time = 20; (time < 18) ? printf("Good day.") : printf("Good evening."); ``` ::: ## 14.switch :::success ![下午1.49 2024-11-20的影像](https://hackmd.io/_uploads/SyA5Ogjzkg.jpg) - 語法 ``` switch(變數名稱) { case 符合數字: 陳述句一; break; case 符合數字: 陳述句二; break; default: 陳述三; break; } ``` - 首先看看 switch 的括號,當中置放要取出==數值==的變數或運算式,取得數值之後,會與 case 設定的數字或字元比對,如果符合就執行以下的陳述句,直到遇到 break 後離開 switch 區塊,若沒有符合的數值或字元,會執行 default 後的陳述句,default 不需要時可以省略。 - 例子 ``` int day = 4; switch (day) { case 1: printf("Monday"); break; case 2: printf("Tuesday"); break; case 3: printf("Wednesday"); break; case 4: printf("Thursday"); break; case 5: printf("Friday"); break; case 6: printf("Saturday"); break; case 7: printf("Sunday"); break; } // Outputs "Thursday" (day 4) ``` - 例子2 ``` int rank = 4; switch (rank) { case 1: case 2: case 3: printf("電腦作業得95分"); break; case 4: case 5: printf("電腦作業得90分"); break; case 6: printf("電腦作業得80分"); break; } // Output "電腦作業得90分" (rank 4) ``` - 關鍵字 ==break== ,當程式執行到達關鍵字 ==break== 時,它會跳出 switch 區塊。停止在switch區塊內執行更多程式並忽略其他 ==case== 的測試。 ::: ### 練習題 #### ==1.兩光法師占卜術== - 兩光法師時常替人占卜,由於他算得又快有便宜,因此生意源源不絕,時常大排長龍,他想算 得更快一點,因此找了你這位電腦高手幫他用電腦來加快算命的速度。   他的占卜規則很簡單,規則是這樣的,輸入一個日期,然後依照下面的公式: M=月 D=日 S=(M*2+D)%3 得到 S 的值,再依照 S 的值從 0 到 2 分別給與 普通、吉、大吉 等三種不同的運勢 :::danger break 可以節省大量執行時間,因為它“忽略”了 switch 區塊中其餘程式的執行。 ::: :::warning - 關鍵字 ==default==,如果没有任何 ==case== 相符時,則執行一些預設程式。 - 例子 ``` int day = 4; switch (day) { case 6: printf("Today is Saturday"); break; case 7: printf("Today is Sunday"); break; default: printf("Looking forward to the Weekend"); } // Outputs "Looking forward to the Weekend" ``` ::: :::danger default 關鍵字必須是 switch 區塊中的最後一段陳述,並且不一定需要 break。 ::: ## 15.While 迴圈 :::info - 語法 ``` while (條件) { // 符合條件下會執行區塊內程式 } ``` - 例子 ``` int i = 0; while (i < 5) { printf("%d\n", i); i++; } ``` - 關於C語言中的while迴圈while1是什麼意思: - while(1)代表了迴圈永遠執行下去.除非遇到break;才跳出迴圈.原因是while的迴圈裡面是一個布林值,而1代表了true,所以是一個無限迴圈. ``` ``` ![](https://i.imgur.com/X78jQA7.png) ::: ### do....while 迴圈 ![](https://i.imgur.com/24iFA5k.png) :::info - 語法 ``` do { // 先執行區塊內程式一次,若條件符合則持續執行下去 } while (條件); ``` - 例子 ``` int i = 0; do { printf("%d\n", i); i++; } while (i < 5); ``` ::: ## 16. for 迴圈 :::success - 當明確知道重複執行一段程式的==次數==時,則使用 for 迴圈而不是 while 迴圈: - 語法 ``` for (陳述句1 ; 陳述句2 ; 陳述句 3) { // 執行區塊內的程式 } ``` #### 例子 1 ``` int i; for (i = 0; i < 5; i++) { printf("%d\n", i); } ``` ![](https://i.imgur.com/Uwx26gs.png) #### 例子 1 解說: - 陳述句 1 : 在迴圈開始之前建立一個變數,名為 ==i== ,起始值為 0 ( int i = 0)。 - 陳述句 2 : 定義了迴圈運行的條件(i 必須小於 5)。如果條件為==真==,迴圈將重複執行,如果條件為假,迴圈即結束。 - 陳述句 3 : 每次執行迴圈一次,==i== 的值都會增加 1 ( i++ )。 #### 例子 2 :本例僅會列印 0 到 10 之間的偶數 ``` for (i = 0; i <= 10; i = i + 2) { printf("%d\n", i); } ``` ![](https://i.imgur.com/SZmDphv.png) ::: ### 練習題 #### ==1.判斷一個整數,是質數還是合數,並找出所有的因數== - 質數只有1和該數本身共 2 個因數。 #### ==2.計算 1 加到 10 的總和== - 限用 for 迴圈完成。 #### ==3. 身份證字號真偽判斷== 我國的身分證字號有底下這樣的規則,因此對於任意輸入的身分證字號可以有一些基本的判斷原則,請您來判斷一個身分證字號是否是正常的號碼(不代表確有此號、此人)。 (1) 英文代號以下表轉換成數字 A=10 台北市 J=18 新竹縣 S=26 高雄縣 B=11 台中市 K=19 苗栗縣 T=27 屏東縣 C=12 基隆市 L=20 台中縣 U=28 花蓮縣 D=13 台南市 M=21 南投縣 V=29 台東縣 E=14 高雄市 N=22 彰化縣 W=32 金門縣 F=15 台北縣 O=35 新竹市 X=30 澎湖縣 G=16 宜蘭縣 P=23 雲林縣 Y=31 陽明山 H=17 桃園縣 Q=24 嘉義縣 Z=33 連江縣 I=34 嘉義市 R=25 台南縣 (2) 英文轉成的數字, 個位數乘9再加上十位數的數字 (3) 各數字從右到左依次乘1、2、3、4....8 (4) 求出(2),(3) 及最後一碼的和 (5) (4)除10 若整除,則為 real,否則為 fake 例: T112663836 ``` 2 + 7*9 + 1*8 + 1*7 + 2*6 + 6*5 + 6*4 + 3*3 + 8*2 + 3*1 + 6) = 180 ``` 除以 10 整除,因此為 real #### ==4.找零機器== 請設計一個找零機器的判斷程式,判斷使用者輸入的金額( money)當中,以最少的銅板數來找零錢。該機器所提供的銅板有 50 元、10 元、5 元及 1 元。當輸入的金額數介於 1 到 1000 之間,則依序顯示該找的各個銅板數(50 元、10 元、5 元及 1 元);當金額為 0 時,則結束判斷。 ## 17.Break 和 Continue :::info ### break : 前面章節中 break 可“跳出” switch 區塊程式。 - break 還可用於==跳出 while 、for 迴圈==。 - 下面例子在 i 等於 4 時==跳出迴圈==: ``` int i; for (i = 0; i < 10; i++) { if (i == 4) { break; } printf("%d\n", i); } ``` ::: ### 練習題 #### ==1.找出兩整數的最大公因數== - 變數設為num1,num2,餘數的變數設為remainder_ #### ==2.找出兩整數的最小公倍數== - 最小公倍數 = 兩數相乘 / 公因數 - [輾轉相除法參考資料](https://i.imgur.com/f8yA8VG.png) :::warning ### continue: 如果出現特定的條件,continue 會中斷一次迴圈結果,並繼續之後的迴圈。 - 下面例子在 i 等於 4 時,==跳過== 4 的值: ``` int i; for (i = 0; i < 10; i++) { if (i == 4) { continue; } printf("%d\n", i); } ``` ::: ## 18.陣列 :::success - ==陣列== : 可以在一個變數中儲存多個數值,而不用為每個數值宣告獨立的變數。 - 要建立陣列,要先定義==數據類型==(如int)並指定陣列名稱,後方加 []。 - 要在[]中加入數值,需在()內使用==逗號==分隔: - 例子:建立四個整數的陣列,陣列名稱為myNumbers。 ``` int myNumbers[] = {25, 50, 75, 100}; ``` ### 依據陣列索引號,存取陣列元素。 - 陣列索引號從 0 開始:[0] 是第一個元素。[1] 是第二個元素,依此類推。 - 下面例子是存取myNumbers陣列中的第一個元素 [0]的值: ``` int myNumbers[] = {25, 50, 75, 100}; printf("%d", myNumbers[0]); // 輸出答案為 25 ``` ### 更改陣列的元素 - 要依據索引號更改特定元素的值。 ``` int myNumbers[] = {25, 50, 75, 100}; myNumbers[0] = 33; printf("%d", myNumbers[0]); // 輸出結果為 33 取代原本的 25 ``` ### 搜尋陣列全部的元素 - 可以使用 for 迴圈搜尋陣列全部元素 。 以下例子輸出myNumbers 陣列中的所有元素: ``` int myNumbers[] = {25, 50, 75, 100}; int i; for (i = 0; i < 4; i++) { printf("%d\n", myNumbers[i]); } ``` ### 先設定陣列規模大小的陣列建立方法 - 另一種常用建立陣列的方法,先指定陣列的大小,然後再增添元素: - 例子: ``` / 宣告 4 個整數的陣列: int myNumbers[4]; // 增添元素在陣列中 myNumbers[0] = 25; myNumbers[1] = 50; myNumbers[2] = 75; myNumbers[3] = 100; ``` ### 陣列的練習 ``` #include <stdio.h> int main() { int myNumbers[3] ; for (int j = 0; j < 4; j++){ scanf("%d",&myNumbers[j]); } myNumbers[1] = 33; for (int i = 0; i < 4 ; i++){ printf("%d\n" , myNumbers[i]); } } ``` - 使用這種建立陣列的方法,必須先確定陣列的大小,才有足夠的記憶體空間讓程式去儲存。 - 建立陣列後,不能再更改它的規模大小。 ::: ## 練習題 ### [1.費波那契數列](https://docs.google.com/document/d/1tEBOikMGC-rKNly4GOOMTIhWm9PZd7bE0kcCRBzNpNQ/edit?usp=sharing) ## 19.字串 ## 20. scanf() 使用者輸入 :::warning - 你已經學過,用 printf() 輸出數值的方法。 - 要用戶輸入數值,可以使用 scanf() - 例子 ``` // 建立一個資料類型為整數的變數,以便儲存使用者所輸入的數值 int myNum; // 詢問使用者要輸入一個數字 printf("Type a number: \n"); // 獲取且儲存使用者輸入的數字 scanf("%d", &myNum); // 輸出使用者輸入的數字 printf("Your number is: %d", myNum); ``` ``` scanf()函數有兩個參數:變數的格式說明符 %d 和引用運算符 &myNum,儲存變數的記憶體位址。 ``` ::: ## [21.字元陣列](https://www.lssh.tp.edu.tw/~hlf/class-1/lang-c/array-char.htm) ## [22.有限狀態機](https://medium.com/pm%E7%9A%84%E7%94%9F%E7%94%A2%E5%8A%9B%E5%B7%A5%E5%85%B7%E7%AE%B1/%E5%A6%82%E4%BD%95%E6%9C%89%E9%82%8F%E8%BC%AF%E7%9A%84%E9%87%90%E6%B8%85%E4%BA%8B%E7%89%A9%E7%9A%84%E7%8B%80%E6%85%8B-f9fb59b15054) ## [23.函式](https://mycollegenotebook.medium.com/%EF%BD%83%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98-%E5%87%BD%E5%BC%8F-functions-cea21d86560f) :::success ### 1. 函式介紹 - 在C語言中==函式==相當重要,可以減少許多繁雜的步驟,將程式變得容易閱讀理解。 - printf(),本質上也是一個函式。(利用 ==include <stdio.h>== 呼叫函式庫來使用) ### 2.函式的特色: - 指定一段程式碼,執行特定的工作。 - 可重複呼叫使用 - 讓程式變得容易閱讀理解。 - 在呼叫函式==條件不改變==的狀態下,可以==直接修改==函式的程式。 - 函式分為==系統定義==函式(如printf)和==使用者定義==函式兩種。 :::success - ==系統定義==函式(==標準函式庫==): 需==呼叫==標頭檔例如: - #include <stdio.h> - #include <stdlib.h> - #include <math.h> - 標準函式庫是C語言標準提供的函式庫,包含了大量的函式,可以幫助開發者簡化程式設計,加速開發速度。標準函式庫通常可以被編譯器直接調用,而不需要開發者自己編寫相關的代碼。 - C語言的標準函式庫可以分為幾個部分,每個部分包含了不同類型的函式: - 標準==輸出/輸入==函式庫:包括了與螢幕和鍵盤輸入輸出有關的函式,例如==printf、scanf==等。 - 字符串函式庫:包括了與字串處理有關的函式,例如strlen、strcpy、strcat等。 - 數學函式庫:包括了與數學運算有關的函式,例如sqrt、sin、cos等。 - 時間函式庫:包括了與時間有關的函式,例如time、ctime、gmtime等。 - 檔案操作函式庫:包括了與檔案操作有關的函式,例如fopen、fclose、fread等。 - 其他函式庫:還包括了與動態記憶體分配、環境變數、數據類型轉換等相關的函式。 ::: :::info - ==使用者定義==函式: ![](https://i.imgur.com/LGEIHXl.png) ![](https://i.imgur.com/QSDPlbQ.png) ![](https://i.imgur.com/6SJ4E3C.png) ![](https://i.imgur.com/lXQyTf3.png) - 回傳值:回傳一個int的型態回去主程式 在下方的程式中,當我們程式跑到 f(4)中,代表他呼叫了上方 ==int f(int x)== 函式,而因為這個函式有回傳值,所以在進行計算過後,我們有一個return x+3,把計算過後的答案傳回到主程式中 f(4) 就會等於回傳值 7,印出答案後程式結束執行。 :::success - 函式定義: 使用者定義函式 ==int f(int x){ return x +3; }== ``` int main() { printf("%d",f(4)); return 0; } ``` ::: :::success - 函式宣告: ::: - 在==主程式==上方,==宣告==函式原型(程式是由上而下讀取,告訴主程式說我設的函式的大概內容),==參數可省略==,主程式下方才放置使用者定義的函式 ``` #include <stdio.h> int f(int ); //有回傳值的函式宣告 int main() { printf("%d",f(4)); return 0; } //以下是函式定義 int f(int x){ return x +3; } ``` ### 3.回傳值型態 #### ==沒有回傳值==:==void== square(int len) - 在下方的程式中,當我們程式跑到square(length)中,代表他呼叫了下方void square函式,而因為這個函式沒有回傳值,所以在印出答案中後,就直接結束程式的執行了(可以想像有一個return 0 函式下方)。 ![上午9.50 2024-3-6的影像](https://hackmd.io/_uploads/HJOMhrr6p.jpg) #### ==有回傳值==:==int== square(int length) - 回傳一個 int 的型態給 主程式 ![上午9.52 2024-3-6的影像](https://hackmd.io/_uploads/Hy_d2rBaT.jpg) ### 4. 函式宣告 - ==例==:寫一個計算正方形的程式,並且使用函式呈現。 - 在主程式上方,==宣告函式==(跟主程式說我建立的函式樣式如何) - 再從主程式下方==定義函式== ``` 回傳值型態 函式名稱 (參數) ``` ![上午10.19 2024-3-6的影像](https://hackmd.io/_uploads/rJPTG8SaT.jpg) :::success 練習題:利用函式寫一個判斷[閏年的程式](https://onlinegdb.com/CJw5yMwx5e) - 輸入: 2011 - 輸出: 0 ``` #include <stdio.h>//閏年的規則,每四年閏一次,但是每一百年不閏,遇到四百年還是要閏 int main() { //int year = 112; int year; printf("請輸入任一年的數字"); scanf("%d",&year); if ( year % 400 == 0){//除以400的餘數為0,則為閏年 printf ("閏年"); } else if (year % 100 == 0){//再除以100的餘數為0,則為平年 printf ("平年"); } else if (year % 4 == 0){//再除以4的餘數為0,則為閏年 printf("閏年"); } else { printf("平年");//餘為平年 } } ::: :::success 練習寫一個計算面積的[公式1](https://onlinegdb.com/7lfKqR1FT),[公式2](https://onlinegdb.com/7ui63kcSd) - 公式: square = len *len ::: :::success - 無回傳值的函式 ::: :::info 在函式原型宣告時,第一個宣告的元素就是函式的傳回值的資料型別,任何的基本資料型別(如int, char, float, double...等)或自訂的資料型別都可以使用,但是如果函式不傳回任何值,則我們要把資料型別宣告為==void==,意思是不傳回值。 ::: ``` #include <stdio.h> void f(int ); //没有回傳值的函式宣告 int main() { f(4); return 0; } //以下是函式定義 void f(int x){ printf("%d",x+3); return ; } ``` :::success 練習寫一個==無回傳值==的計算面積[公式](https://onlinegdb.com/IExbb4gff) - 公式: square = len *len ::: ::: success - 兩個參數的函式 ::: :::info ``` int add(int x, int y) { // 函式定義為 add,参數列表為 x 和 y int result = x + y; // 將 x 和 y 相加,得到結果 return result; // 將結果回傳給函式呼叫者 } int main(){ int sum = add(3, 5); // 呼叫函數 add,並將結果指定給變數 sum } ``` ## [函式影片1](https://www.youtube.com/watch?v=QDcGPASnB6k) ## [函式解說1](https://hackmd.io/@twthe02/ry4gu9CJ3) ## [函式影片2](https://www.youtube.com/watch?v=5NN-G5BVEmo) ::: ::: success ## [亂數](1https://blog.gtwang.org/programming/c-cpp-rand-random-number-generation-tutorial-examples/) - 使用 rand 函數產生亂數 - ==要先宣告相關函式== - #include <stdlib.h> /* 亂數相關函式 */ - #include <time.h> /* 時間相關函式 */ - C 語言中若要產生亂數,可以使用 stdlib.h 中的 rand 函式,而在呼叫 rand 函式之前,要先使用 srand 函式設定初始的亂數種子: ![上午9.04 2024-3-13的影像](https://hackmd.io/_uploads/ByksjdATp.jpg) - ==固定亂數種子==:上面的範例中,利用時間產生亂數種子,所以每次產生的亂數都不同,如果需要讓模擬的結果具有可重覆性以便除錯與驗證,這種狀況就必須將亂數種子==固定==不變,如果沒有固定亂數種子的話,每次跑出來的結果都不同,會讓除錯的難度提高。 ![上午9.30 2024-3-13的影像](https://hackmd.io/_uploads/H1RRbYC6T.jpg) - 產生==特定範圍整數亂數== ![上午9.36 2024-3-13的影像](https://hackmd.io/_uploads/HkTfmtCa6.jpg) ::: 練習題: :::success 寫一個程式,它可以處理任何筆數的成績,來處理全班分數。 第二個工作:重複輸入,直到輸入「-1」,才停止。 請輸出「輸入的分數筆數」。 輸入範例: 75 75 75 88 70 64 83 89 -1 輸出範例: 8 ::: :::warning 冒牌費氏數列 令: - f(1)=10,f(2)=15,f(3)=16 - f(n)={f(n-2)+f(n-3),當n>=4 請寫一個程式,輸入n,輸出f(n)值。 輸入範例: 5 輸出範例: 31 ::: - [zerojudge參考答案](1https://ffrankkk122.gitbooks.io/-zerojudge-code/content/a001.html) - [APCS檢定應試指南](1https://hackmd.io/@howkii-studio/apcs_overview/https%3A%2F%2Fhackmd.io%2F%40howkii-studio%2Fapcs_exercise_programming) - [c語言實例100題](https://www.runoob.com/cprogramming/c-100-examples.html) - [幾A幾B猜數字](http://www.mathland.idv.tw/game/1A2B.htm) - [c 語言破解](1https://hackmd.io/@CHAWTeam/DiceC/https%3A%2F%2Fhackmd.io%2F%40CHAWTeam%2FDiceC-15-3) - [data-structure-c](https://github.com/ksw2000/Data-Structure-in-C) - [遞迴](https://hackmd.io/@sysprog/c-recursion) - [河內塔](https://jason-chen-1992.weebly.com/home/-tower-of-hanoi) - [河內塔遞迴概念](http://www.mathland.idv.tw/life/hanoirecursion.htm) - [河內塔遊戲](https://www.novelgames.com/zh-HK/tower/) - [河內塔演算法](https://ithelp.ithome.com.tw/articles/10245079) - [河內塔遞迴執行順序](https://ithelp.ithome.com.tw/articles/10281346) - [迭代版河內塔程式](http://squall.cs.ntou.edu.tw/cprog/practices/Iterative%20Hanoi.pdf) - [迭代與遞迴的差別](http://203.72.56.75/~pingfeng/geogebra/htm/6/6-8A0_1.pdf) - [遞迴 VS 迭代](https://hackmd.io/5T81GHb6RAihMSHQebVcZQ?both) - [費氏數列以迭代和遞迴實作](https://dotblogs.com.tw/Ace_Dream/2016/01/20/iterative_recursive) - [c語言講義](https://web.fg.tp.edu.tw/~earth/vision/study/cprogram06/C_handout.pdf) - [P問題和NP問題](https://www.youtube.com/watch?v=YX40hbAHx3s) - [常見程式演算](https://openhome.cc/zh-tw/algorithm/) - [Coding Prep 程式教學](https://coding-prep.com/) - [APCS筆試題目分類](https://hackmd.io/@algoseacow/apps-written?fbclid=IwAR3PEteZkXjjWeiSZEkSR0Y1OdhRGuFZxIviMxwSk8HZ12V0z5ev5yy02so) - [APCS Code::Blocks 操作教學](https://hackmd.io/@smallshawn95/apcs_codeblocks?fbclid=IwAR1-2zUUf8KexWebx_x5fmUM0JydUzIC2yOXEDSGwUAVDufeMDBd0TExK20) - [程式自學平台](https://e-tutor.itsa.org.tw/e-Tutor/) - [如何在windows環境用gcc編譯成執行檔](https://shaochien.gitbooks.io/how-to-use-gcc-to-develop-c-cpp-on-windows/content/use-gcc-to-compile-program.html) - [新竹實驗中學C++講義](https://hackmd.io/@CLKO/B18yT_i5Z?type=view) - [zerojudge-高中生程式解題系統](https://zerojudge.tw/)