---
# System prepended metadata

title: "C語言期中考搶救包\U0001F62D"

---

# C語言期中考搶救包😭
給對C語言考試還抱有補救心態的人
## 前言
### 注意
- 以下程式皆為C的寫法
- 按照順序，底下的概念需要上面的概念
- 電腦看字體大小比較正常
- 純手打無AI，有錯可告訴我
- 還沒寫完的我有空再用
- 有問題當然可以來問我，但我希望來問之前可以先自己查過or問過AI，清楚自己要問什麼
### 以下為我的廢話可以跳過
印象中上禮拜有人問我資訊課考試可以看什麼
我就只能說基礎語法，我也不知道你們可以看什麼
阿最近要考了感覺聽到蠻多哀號的
突然覺得我可以搞個教學，給還想補救的人
考完APCS，就有時間搞這個了
(結果這東西花我很少時間，兩小時內，主要打字不夠快)
我覺得班上其實蠻多人會程式的
只是感覺沒人再討論就是了
希望想學的是有能被救到啦

## 變數
變數 就是個可以儲存值，且可以用來運算跟修改的東西
#### 宣告一個變數
用變數前，你需要告訴電腦
要一個 什麼類型 什麼名字 初始值是多少的變數
這個動作叫 宣告
```c
類型 名字 = 初始值;
int a = 0;
```
類別：
整數 int
小數 float
字元 char
字串 string
布林 bool

| 意思 | 類別名 | 說明                                            |
| ---- |:------:| ----------------------------------------------- |
| 整數 |  int   | 就是整數🙂                                      |
| 小數 | float  | 就是小數🙂                                      |
| 字元 |  char  | 單一字或符號，用`' '` ，如 `'a'`、`'/'`               |
| 字串 | string | 一串字或符號，用`" "`，如 `"Hello world!"` |
| 布林 |  bool  | `true`或`false`，使用需引入標頭 `#include<stdbool.h>`|


## 輸入輸出
C語言的輸入輸出其實不太好搞
使用輸入輸出時需要引入標頭檔`#include <stdio.h>`
關於標頭檔有興趣自行研究
### 輸入
```c
int a = 0;
scacnf(輸入輸出類型,&變數名,可多個變數);
scacnf("%d",&a);
```
類型是字串的格式進去的，所以用" "
**重要: & 記得寫，沒寫會出問題且不會報錯**

這邊的類型又跟上面不太一樣的
| 類別名 | 輸入輸出類型 |
|:------:| ------------ |
|  int   | %d           |
| float  | %f           |
|  char  | %c           |
| string | %s           |

可以發現只有int要特別記一下
這邊要知道一個 %* 代表一個數字，所以可以
```c
int a,b,c;
scanf("%d%d%d",&a,&b,&c); // 一行輸入三個
```
### 輸出
輸出不用 &
```c
printf(類型，變數名)
printf("%d",a);
printf("\n"); // "\n" 為換行符號

// 字串內為格式，他會把 %* 替換成你給的變數
int a=2,b=1;
printf("%d + %d = %d\n",a,b,a+b);
// 結果
// 2 + 1 = 3
```
類型跟上面一樣
而字串裡面就是輸出格式
特別的是小數輸出，可以對他設置格式
```c
float a = 5.55;
printf("%.3f",a); // 輸出至小數點後3位，這個比較好用
//結果: 5.550
printf("%3.1f",a); // 共輸出三位，小數點自身算一位
//結果: 5.6
```
有發現一件事嗎，他自動四捨五入了
~~我高一考試被這搞到~~
如果不要四捨五入，就不能這樣算
:::spoiler 不要四捨五入參考寫法:
```c
float a = 5.55;
float b = (int)(a * 10) / 10;   // 截斷到小數一位
```
:::

