國立清華大學資訊基礎教育 教學改進計畫 C語言基礎入門 2018/12/1
C語言的歷史 C語言的真正發展要追溯到1963年的ALGOL 60語言。 1963 ,劍橋大學將ALGOL 60 轉成 CPL(Combined Programming Language) 語言。 1967年,劍橋大學的Matin Richards 簡化了CPL成為BCPL語言。 1970年,美國貝爾實驗室Ken Thompson 修改BCPL成為B語言。 1973年,美國貝爾實驗室D.M.RITCHIE 以B語言為基礎發展出新的語言,以BCPL的第二個字為基礎,稱為C語言。 1983年,美國國家標準局語言標準化委員會對C語言進行了標準化, 稱為ANSI C。 2018/12/1
C語言的特色 一共有9種控制語句,32個關鍵字。 資料結構豐富: 除了基本的整數實數變數字元之外,也涵蓋結構變數,指標變數等。 語法限制不嚴格,設計彈性大。 應用範圍大,適合在各種作業系統上使用。 2018/12/1
基本程式1 程式碼: #include <stdio.h> main() { printf(“Hello World!\n”); } 程式執行後的輸出結果: Hello World! 2018/12/1
基本程式1說明 #include <stdio.h> stdio.h 是標準的輸入輸出標頭檔案 (Standard Input Output Header) ,它定義了輸入輸出的動作和所需的變數及一些巨集指令。 這一行程式並非由編譯程式所處理,而是在編譯前由前端處理程式(Preprocessor)處理,所以這段程式稱為前端處理程式指引 (Preprocessor Directives) 。 2018/12/1
基本程式1說明 main() { } printf(“Hello World!\n”); main()是C語言第一個會去執行的程式,“{”表示程式開始,“}”表示程式結束。 printf(“Hello World!\n”); printf是一個輸出函數(定義在stdio.h檔案裡面) ,這個函數可以印出雙引號“”的內容,而\n 是 new line,將目前游標移到下一列列首。 2018/12/1
基本程式2 程式碼: #include <stdio.h> main() { int a; a = 1; printf(“The a is : %d.\n”, a); } 程式執行後的輸出結果: The a is 1. 2018/12/1
基本程式2說明 int a; a = 1; printf(“The a is : %d.\n”, a); int 為 C語言關鍵字 (Key words)之一,int表示integer之意,即宣告a這個變數的資料型態為整數。 a = 1; a這個變數我們又稱為 識別字 (Identifiers) ,是由程式設計師自己定義的,然而有以下的限制: 變數名稱需為英文字母或底線字元( _ )或阿拉伯數字組成。 第一個字只能為英文字母或底線字元( _ ) 。 變數名稱不能過長(傳統只允許8字元, turbo C可到32字元) 。 變數有分大小寫,ABC和abc是不同的兩個變數。 printf(“The a is : %d.\n”, a); %d 是代表 a 變數的值以十進位 (decimal) 方式呈現。 2018/12/1
C語言的關鍵字(共32個) asm double goto struct auto else if switch break end int typedef case entry long union char enum register unsigned continue extern short unix default float sizeof void do for static volatile PS. 以上為一般C編譯器所提供的關鍵字 不同的編譯器會有其他額外的關鍵字 2018/12/1
識別字與關鍵字 關鍵字如上頁表所列 識別字有兩種 程式語言的規定用字,使用者不可用來當變數,資料型態或函數名稱 使用者自己定義 程式庫定義 如 char (宣告字元) 識別字有兩種 使用者自己定義 如ABC_123, test1等 程式庫定義 如printf, scanf等 2018/12/1
C的常數宣告 const int a = 1; 在執行過程中 a 為一個故定不變動的整數,其值為1 常數的資料型態可為整數,浮點數,字元。 整數常數通常介於 -32768 ~ 32767 , 佔用2bytes ,而長整數可到4 bytes 。 浮點常數數通常為8 bytes ,表示法如下: 12.34e5 (12.34* ) 1.45E-4 (1.45* ) 字元常數通常是由單引號括起來 : ‘a’ 。 2018/12/1
C語言變數宣告方法 short a, int b, long c; unsigned d, unsigned int e; 整數型態一般而言有三種 : short , int , long (佔記憶由小至大排列) 。 unsigned d, unsigned int e; unisgned表示只有正數沒有負數可搭配以上整數型態宣告,如unsigned long x; float f, double g; float浮點數, double倍精數,後者的有效位數和精確度皆高於前者 (通常為4 bytes VS. 8 bytes) 。 char h; 字元: 資料存的是內碼值 ,如字元 ‘A’ 的ASCII內碼為65。基本上字元是以數字來儲存的,所以也可用來計算,只不過它能表示的數值較小而已。 2018/12/1
測試變數的記憶體空間 - sizeof 2018/12/1
執行結果 平台 : WinXP + Visual C++ 6.0 2018/12/1
void 資料型態 一開始C語言的每一個函數需要傳回值,然而有些函數並不需要傳回值,所以ANSI定義了void 來代表這個函數它不需要任何回傳值,所以void有人稱之為虛擬型態。 void main(void) { printf(“test!\n”); } int main() int a = 10; return a; 2018/12/1
printf 的使用 程式碼: 執行結果: 2018/12/1
printf資料型態的常用格式對照表 資料型態 %c 字元 %s 字串 %d 有號十進位整數 %e 浮點(指數表示) %f 浮點(小數點表示) %g 浮點(最精簡表示) %u 無正負號之十進位整數 %ld 有號長整數十進位數 PS. 尚有其他控制字元,因為不常使用,故請讀者自行參考C語言書籍或相關網頁, 在此不再贅述。 2018/12/1
printf 欄位寬度設定 C語言允許使用者自行設定每項資料所需的位數,其方法是在%符號和控制字元間加上列印時所需的寬度。 例如: 字元變數 ch=‘A’ ,寬度為3 ,採向右靠齊,則指令應為: printf(“%3c”, ch); 整數變數 a = 100 , 寬度為5 ,採向左靠齊,則指令應為: printf(“%-5d”, a); 說明: C語言對於輸出的資料型態皆以一段字串的方式傳送到螢幕上,但傳輸之資料其資料型態都不同,故需有特定的控制格式來表示不同的資料型態 f=3.14159 共佔7位 小數點4位,第4位四捨五入 向右靠齊(-7.4f 向左靠齊) 若寬度給的不夠, 系統仍照印全部資料 小數點若欲印出比實際的,則補0 2018/12/1
scanf 使用 scanf與printf是相對的,前者為輸入函數,後者則是輸出函數。 在格式方面也是類似的: scanf(“%c”, &c); %等待輸入一個字元 c scanf(“%d”, &d); %等待輸入一個整數 d scanf(“%f”, &f); %等待輸入一個浮點數 f scanf(“%d %f”, &d, &f); %等待輸入兩個變數,整數,浮點數 scanf(“%s ”, str); %輸入一個字串 (字串變數前通常‘不’需要加上 ‘&’ 符號) 2018/12/1
基本運算式和運算符號 加減乘除和取餘數 邏輯符號 : ‘+’ 、 ‘-’ 、 ‘*’ 、 ‘/’、 ‘mod’ A = 2 *3 (A = 6) C = 5 mod 3 (C = 2) 邏輯符號 : and : ‘&&’ or : ‘||’ if, else Example: if (a>10) && (b<3) printf(“OK!\n”); else Printf(“NO!\n”); 2018/12/1
基本運算式和運算符號 大於等於小於 不等於 相加後指定 > = = < != += A += 3 (相同於 A = A +3) 2018/12/1
控制結構 if-else 括號 { } 內的程式碼可不只一行,假如只要執行一行程式碼,則括號可以省略不寫。 if (condition) { } else 括號 { } 內的程式碼可不只一行,假如只要執行一行程式碼,則括號可以省略不寫。 condition通常都為邏輯判斷,如 a==b or c>9等。 2018/12/1
if- else 請問這兩者的執行結果有何不同? 2018/12/1
if – else 練習 輸入一個數字,輸出為這個數字的平方: PS. 數學函數需要引用math.h檔案, 可用數學函數有 exp, sqrt, floor, round等 可自行查閱相關help 2018/12/1
巢狀 if if (a>3) if (b>3) printf(“a and b are both greater than 3!\n”); else printf(“b is not greater than 3!\n”); 以下範例的執行結果與上面相同 : 因為 else是找最近的if 作對應 2018/12/1
switch-case if-else 程式: switch case 程式: 2018/12/1
switch-case 解說 架構: switch (op) { } case X : ……………; break; default: ……………; } op 可以是 實數 或者 字元,在ANSI C op不支援字串 case 後面加上break; 若不加break ,則程式會一路比下 去,所得的結果就非我們想要的了,default則設定當 比較所有pattern都不符合時要執行的步驟。 2018/12/1
Homework Exercise 設計一個程式,乖乖包數與折價關係如下: 1~5包,原價 6~10包以內,原價九折 11~20包以內,原價八折 21包以上,原價七折 一包原價10元,輸入購買數量,則印出所需總價。 2018/12/1
迴圈設計 C語言提供3種迴圈設計方法: for loop while do-while 2018/12/1
for loop 格式 for (i=0; i<5; i++) i ++ 相當於 i = i + 1 or i+=1 所以上式可改寫成 執行迴圈的動作 起始值 判斷跳離迴圈條件 2018/12/1
for loop 兩層迴圈可印出九九乘法表: 2018/12/1
for loop 無窮迴圈 格式: 例子: for (; ;) for (n=1; ;n++) { printf(“%d\t”, n); 無窮迴路一直執行 for (n=1; ;n++) 無窮迴路每執行一次n就加一 例子: { printf(“%d\t”, n); if (n>5) break; } 此程式可印出 1 2 3 4 5 2018/12/1
while 迴圈 格式: While (op) { //程式碼 } op為 邏輯判斷式,如 a > 1 例如: while (a > 3) a = a – 1; 2018/12/1
while 迴圈 請問上述例子的目的是求這兩個正數的什麼? 2018/12/1
while 無窮迴圈 格式: while (1) { //程式碼 } 2018/12/1
do-while 格式: do { //程式碼 }while (op) 2018/12/1
do-while example scanf(“%d%*c”, &i); 和 scanf(“%c%*c”, &t); 其中 補上 %*c 是為了配合輸入後 按下 enter 鍵。 2018/12/1
副程式 通常程式大到某種程度以上,可能會有些重複的程式碼,這些重複程式碼雖然不至於浪費運算時間,但卻讓其他程式設計師叫不容易閱讀, 而且結構顯得凌亂。為了讓程式碼更有結構和可讀性,通常我們會設計副程式。 一般格式的例子: 副程式 int test(int x, int y) { int z; z = pow(x, y) * 4; return z; } 2018/12/1
Homework Exercise 2 設計一個程式,輸入一個正整數N,計算第N項之費氏級數: F(0) = 0; F(1) = 1; F(N)=F(N-1)+F(N-2); 2018/12/1
副程式 副程式和主程式搭配 (兩種撰寫方式) 2018/12/1
副程式 請用副程式的做法設計下列圖形表示 * * * * * * * * * * * * * * * 2018/12/1
陣列 由於單一變數的彈性太小,倘若程式中需要多個變數來儲存資料,而且這些變數中是有關係性的,那麼採用陣列的資料結構是比較好的做法。 例如設計一個樂透程式,需要儲存6組正整數號碼,程式宣告可以為 int a, b, c, d, e, f; 也可以為 int number[6]; 第一種的變數較為繁雜,而且程式寫作限制較大,第二 種宣告表現略為簡潔,程式寫作彈性大。 2018/12/1
陣列界線檢查 C語言與高階語言不同的是,它並沒有做任何陣列的界線檢查,也就是說當程式存取超過陣列界線的值時,就會發生不可預期的錯誤,而且這樣的程式在編譯時期並不會被偵測出來,這是為了考量C語言在執行上的效率,所以程式設計師必須自行小心的存取陣列所規範的值。 2018/12/1
陣列表示 整數一維陣列表示 浮點數二維陣列表示 在C語言中,所有多維陣列其實在記憶體擺放都是以一維來呈現的,如一個 2 x 2的矩陣: int a[10]; %從a[0] ~ a[9] 共 10個elements 初始值設定: int a[10] = {1,2,3,4,5,6,7,8,9,10}; 浮點數二維陣列表示 float a[2][3]; % 2 x 3 的 matrix 從a[0][0]~ a[2][3] 。 在C語言中,所有多維陣列其實在記憶體擺放都是以一維來呈現的,如一個 2 x 2的矩陣: 在記憶體中的排列方式則是 A[0][0] A[0][1] A[1][0] A[1][1] A[0][0] A[0][1] A[1][0] A[1][1] 2018/12/1
Exercise 請設計一個 “簡單的”支援 2 x 2 的正整數矩陣相乘的程式,例如 輸入方式為 : 第一個矩陣的第一列 : 2 3 第一個矩陣的第二列 : 1 4 第二個矩陣的第一列 : 1 3 第二個矩陣的第二列 : 0 2 輸出結果: 矩陣的第一列 : 2 12 矩陣的第二列 : 1 11 2018/12/1
基本字串簡介 C語言並沒有提供字串的基本資料型態,而是由字元陣列來處理。如下例: char string[5] = “ABC”; 在記憶體中的位置 字串是一維的字元陣列,而字串陣列則是一個二維的字元陣列,每一列代表一個字串。如下例: char week[7][10] = {“Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”, “Sunday”}; A B C \0 ? 2018/12/1
字串基本處理 讀取字串 char abc[10]; scanf(“%s”, abc); //不需在abc前面加上 & 字串處理的基本函數 strcmp strcpy strcat strlen 以上均可 help string 查知其用法 細節請參閱 C語言進階 2018/12/1
Homework Exercise 4 設計一程式,讓使用者輸入一字串(不超過30字元),之後將該字串以反序且大小寫互換的方式印出來。 例如:輸入”Hello”後,程式顯示出”OLLEh”。 2018/12/1
參考資料 網頁: 書籍: C語言簡介 : http://yach.idv.tw/aky/cth/cpg.htm http://zh.wikipedia.org/wiki/C%E7%B7%A8%E7%A8%8B%E8%AA%9E%E8%A8%80 書籍: C語言詳論 : Jeri R. Hanly等著, 潘育群 蔡明志譯 Turbo C 程式設計入門 : 老園丁工作室 2018/12/1