###### 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/)