Introduction to the C Programming Language
程式碼的編譯 一般來說,程式碼編輯完成後,必須轉換成機器所能理解的語言(即機器碼,machine code)後,才能正確的執行。 所有的程式語言中,都附有這種轉換的程式,而轉換程式可概分成兩種,即直譯器(interpreter)與編譯器(compiler)。 C語言是屬於編譯器的一種。
C語言的編譯及連結過程 撰寫程式 編譯器 (Compiler) 連結程式 (Linker) 原始程式 (xxx.c) 函數庫 (Library) 連結程式 (Linker) 目的檔 (xxx.obj) [ 參閱 : C語言教學手冊 1-15 ~ 1-17 , 洪維恩著 ] 利用文字編輯程式(text editor) 撰寫一原始檔案(.c), 所有的原始檔都要有.c的擴充檔名,否則將不會正確 地被編譯程式認出來. 此原始檔案經由編譯程式(complier)產生目的檔(.obj), 1. 編譯程式除了要檢查原始程式的語法,定義的變數名稱 等等是否正確之外,還要將標頭檔讀進來,根據這個標頭檔 的內容所記載之函數的定義,檢查程式中所使用的函數用法 是否合乎規則. ] 2. 目的檔即代表一個已經編譯過且沒有錯誤的程式. 可是雖然 目的檔的內容是正確的,但它不代表執行結果會完全正確, 因為它無法替您檢查出邏輯上的錯誤. 連結程式(linker)會將其他的目的檔及所呼叫的函數庫(library) 連結在一起後,產生一可執行檔(.exe). 函數庫 : C語言已經將許多常用的函數寫好,並將這些函數分門別類 (如數學函數,標準輸出輸入函數等),當你想要使用這些函數時, 只要在程式中載入它所屬的標頭檔就可以使用它們.這些不同 的函數集合在一起,就把他們統稱為函數庫. 執行檔 (xxx.exe)
簡 單 的 C 程 式 範 例 #include<stdio.h> #include<stdlib.h> /* prog1_1 , 第一個C程式碼 */ #include<stdio.h> #include<stdlib.h> int main(void) { printf("First C program!\n"); /*在螢幕上印出 ””內的字串*/ printf("享受C的樂趣\n!"); system("pause"); /*暫停程式的執行*/ return 0; } 原始的程式碼 說明: 1. #include<stdio.h> : 將stdio.h這個檔案含括進來,並置於#include這行敘述的地方. 2. main() : 程式執行的起點,所執行的是{ }內的內容. 3. 空格,跳格,換行,對編譯程式來說是看不到的,故可利用“縮排” 來增加 “可讀性”
程式碼的編輯、撰寫 下面視窗為鍵入程式碼之後的情形: 說明: 1. #include<stdio.h> : 將stdio.h這個檔案含括進來,並置於#include這行敘述的地方. 2. main() : 程式執行的起點,所執行的是{ }內的內容. 3. 空格,跳格,換行,對編譯程式來說是看不到的,故可利用“縮排” 來增加 “可讀性”
程式碼的編輯、撰寫 選擇『檔案』功能表裡的『儲存』即可儲存檔案。 存檔類型需存成 .c 檔 說明: 1. #include<stdio.h> : 將stdio.h這個檔案含括進來,並置於#include這行敘述的地方. 2. main() : 程式執行的起點,所執行的是{ }內的內容. 3. 空格,跳格,換行,對編譯程式來說是看不到的,故可利用“縮排” 來增加 “可讀性”
程式碼的編譯、執行 程式碼寫完後,接下來就是要將原始程式碼變成可執行的程式碼。 以Dev C++為例,有下列幾種方式進行編譯與執行: 選擇『執行』功能表中的『編譯』來編譯程式, 然後選擇『執行』功能表裡的『執行』來執行它。 選擇『執行』功能表裡的『編譯並執行』,此時 Dev C++在編譯完程式之後,會自動執行程式。 說明: 1. #include<stdio.h> : 將stdio.h這個檔案含括進來,並置於#include這行敘述的地方. 2. main() : 程式執行的起點,所執行的是{ }內的內容. 3. 空格,跳格,換行,對編譯程式來說是看不到的,故可利用“縮排” 來增加 “可讀性”
簡 單 的 C 程 式 範 例 #include<stdio.h> /* 將stdio.h這個檔案含括(include)進來*/ #include<stdlib.h> int main(void) { int num; /* 宣告一個名為num的整數型態變數 */ num=2; /* 把num的值設為2 */ printf("I have %d dogs\n",num); /* 呼叫printf()函數 */ printf("You have %d dogs,too\n",num); system("pause"); return 0; } /* 將stdio.h這個檔案含括(include)進來*/ /*將stdlib.h這個檔案含括(include)進來*/ 定義了main函數,{}內為main的主體 C語言的註解。 C是以 " /* "及 " */ “ 記號來包圍註解文字. 說明: 1.stdio是standard input/output(標準輸入/輸出)的縮寫。C語言裡只要有關輸入與輸出的格式均是 定義在這個檔案裡。 2.因為system()函數是定義在stdlib.h裡,所以要include進來。 2. main() : 所有的C程式都是由main()開始執行,所執行的是{ }內的內容. 3. { }: 代表程式的開始與結束 4. /* */ : C程式的註解,以“/*”及“*/”記號來包圍註解的文字. 5. 分號(;) : 代表敘述(statement)的結束符號. printf函數會先把『%d』這個符號以num的值來取代。 再將雙引號內的文字輸出到螢幕上。
解 析 C 語 言 include指令與標頭檔: main()函數: 大括號、本體 在C語言裡,性質相近的格式定義會放在同一個標頭檔裡。 每ㄧ個C程式都必有一個main()函數,而且只能有一個。 所有C程式都是由main()函數開始執行,所執行的是{ }內的內容。 大括號、本體 以main()函數而言,左大括號({)與右大括號(})之間的程式碼就是main()函數的本體(body)。 本體內的每個指令敘述需以分號『;』做結尾。 1.stdio.h 與 stdlib.h 都稱為標頭檔(header file)。 2.例如:stdio.h 提供了輸入/輸出的函數 math.h提供了數學函數(如平方、立方、開根號)。
變數與常數 變數(variables): 是一個記憶體空間,主要用途是讓程式設計者,暫時存放一個數值,並於需要時可以隨時取用它或改變它. 變數一定要宣告過才能使用,否則將產生錯誤. 當我們宣告一個變數(variable)時,compiler會在記憶體內配置一個空間給此變數。 常數(constant)不同於變數,它的值是固定的。 例如:整數常數12400、浮點常數5.1
變數與常數 變數可用來存放資料。不同類型的資料需要不同型態的 變數來儲存。 使用變數前必須先宣告此變數所欲儲存的資料型態。 例如:班級的人數ㄧ定是整數,因此可利用整數型態的 變數來儲存班級的人數。 例如: int num; num=54; 宣告ㄧ個變數num為整數資料型態 num的值設為54
基本資料型態 C語言常用的四種資料型態: 例如: char name; /*宣告一個變數name為字元資料型態*/ char(字元) character int(整數) integer float(浮點數) single-precision floating point double(倍精度浮點數) double-precision floating point 例如: char name; /*宣告一個變數name為字元資料型態*/ int num; /*宣告一個變數num為整數資料型態*/ float grade; /*宣告一個變數grade為浮點資料型態*/
基本資料型態 下表列出了C語言中各種基本資料型態所佔的記憶體空間及範圍 不同的編譯程式裡,整數類的變數所佔的位元組可能會有所不同 資料型態 型態說明 位元組 表示範圍 整數 類型 long int 長整數 4 -2147483648 ~ 2147483647 int short int 短整數 2 -32768 ~ 32767 char 字元 1 0 ~ 255(256個字元) 浮點數 float 1.2E-38 ~ 3.E38 double 倍精度浮點數 8 2.2E-308 ~ 1.8E308 不同的編譯程式裡,整數類的變數所佔的位元組可能會有所不同
整數資料型態 在Dev C++中,int 與 long int 都佔了4個位元組. 在其它編譯器裡(如:Turbo C), int 可能只佔了2個位元組. 在宣告長整數或短整數變數時,可以省略 int . short int a=1000; 可寫成 short a=1000; long int b=2000 ; 可寫成 long b=2000; 若儲存的資料絕對不會出現負數的時候,可以使用無號整數來儲存 變數與常數的不同: 當我們宣告一個變數時,編譯程式會在記憶體內配置一快空間給它。不管變數的值如何改變,它所佔的記憶體空間永遠都一樣。 常數與變數不同,它的值是固定的,如整數常數1200,浮點常數123.4等。 整數常數的特性: 沒有小數點,帶符號其常數數值範圍為-32768~+32767(不帶符號,則為0~65535) 長整數(long)常數,帶符號其數值範圍為-2147483648~2147483647 C語言中,允許八進位整數的存在,只要是以零開頭的整數都被視為8進位數字。 C語言中,允許十六進位整數的存在,只要是以0x開頭的整數都被視為16進位數字。 資料型態 型態說明 位元組 表示範圍 unsigned long int 無號長整數 4 0 ~ 4294967295 unsigned int 無號整數 unsigned short int 無號短整數 2 0 ~ 65535
字元資料型態 字元型態在記憶體中佔有 1 個位元組,可用來儲存字元. 通常字元會被編碼,亦即替每一個字元編上一個整數碼,以方便處理這些字元. ASCII是較為人知的編碼系統(請參閱附A). 在 ASCII 編碼系統中,數字 0 到 127 分別代表不同的常用符號。 例如:英文大寫 A 的 ASCII 碼是 65 英文小寫 a 的 ASCII 碼是 97 符號 % 的 ASCII 碼是37 C語言可接受科學記號表示法的浮點數。 例如:若有一數字是123.456,我們可以寫成 1.23456e2 或 0.123456e3 附錄A
字元常數(Character Constants) 字元常數必須放在單引號裡面. 例如: ’A’ , ’a’ , ‘7’ , ‘*’ 也可以使用ASCII code來表示字元常數 範例: char ch=‘A’; 同等於 char ch=65; char ch=‘7’; 同等於 char ch=55; char ch=‘%’ 同等於 char ch=37; 在單引號之間的字元,我們都稱它是字元常數。例如:‘a’,’3’,’;’都是字元常數。 字元常數特性: 字元長度為1(不像字串長度為0~65535) C語言的字元型態與位元組整數是相容互通的 \xdd , 十六進位表示ASCII碼(每個d表示一數目),例如: \x42 B \ddd, 八進位表示ASCII碼(每個d表示一數目),例如: \101 A \0,代表null 41h:代表ASCII碼值十六進制(查表) chars are simply 1-byte integer. 例如: Upper = (lower - ‘a’) + ‘A’;
字串常數(String Constants) 字串常數是以ㄧ對雙引號包圍. 例如: “holiday” , “Hello” , ”Jane Wang” …等 “a” 會被視為包含了一個字元的字串. 在C語言中處理字元和字串的方式是不ㄧ樣的. 在單引號之間的字元,我們都稱它是字元常數。例如:‘a’,’3’,’;’都是字元常數。 字元常數特性: 字元長度為1(不像字串長度為0~65535) C語言的字元型態與位元組整數是相容互通的 \xdd , 十六進位表示ASCII碼(每個d表示一數目),例如: \x42 B \ddd, 八進位表示ASCII碼(每個d表示一數目),例如: \101 A \0,代表null 41h:代表ASCII碼值十六進制(查表) chars are simply 1-byte integer. 例如: Upper = (lower - ‘a’) + ‘A’;
變數宣告(Declarations) 宣告的語法如下: 資料型態 變數名稱; 例如: 變數命名原則: 資料型態 變數名稱; 例如: int num1; /* 把變數num1宣告為 int 型態 */ char a; /* 把變數a宣告為 char 型態 */ float f; /* 把變數f宣告為 float 型態 */ 變數命名原則: 1. 第一個字元必須是英文字母或底線 2. 大小寫代表不同的變數(如 : SUM, Sum, sum). 3. 可由字母,底線,阿拉伯數字所組成. 4. 不可為關鍵字(Keyword)或保留字(Reserve word). Ex: 不合法的識別字: 2A , good! , $money, case 變數宣告: 範例: int apples,oranges,cherries;
變數宣告(Declarations) Memory 若想同時宣告一個以上相同型態的變數, 則可用逗號(,)隔開. 例如 : 可寫成 int a; int b; int c; 可寫成 int a, b, c; 在變數宣告完成後,可使用等號運算子(=)替變數設值。 例如: int a; /* 把變數a宣告為int型態 */ a Memory a=3; 指定整數變數a的初值為3 3 C 語言 所有變數都要先行宣告,才能使用 若一個以上的變數擁有相同的型態,則可用逗號隔開 設定變數初始值 ex : int i =0; i 的始值為0 也可以在宣告的時候,替變數設值。 例如: 3 num int num=3; 指定整數變數num的初值為3
溢位 當數值的大小超過變數可以表示的範圍時,溢位(overflow)便會發生。 例如: int num= 2147483647; num=num+1; 解說: 設定num的初值為整數(integer)所容許的最大值(2147483647)。 當num的值加上1後,會發生溢位的現象。此時num的值 會變成- 2147483648 。
簡 單 的 C 程 式 範 例 #include<stdio.h> #include<stdlib.h> int main(void) { int sum; /* 宣告整數變數sum */ int a=5,b=9; /* a的值為5 , b的值為9 */ float avg; /* 宣告浮點變數avg */ sum = a + b; avg = sum / 2; printf(“The average = %f\n” , avg); system("pause"); return 0; } 將a與b的值相加,放到sum中 將sum的值除以2,放到avg中
運算子(Operator ) 運算式是C語言的其中一種敘述,運算式是由運算元(Operand)與運算子(Operator)所組成.運算元可以是常數,變數,甚至是函數;而運算子就是數學上的算數符號,如+,-,*,/等. 以運算式(num=a+10)為例,num、a與10都是運算元, 『=』與『+』則為運算子: num = a + 10 運算式 運算元 運算子 運算元 運算子 運算元
一元運算子與二元運算子 一元運算子 : 一個運算子若在計算時,只操作一個運算元,將稱為一元運算子. 二元運算子 : 如負號“-”,當數字前加上“-”,其值將變為負值,例如: -10. 二元運算子 : 一個運算子若在計算時,操作兩個運算元,將被稱為二元運算子. 例如:加號“+”在運算式“x+2”,操作左右兩邊的運算元,執行 x與 2的相加.
指派運算子(assignment operator) 運算子符號 : = 範例1: i = 14; 意義:將整數14指定給i這個變數. 範例2: i = i + 2; 當我們宣告一個變數時,compiler會在記憶體裡指定一塊空間來存放此變數的資料。 『=』符號是將右邊算式所得的數值或資料,指定到這塊記憶體空間裡。 意義:將 i 內存放的數值,從記憶體取出,加2以後,再指派回原來的記憶空間裡.
算術運算子 運算子符號 名 稱 結合規則 使用語法範例 當a=6,b=2時前述範例的 運算結果 + 加法 由左而右 a + b 6 + 2 = 8 - 減法 a – b 6 – 2 = 4 * 乘法 a * b 6 * 2 = 12 / 除法 a / b 6 / 2 = 3 % 取餘數 a % b 6 % 2 = 0
算術運算子 算數算子的運算規則: 1.運算子的優先順序 2.運算子的結合規則 範例 : 6 – 32 % 5 + 28 / 4 * 2 範例 : 6 – 32 % 5 + 28 / 4 * 2 6 – 2 + 28 / 4 * 2 6 – 2 + 7 * 2 6 - 2 + 14 4 + 14 18 優先順序 運算子符號 結合規則 1 *(乘), /(除), %(取餘數) 由左而右 2 +(加), -(減)
算術指定運算子 運算子符號 結合規則 原 式 簡化寫法 當a=6時前述範例的 運算結果 += 由右而左 a = a + 2 a += 2 8 原 式 簡化寫法 當a=6時前述範例的 運算結果 += 由右而左 a = a + 2 a += 2 8 -= a = a – 2 a -= 2 4 *= a = a * 2 a *= 2 12 /= a = a / 2 a /= 2 3 %= a =a% b a %= 2
比較運算子 運算子 符號 名 稱 結合規則 使用語法範例 當a=6,b=2時前述範例的 比較結果 = = 等於 由左而右 a = = b 6 = = 2 , 0(假) > 大於 a > b 6 > 2 , 1(真) < 小於 a < b 6 < 2 , 0(假) >= 大於或等於 a >= b 6 >= 2 , 1(真) <= 小於或等於 a <= b 6 <= 2 , 0(假) != 不等於 a != b 6 != 2 , 1(真)
邏輯運算子 運算子 符號 名稱 結合規則 使用語法 範例 說 明 && 且 由左而右 a && b 說 明 && 且 由左而右 a && b 當a,b兩者均為真時,結果為1(真),否則為0(假). || 或 a || b 當a,b兩者期中一個為真時結果就為1(真),當a,b都為假時結果為0(假). ! 反 由右而左 !a 當a為真時,結果為0(假),當a為假時,結果為1(真). AND與OR的真值表: AND T F T T F F F F -------------------------------- OR T F T T T F T F
邏輯運算子 當a=2, b=6時,下式的真假值 : ( ! ( a >= b ) ) && ( a == b ) 1 && 0 1 && 0 0 優先順序 運算子符號 結合規則 1 !(反) 由右而左 2 &&(且) 由左而右 3 ||(或)
遞增 , 遞減運算子 範例 : j = i ++; 表示先將i值給j後, i值再加1 運算子 符號 名 稱 結合規則 使用語法 範例 相當於 ++ 遞增運算子 由右而左 a++ 或 ++a a = a + 1 -- 遞減運算子 a-- 或 --a a = a – 1 範例 : j = i ++; 表示先將i值給j後, i值再加1 j = ++i; 表示先將i值加1後, 再傳給j
條件運算子 運算子 符號 名 稱 使用語法 範例 說 明 ? : 條件運算子 (條件式) ? 程式敘述1 : 程式敘述2 名 稱 使用語法 範例 說 明 ? : 條件運算子 (條件式) ? 程式敘述1 : 程式敘述2 當條件式判斷結果為1(真)時,將執行程式敘述1; 為0 (假)時,則執行程式敘述2.
型態轉型 C語言對於不同資料型態的算術運算式,它會自動轉變為 可包容性的型態,其轉型規則: 所有的字元型態和短整數型態能轉型為 int 所有的浮點型態float 能轉型為double 對所有成對的運算元,一律依下列的順序轉型: 一旦有長雙倍精確度long double之運算元,則其他運算元皆轉型為長雙倍精確度 一旦有雙倍精確度double 之運算元,則其他運算元皆轉為雙倍精確度 一旦有長整數型態long之運算元,則其他運算元皆轉為長整數型態 一旦有未帶正負號整數型態,則其他運算元皆轉為未帶正負號整數型態 範例: char ch; int i ; float f; double d; r=ch / i +f*d-(f+i); 問題: r應該宣告成何種資料型態? Ans: double 1. f 轉型為double , i 轉型為double f+i 為 double 2. ch轉型為int , i 為int ch / i 為int 3. f 轉型為 double,d 為double f * d 為double 4 .合併2. 3.的結果,則轉型為double( int + double) 5.合併4. 1.的結果,則為double( double + double) 6.故r 應宣告為double型態
型態轉型 cont1. 強迫式將運算式結果轉型: (型態) 運算式 或 (型態) 變數 型態:指C語言上的基本型態,前後用小括號圍住 例如: (型態) 運算式 或 (型態) 變數 型態:指C語言上的基本型態,前後用小括號圍住 例如: int i=7, j; float f; f=(float) i / 2; j=(int) f ; i 為整數, i 除以2後,強迫轉型為浮點型態,再傳給變數 f ,故變數 f 應宣告為浮點數 f 為浮點,強迫轉型為整數型態後,再傳給整數變數j 一個良好的程式設計師,應避免讓運算式自動轉型處理,才能確保程式的正確性與效率性
附錄A (Ascii碼)
附錄A (Ascii碼)
跳脫字元(Escape Sequences) \a alert (bell) character \\ backslash \b backspace \? question mark \f formfeed \' single quote \n newline \" double quote \r carriage return \000 octal number \t horizontal tab \xhh hexadecimal number \0 null character 倒斜線(\),代表“脫離”字元(或稱首前導標識),使得在解譯字串時脫離正常的方式,而使下一個字元具特殊意義 \b:到退一格 \f:跳頁 \n:換行 \r:倒回同列的開始處 \t:跳8個字元