---
# System prepended metadata

title: C語言筆記
tags: [重點筆記, C語言]

---

###### tags:`C語言`、`重點筆記`

# <font color = "#f00"> 參考資源 </font>

## 書籍
:::success
* C語言教學手冊 第四版
:::


# <font color="#f00">第一章節 認識C語言</font>

## <font color="#AC19C9">C語言概述</font>
* **創造者：** **Dennis Ritchie**
* **前身：B語言**
>1. 原先用於撰寫DEC PDP-11電腦的系統程式(此程式與Unix系統密不可分)
>2. 現已成功植入個人電腦
>ex：Turbo C、Microsoft C ……

![image](https://hackmd.io/_uploads/H1xQ0tap0.png)

---


## <font color="#AC19C9">C語言特色</font>

### 1. 高效率的編譯式語言
      原始程式碼編輯完成後，需轉換成機器碼(machine code)後，才能正確執行。
      
      ps：所有程式語言度附有這種轉換程式。(直譯器、編譯器)
        


* **直譯器(interpreter)**

    1. 先檢查該行敘述，有錯誤立即中斷，直至修正後才繼續執行。
    2. 優點：占用記憶體較少
       缺點：執行速度慢、效率低

| 示意圖 (直譯器) |
| -------- | 
| ![未命名绘图.drawio](https://hackmd.io/_uploads/HJzKnCxQ0.png)   |


* **編譯器(compiler)**

    1.  先檢查所有程式碼，然後編譯成可執行檔；當程式每修改一次，就須重新編譯。
    2.  執行效率高於直譯器(interpreter)

| 示意圖 (編譯器) | 
| -------- | 
| ![2.drawio](https://hackmd.io/_uploads/r1M711Zm0.png)| 




### 2. 介於高階與低階之語言
    程式語言可依其特性分為「高階語言」、「低階語言」
    
    1. C語言兼顧了低階優點(硬體控制)和高階(易於撰寫、除錯)，故人稱「中階語言」。
    
    2. C語言可容易的連結「組合語言」，提高執行效率。

* **低階語言(ex：組合語言)：**
    1. 優點：執行效率高、對硬體控制程度相當好
       缺點：艱澀難懂、維護不易

* **高階語言：**
    1. 敘述性語言
    2. 優點：易於撰寫、除錯
       缺點：執行效率低、對硬體控制程度差


### 3. 靈活的程式控制流程
    可容易設計出具有結構化及模組化的程式語言
![image](https://hackmd.io/_uploads/HySBAt6TA.png)



### 4. 可攜性佳
    1. 可攜性(portability)就像是硬體的相容性(compatibility)一樣
    
    2. 可攜性意味著某一系統所撰寫的程式語言，可在少量修改或不修改的情況下，即可在另一作業系統執行。
    
    ex：在Unix的C程式碼拿到Windows的環境裡執行，僅需修改少量程式碼，再重新編譯即可執行。



### 5. 為程式設計師所做的語言
    1. 可直接依記憶體位址來存取變數，以提高程式執行的效率。
    
    2. C語言也提供了豐富的運算子(operator)，使語法更為簡潔有力。
    
    3. 大多數C語言環境都提供了已撰寫好的程式庫(library)，內含許多C語言函數供使用者無需重新撰寫程式碼。

---

## <font color="#AC19C9">程式的規劃與實作</font>
    程式撰寫需經歷6個步驟



### 1. 規劃程式：
* 撰寫這個程式的目的為何？
* 使用者是誰？
* 需求在哪？


| 流程圖 
|-------- | 
| ![image](https://hackmd.io/_uploads/Skg9YyZQR.png)|
|![image](https://hackmd.io/_uploads/S1zW51ZXA.png)|
![image](https://hackmd.io/_uploads/BkGtCY6TC.png)



### 2. 撰寫程式碼及註解：
    加上註解可增加維護程式的容易度、可讀性。



### 3. 編譯與連結程式：
    程式藉編譯器 → 電腦看得懂，在轉換後透過連結器與函數模組連結 → 可執行之程式。



### 4. 執行程式：
    通常編譯完程式，沒有錯誤後，編譯程式會製作一個可執行檔。

### 5. 除錯與測試：
* **語意錯誤 (semantic error)：**
> 邏輯錯了。
* **語法錯誤 (syntax error)：**
> 語法錯了。



### 6. 程式碼的修飾與儲存：
    執行結果沒問題；可將程式增加可讀性或簡化程式。
    

---

## <font color="#AC19C9">基本流程</font>

| 示意圖 |
| -------- | 
|   ![3.drawio](https://hackmd.io/_uploads/BJ7tle-mA.png)| 

---

## <font color="#AC19C9">編譯與執行過程</font>
    1. compiler除了檢查語法是否正確，還會讀取標頭檔(header file)，根據其記載的函數原型(prototype)，檢查函數用法是否合乎規則；皆無錯誤後產生一個目的檔。
    
    ps：目的檔：已編譯且沒錯的程式
    
    2. 目的檔(object file)產生後，則由連結器(linker)連結object file和函數庫(library)，成為一個「.exe」的可執行檔案。
    
    ps：執行檔：成為一個獨立個體，無須環境即可執行。
> 函數是C語言的基本單位，C語言由函數組成。
> * 若要使用函數，使用對應的標頭檔即可。
> * 不同的函數集合再一起，統稱"函數庫"。


| 示意圖 | 
| -------- |
| ![4.drawio](https://hackmd.io/_uploads/SJMFBeZm0.png)|


---

# <font color="#f00">第二章節 C語言基本概述</font>

## <font color="#AC19C9">簡單的例子</font>


```c=
/* prog 2-1 , C語言 */
#include <stdio.h>
#include <stdlib.h>
int main(void){
    
    int num;
    num = 2;
    
    printf("I have %d cats.\n",num);
    printf("You have %d cats, too.\n",num);
    
    system("pause");
    return 0;
}
```


* **註解**
    * 「//」 、「/*  */」
* **#include <stdio.h>**
    1. 告訴computer 把stdio.h，包括(include)進來。
    2. 凡定義「输入」、「输出」函數的格式。
    > stdio ⇒ standard input/output的縮寫。
    > .h ⇒ header 的字首。
* **#include <stdlib.h>**
    * 標準函數庫
    >  stdlib ⇒ standard library的縮寫。
* **int main(void)**
    1. 定義 main 函數(範圍從左大括號到右大括號)。
    2. main 為主函數(程式開始執行的起點)。
    3. 每個獨立C程式一定要有 main()函數。
    > int ⇒ integer的縮寫(整數之意)。
    > void ⇒ main()函數不須傳入任何引數。
* **int num;** 
    * 宣告num為一個整數型態的變數。
* **num = 2;**
    * 設定敘述。
* **printf("I have %d cats.\n",num);**
    1. 「%d」以num值來取代(十進位格式)。
    2. 「/n」為換行的控制字元。
* **system("pause");**
    1.  使程式執行到這便先暫停。
    2.  不會自動關閉DOS視窗，可不用撰寫此敘述。

* **return 0;**
    1. 由main()函數傳回整數 0 ，此數值由系統接收。
    2. 已傳回 0 代表程式順利執行，傳回其他整數表示程式出錯。
    > 因傳回值為整數，所以main()函數必須指明傳回值的型態為int。

## <font color="#AC19C9">標頭檔 (header file)</font>

* #include為C語言前置處理器(pre_processor directive)，因為是在編譯前執行，故稱「前置」處理器。
* 一些以「#」開頭的指令都屬於前置處理器。


      1. 不含括stdio.h或stdlib.h標頭檔也可以編譯？
    
      Ans： * 某些編譯器會將常用的標頭檔自動載入。
            * 有些編譯器發現沒含括標頭檔之後，會出現警告訊息，並自動含括該有的標頭檔。
         
      ps：建議都仍打上標頭檔避免程式出錯。

      2. 含括了不必要的標頭檔是否會增加編譯後程式大小？
    
      Ans：不會；沒使用到的資訊不屬於程式範圍，故不會增加程式大小。
    

## <font color="#AC19C9">主函數main()與函數的本體</font>

1. main()是一個不可或缺的函數，他是程式執行的開端，沒他程式無法動。
2. 每一個C程式必須有一個main()函數，而且只能有一個。
3. 從左大括號開始到右大括號結束，此區間程式碼稱為main()函數的本體(body)。
4. 用來完成特定工做的程式片段稱為「區塊(block)」。

       ps：本體內的每個指令敘述結束後，必須以分號「；」做結尾。

![image](https://hackmd.io/_uploads/H1lgw9aTC.png)

## <font color="#AC19C9">變數與常數</font>
     1. 變數可用來存放資料。
     2. 在同一個敘述中，每個變數皆須以逗號分開。
     3. 可依個人喜好決定變數名稱，但不可使用「關鍵字(keyword)」。
     4. 不管變數的值如何改變，其值永遠占用相同記憶空間。
* **宣告變數的好處**
    * 方便編譯器找到錯誤的變數名稱。
    * 避免變數名稱打錯。
    * 除錯容易。
    * 增加程式的可讀性。
    * 便於程式碼的維護。

      
* **常數(constant)不同於變數，其值固定。**

---

## <font color="#AC19C9">識別字及關鍵字</font>
### 識別字(identifier)
    使用者自訂；只要能代表變數意義即可。
    
### 關鍵字(keyword)
    用來命名變數或函數的文字(C語言預先定義的識別字)。
![image](https://hackmd.io/_uploads/r1Vi9cpa0.png)

### 提高程式的可讀性
    1. 建議採用固定字距(fixed spaced)的字體。
    2. 將程式碼縮排(indent)。
    3. 加上註解。


---

# <font color="#f00">第三章節 基本資料型態</font>

![image](https://hackmd.io/_uploads/ByuCkj6aR.png)

## <font color="#AC19C9">無號整數</font>
    1. 當資料絕對不會出現負數的時候使用。
    
    2. 其正數的表示範圍變為原先2倍。
![image](https://hackmd.io/_uploads/Sk1MgspTC.png)

## <font color="#AC19C9">溢位(overflow)</font>

    數值大小超過變數可表示範圍。

![image](https://hackmd.io/_uploads/HyOeZoaaR.png)

```c=
#include <stdio.h>
#include <stdlib.h>
int main(void){
    short sum,s = 32767;
    
    sum = s + 1;
    printf("s + 1 = %d\n",sum);
    
    sum = s + 2;
    printf("s + 2 = %d\n",sum);
    
    return 0;
}
```

## <font color="#AC19C9">字元型態 char</font>
    1. 字元常數必須放在單引號「''」，而非雙引號「""」。
    
    2. 字元格式碼為「%c」。
    
    ps：字元常數與字串常數是有區別的！！！
        前者用單引號「''」包圍字元，後者則用雙引號「""」包圍。
        
        
```c=
#include <stdio.h>
#include <stdlib.h>
int main(void){
    
    char ch ='a';
    printf("ch = %c\n",ch);
    printf("ASCII of ch = %d\n",ch);
    
    return 0;
}
```


```c=
#include <stdio.h>
#include <stdlib.h>
int main(void){
    
    int i = 298;
    
    printf("ASCII(%d) = %c",i,i);
    
    return 0;
}
```


## <font color="#AC19C9">跳脫字元與跳脫序列
</font>

    對於某些無法直接用鍵盤輸入的字元，C語言是以反斜線字元「\」，加上一個控制碼作為一個完整的特殊字元。

* 反斜線「\」稱為跳脫字元(escape character)。

* 反斜線「\」加上控制碼，稱為跳脫序列(escape sequence)。

![image](https://hackmd.io/_uploads/rkxD8i6a0.png)

## <font color="#AC19C9">浮點數型態 float</font>
    小數型態的數值；浮點數(floating point)
    
* 要印出浮點數，可用「%f」格式碼。
* 要以指數的型式列印浮點數，可用「%e」格式碼。

```c=
/* floating point example*/
#include <stdio.h>
#include <stdlib.h>
int main(void){
    float num1 = 123.45f;
    float num2 = 4.65e-3f;
    
    printf("num1 = %e\n", num1);
    printf("num2 = %f\n", num2);
    system("pause");
    return 0;
}
```

## <font color="#AC19C9">倍精度浮點數 double</font>

    1. 表示範圍需要更大時，可使用倍精度浮點數double。
    
    2. 也是用「%f」格式碼。

    ex：「%16.12f」代表共16個字元，其中有12個字元是小數點之後的位數。

![image](https://hackmd.io/_uploads/BJA9Yipp0.png)

## <font color="#AC19C9">查詢常數、變數或資料型態所佔位元組</font>

* **sizeof 指令 (1)**
    * 查詢變數佔了多少個位元組的語法：
![image](https://hackmd.io/_uploads/ByA6cjaa0.png)

* **sizeof 指令 (2)**
    * 查詢資料型態所佔的位元組：
![image](https://hackmd.io/_uploads/rJmQoipTC.png)

```c=
/* 列印出各種資料的長度 */
#include <stdio.h>
#include <stdlib.h>
 int main(void){
    char ch;
    float num; 

    printf ("sizeof(2L) = %d\n", sizeof (2L));

    printf ("sizeof(ch) = %d\n", sizeof(ch));
    printf ("sizeof(num) = %d\n", sizeof(num));

    printf ("sizeof(int) = %d\n", sizeof(int));
    printf("sizeof(long) = %d\n", sizeof(long));
    printf("sizeof(short) = %d\n", sizeof(short));

    system("pause");
    return 0;
 }
```

## <font color="#AC19C9">資料型態的轉換</font>

*   **將資料型態轉換成另一種型態的語法：**
![image](https://hackmd.io/_uploads/S1pKoipTA.png)

```c=
/* 浮點數轉換成整數的範例： */
#include <stdio.h>
#include <stdlib.h>
int main(void){
    int n1,n2; 
    float num1=3.002F, num2=3.988F;

    n1 = (int) num1;
    n2 = (int) num2;

    printf ("numl=%f, num2=%f\n", num1, num2); 
    printf("nl = %d, n2 = %d\n", n1, n2);

    system("pause");
    return 0;
}
```

```c=
/* 整數轉換成浮點數的範例： */
#include <stdio.h>
#include <stdlib.h>
int main(void){
    int num = 5;

    printf ("numl / 2 = %d\n",num/2); 
    printf("(float)num/2 = %f\n",(float)num/2);

    system("pause");
    return 0;
}
```


---


# <font color="#f00">第四章節 格式化的輸出與輸入</font>

## 輸出函數printf()
    可表達文字、意念、資訊…
    由print(列印)和format(格式)所組成，也就是「格式化列印」。
    
* printf()函數使用格式：
![image](https://hackmd.io/_uploads/HyM8F7jfye.png)

    *  格式字串必須以雙引號包圍，裡面填入欲輸出的字串與項目格式。
    *  而項目1、項目2等可以是常數、變數或是運算式。
    *  格式字串裡有幾個格式碼，後面就應該有相同數目的項目。
    *  每個引數需用逗號隔開。 
    
    
```c=
#include <stdio.h>
#include <stdlib.h>
int main(void){
    
    int a = 2, b = 3;
    
    printf("I have %d dogs and %d cats.\n",a,b);
    
    return 0;
}
```

## 用於printf()函數的格式碼
        不同型態的資料內容必須配合不同的列印格式碼。
        ps：若要列印出百分符號「%」，格式碼需用「%%」。
![image](https://hackmd.io/_uploads/rJWw6Qjzkg.png)


## 控制輸出欄位的寬度
    若想讓資料在輸出時，能有固定的欄位寬度，可以在「%」後面加上寬度的數值。
    ex：「%6.2f」表示包含小數點總共6個位數，小數點右邊只要顯示2位數。

```c=
#include <stdio.h>
#include <stdlib.h>
int main(void){
    
    int num1 = 32, num2 = 1024;
    float num3 = 12.3478f;
    
    printf("num1 = %6d\n",num1);
    printf("num2 = %-6d\n",num2);
    printf("num3 = %6.2f\n",num3);
    
    return 0;
}
```

## printf()函數的修飾子
        格式碼「%-6d」裡的負號與數字6便是printf()函數的修飾子(modifiers)。

![image](https://hackmd.io/_uploads/SyBWeEozkl.png)

```c=
#include <stdio.h>
#include <stdlib.h>
int main(void){
    
    int i = 1234;
    
    printf("i = %+08d\n",i);
    
    return 0;
}
```