## 基本運算
加減乘除 以及 求餘
計算順序是 括號 > 乘除 求餘 > 加減
基本運算的寫法都一樣：
```c
int a = 0;
int b = 2
a = a + 1; 
a = a - b; // 運算可以都是變數
a = (a + 1)*b; // 括號優先 
a = a / 1;
a = a % 7;
// 以上都可以簡寫成以下形式
a *= 2;
a -= 7;
// 當"加減"數字1時，還可以簡寫成
a++;
a--;
```
要注意的是程式的`一個等於`
代表把右邊的值賦予給左邊(稱為賦值)
加減乘用法比較沒什麼問題
特別要注意的是 除 求餘
### 除
除要特別注意類別問題
如果 整數除整數
是**不會**產生小數的(無條件捨去)
如 `5/2 = 2`
整數除小數 或 小數除小數 就沒問題
如何讓整數除整數，需要保留小數？
把整數轉成小數
```c
int a = 5;
float b = 5 / 2.0; // 除2改成除2.0

int c = 2; // 除數是變數
float t = c; // 轉小數
float d = a / t;
// 也可以用強制轉換： (轉換類型)變數
// 課上可能沒教? 我不知道
float d = a / (float)c;
```
### 求餘
求餘比較特別，取左邊÷右邊的餘數
舉例 7/2 = 3...1
所以 7%2 = 1
寫法跟上面運算都一樣
```c
int a = 5;
a %= 2; // a=1
```
求餘x可以判斷是否整除x
底下章節再詳細講

## 條件運算、邏輯運算
結果會是布林值
### 條件(比較):
```c
bool result = 1>=2; //false
//也可以是變數
int a=10,b=6;
result = a > b; //true
```
比較運算子:
```c
>     大於
>=    大於等於
<
<=
==   <- 要注意兩個等於才是比較
```
一個等於是賦值
絕對不能寫錯（不小心寫錯很難發現）
### 邏輯
```c
bool a = true;
bool b = false;
bool c = a || b; // c = true
c = a && b; // c = false
c = ( a || b ) && a; //括號優先 c = true 
```
| 邏輯運算子 | 意思    |
| ---------- | ------- |
| &&         | 與(and) |
| \|\|       | 或(or)  |

## 條件判斷
讓程式依照不同情況運行不同內容
將會用到上面的條件運算、邏輯運算
結構：
```c
if(布林值){
    
}else if(布林值){
    
}else{
    
}
int a = 75;
if(a >= 90){
    printf("A");
}else if(a>=80){
    printf("B");
}else{
    printf("C");
}
// 結果:
// C
```
if系列有三個 `if` `else if` `else`
並沒有一定要都出現，也沒有限制要幾個
視情況自己判斷，但要寫`if`就是會出現`if`
不會出現沒有`if`的 `else if` 跟 `else`
**很重要：要記得寫小掛號跟大掛號**

條件判斷很常跟求餘一起用
```c
int a = 10;
if (a%5 == 0){ //判斷整除
}

int b = 3;
if (b%2 == 1){
    // 是奇數
}else{
    // 是偶數
}
```

### 巢狀
if系列內可以再套if系列
但要注意else是給誰
這時候`縮排`就很重要了
```c
if(){
    if(){
        
    }else{
        
    }
}else{
    
}
```
## 迴圈
重複做很多次同樣內容
**很重要：要記得寫小掛號跟大掛號**
### for
結構：
```c
for(變數宣告 ; 持續條件 ; 每次循環改變變數){
    
}

for(int i=0 ; i<10 ; i++){
    printf("%d ",i); //注意:這個輸出格式有%d旁有空格
}
// 輸出結果：
// 0 1 2 3 4 5 6 7 8 9
for(int i=10 ; i>=0 ; i--){
    printf("%d ",i);
}
// 輸出結果：
// 10 9 8 7 6 5 4 3 2 1 0

int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
    printf("%d ",i);
}
// 結果：
// 輸出 1~n
```
當 `持續條件` 為false時跳出迴圈
同樣的for一樣可以巢狀
但注意兩層變數名要不同
```c 
for(int i=0 ; i<4; i++){，， // 這裡是 i
    for(int j=0 ; j<4 ; j++){  // 這裡是 j
        printf("%d ",i*j);
    }
    printf("\n");
}
// 結果:
// 0 0 0 0
// 0 1 2 3
// 0 2 4 6
// 0 3 6 9
```
### while
while只靠一個布林值來判斷是否執行
透過內部邏輯來改變判斷條件
如果內部沒有改變會導致無限迴圈
結構：
```c
while(布林值){
    //記得要能改變上面的條件
}
int a = 99;
while(a>0){    
    printf("%d ",a);
    a /= 2;
}
// 輸出：
// 99 49 24 12 6 3 1
```
同樣可以巢狀

