###### 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; } ```