### continue break
continue 和 break 可以在迴圈中跳出
continue是跳過一次當前迴圈，整個迴圈依然繼續
break會直接離開一個迴圈
要注意break只會跳離一個
如果是巢狀，並不會跳出所有
兩個都只能在迴圈中使用
```c
for(int i=0;i<10;i++){
    if(i%2==0){
        continue; //跳過一次
    }else if(i>=4){
        break; //離開迴圈
    }
    printf("%d",i);
}
// 結果：
// 1 3
```
### 該用for還是while？
for適合確定迴圈次數的情況
while適合不知道要迴圈幾次


## 其他
### return
return將會退出函式
函式有興趣自行研究
現在會用到的是 `int main(){}` 這是一個函式
所以在裡面用 `return 0;` 會退出整個程式

### 常用函式
#### 根號
需引入`#include <math.h>`
`sqrt();` 小括號內放數字，輸出根號值
#### 絕對值
需引入`#include <stdlib.h>`
`abs();` 小括號內放數字，輸出絕對值

# 上次的題目+題解
## 韓信點兵
韓信點兵後，發現兵的數量呈現以下規則
5人一組剩3人
7人一組剩2人
11人一組剩5人
問1~10000那些兵數滿足條件
:::spoiler 題解
5人一組3人就是 人數 / 5 的餘數 -> n%5 == 3 是否為true
所以用if判斷是否三個條件是否同時成立就好
人數可以可能是1\~10000，所以for迴圈1~10000
:::
:::spoiler 完整程式
```c=
#include <stdio.h>
int main() {
    for(int i=1;i<=10000;i++){
        if(i%5==3 && i%7==5 && i%11==5){
            printf("%d\n",i);
        }
    }
    return 0;
}
```
:::

## 電影院座位
Amy去看電影，影廳的座位是8個一排，共12排，96個位置，所有座位按照
順序編號。請輸入Amy的座位編號(1-96)，印出她的座位在第幾排第幾個位置。(作業題)
:::spoiler 題解
觀察一下可以發現編號是
1~8 -> 第一排第1~8
9~16 -> 第二排第1~8
...以此類推
可以發現排數是 (n/8)+1 
但當n=8時上面的式子會不對
所以要特別處理當n整除8的情況 ->排數為 (n/8)
第幾個則是 n%8
同樣特別處理n整除8的情況 -> 個數為8

:::
:::spoiler 完整程式
```c=
#include <stdio.h>
int main()
{
    int n,r,c;
    scanf("%d",&n);
    if (n%8 != 0){ 
        r = n/8+1;
        c = n%8;
    } else { // 整除情況
        r = n/8;
        c = 8;
    }
    printf("%d %d\n",r,c);
    return 0;
}
```
:::

## 質數
輸入一整數，輸出是否為質數
是的話輸出"yes"否則"no"
:::spoiler 題解
質數定義為除了1跟自己(n)，還能整除其他數
所以只要迴圈1~n，每個數字都判斷一下能不能整除
能整除的話代表不是質數跳出迴圈，能的話繼續
要注意不能在迴圈中輸出，除非你確定輸出之後不會在繼續迴圈
否則會重複輸出
:::
:::spoiler 完整程式
法一: 使用bool變數
```c=
#include <stdio.h>
#include <stdbool.h> //bool
int main() {
    int n;
    scanf("%d",&n);
    bool is_prime = true;
    for(int i=2;i<n;i++){
        if(n%i == 0){
            is_prime = false;
            break;
        }
    }
    if(is_prime){
        printf("yes");
    }else{
        printf("no");
    }
    return 0;
}
```
法二:使用return來確保不會重複輸出
```c=
#include <stdio.h>
int main() {
    int n;
    scanf("%d",&n);
    for(int i=2;i<n;i++){
        if(n%i == 0){
            printf("no");
            return 0;
        }
    }
    printf("yes");
    return 0;
}
```
:::

## 分薯條
子路有23根薯條，想分給給他4個朋友
社長最多拿8
冠頡最多拿7
家瑋最多拿6
章宇最多拿5
問有幾種方法可以分
:::spoiler 題解
~~子路我要吃薯條~~
如果排列組合厲害的話可以用數學算出答案
程式最簡單的解法是四層for迴圈，代表四個人拿到的薯條
循環出所有滿足條件的答案
怎麼知道是否滿足條件?
四個for迴圈的變數相加等於23就是滿足條件
另外我記得有人會用+-來跑這個
當然可以，那是更好的做法，只是實作比完全暴力解還難
這題很神奇的是，有沒有限制能不能不拿薯條，出現的答案是一樣的
我是懶得想為什麼www
:::
:::spoiler 完整程式
```c=
#include <stdio.h>
int main() {
    int count = 0;
    for(int i=0;i<=8;i++){
        for(int j=0;j<=7;j++){
            for(int k=0;k<=6;k++){
                for(int l=0;l<=5;l++){
                    if(i+j+k+l == 23){
                        count++;
                    }
               }
            }
        }
    }
    printf("%d",count);
    return 0;
}
```
:::


## 會長高的怪植物
班上在種綠豆，有一盆綠豆變異成怪植物了
怪植物
第一天會長高 原高度的一半
第二天會長高 原高度的一半又一半
每天長高的長度 會是 上一天的一半
當長高長度 $<0.5$ 時，植物就沒救了，停止生長
輸入植物的長度，輸出最後植物的長度
:::spoiler 題解
先計算出一天會長多少，一天一天的加到原長度上就是答案了
由於原長度不限，所以也不能確定要幾天才會<0.5，所以用while
每天生長長度: $l = l/2$ (初始=原長度)
每天長度: $原長度$ += $l$;
:::
:::spoiler 完整程式
```c=
#include <stdio.h>
int main() {
    float n; //長度
    scanf("%f",&n);
    float l = n; //每天生長長度  初始 = 原長度
    while(l>=0.5){
        l /= 2;
        n += l;
    }
    printf("%f",n);
}
```
:::

## 密碼差
輸入一整數，輸出這串數字中
$|奇數位總和 - 偶數位總和$|
:::spoiler 題解
這題難點在於分出奇數位和偶數位
方法很多，這邊提供我自己的做法
個位數的取法是 n%10 ，這樣能取到個位數
取完之後 n/10，捨棄掉個位數
再次取個位數，這時會取到原先的十位數
重複直到 n==0 結束
可以發現每重複一次，會取到 
奇數位 -> 偶數位 -> 奇數位 -> ...
只要這次是奇，下次一定是偶 ...以此類推
所以只要建立兩個總和變數，判斷當前奇偶，加上對應的變數
最後再取差就好
:::
:::spoiler 完整程式
```c=
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main() {
    int n;
    scanf("%d",&n);
    int odd_sum = 0;
    int even_sum = 0;
    bool is_odd = true;
    while(n!=0){ //不確定跑幾次用while
        if(is_odd){
            odd_sum += n%10;
            is_odd = false;
        }else{
            even_sum += n%10;
            is_odd = true;
        }
        n /= 10;
    }
    // 絕對值: abs()
    printf("%d", abs(odd_sum - even_sum) );
}
```
:::
