第二章 C 語言基本概述 C 語言的基本語法關鍵字 vs. 識別字各種程式錯誤提高程式的可讀性 1
2.1 簡單的例子 簡單的 C 程式 下面的程式碼可印出兩行字串 : 2
2.2 解析 C 語言 含括指令與標頭檔 (1/4) #include 是前置處理器的指令 #include 稱為含括指令 語法為 #include < 標頭檔 > 前置處理器以標頭檔 (header file) 的內容取代 #include < > 因為是在編譯前執行, 所以稱為 " 前置 " 處理器 3
2.2 解析 C 語言 含括指令與標頭檔 (2/4) 含括動作前後的比較 : #include <stdio.h> #include <stdlib.h> 4
2.2 解析 C 語言 含括指令與標頭檔 (3/4) 不含括 stdio.h 或 stdlib.h 標頭檔也可以編譯? 標頭檔內是工具函式的宣告, 例如 printf() 在 stdio.h 中, system() 在 stdlib.h 中, 程式裡有使用到的工具函式才需要含括對應的標頭檔案 某些編譯器會將常用的標頭檔自動含括 有些編譯器會出現警告訊息, 並自動含括一些標頭檔 早期的 C 編譯器沒有適當宣告時有一些預設的法則 ; ANSI C 的編譯器如果沒有含括所使用函數的標頭檔, 所用到的工具函數沒有適當的宣告時即無法編譯 5
2.2 解析 C 語言 含括指令與標頭檔 (4/4) 標頭檔的內容 : 6
2.2 解析 C 語言 函數 (function) main() main() 函數是你的程式執行的起點 每個 C 程式必須有一個 main() 函數, 而且只能有一個 函式 7
2.2 解析 C 語言 程式區塊及本體 程式區塊與本體的範圍 : 8
2.2 解析 C 語言 變數的使用 宣告方式 : 變數是 CPU 執行演算法過程中存放資料的地方 int num; /* 宣告名稱為 num 的整數變數 */ int a,b,c; /* 宣告 a,b 與 c 為整數變數 */ 同一敘述宣告三個變數 float sum=0.0; /* 宣告浮點數變數 sum, 並設值為 0.0 */ 變數裡存放的資料型態 : char 字元, 如 'A' '2' 與 '&' 等 int 整數 變數的初始化 long 長整數 short 短整數 如 12-27 等 float 單精度浮點數 double 倍精度浮點數 如 12.762-37.483 等 9
變數的使用 Integer Type short unsigned short 1 int 1 unsigned int long unsigned long 2.2 解析 C 語言 Range in Typical Microprocessor Implementation -32768 ~ 32767 0 ~ 65535-2147483648 ~ 2147483647 0 ~ 65535-2147483648 ~ 2147483647 0 ~ 4294967295 Floating-Point Type float double 4 long double 2 Approximate Range 3 10-37 ~10 38 10-307 ~10 308 10-4931 ~10 4932 Significant Digits 1: machine, operating system, and compiler dependent 2: not all numbers in the range can be represented precisely 3: The mass of one electron is approximately 10-27 grams. Diameter of the Milky Way galaxy in kilometers is approximately 10 23 kms. 4: long double is the same as double for VC6 and VC2005 6 15 19 10
11 ASCII 字元內碼表 12 11 10 9 8 7 6 5 4 3 2 1 0 x n d Z P F < 2 ( RS DC4 LF NUL 0 y o e [ Q G = 3 ) US NAK VT SOH 1 z p f \ R H > 4 * SP SYN FF STX 2 { q g ] S I? 5 +! ETB CR ETX 3 r h ^ T J @ 6, " CAN SO EOT 4 } s i _ U K A 7 - # EM SI ENQ 5 ~ t j ` V L B 8. $ SUB DLE ACK 6 DEL u k a W M C 9 / % ESC DCL BEL 7 v l b X N D : 0 & FS DC2 BS 8 w m c Y O E ; 1 ' GS DC3 HT 9 2.2 解析 C 語言 2.2 2.2 2.2 解析 C 語言解析 C 語言解析 C 語言
2.2 解析 C 語言 變數的命名規則 變數名稱可以是英文字母 數字或底線 名稱中不能有空白字元 第一個字元不能是數字 不能使用到關鍵字 intel_4x /* 正確 */ _AMD /* 正確, 變數的第一個字母可以是底線 */ 2dos /* 錯誤, 變數的第一個字母不能是數字 */ my dogs /* 錯誤, 變數不能有空格 */ goto /* 錯誤, 變數不能是 C 語言的關鍵字 */ 12
2.2 解析 C 語言 變數的設值方式 宣告的時候設值 ( 初始化 ) int num = 2; /* 宣告變數, 並直接設值 */ 宣告後再設值 int num1,num2; /* 宣告變數 */ char ch; num1 = 2; /* 將整數變數 num1 的值設為 2 */ num2 = 30; /* 將整數變數 num2 的值設為 30 */ ch = m ; /* 將字元變數 ch 的值設為 'm' */ 13
2.2 解析 C 語言 Strong type Language Weak-type Language: 變數使用前不需要宣告, 同一個變數裡可以放不同型態的資料 Strong-type Language: 變數在使用之前一定要宣告, 並且只能存放指定型態的資料, 限制嚴格的好處如下 : 避免變數名稱打錯 ( 如數字 0 與英文字母 O) 增加程式的可讀性 便於程式碼的維護 除錯容易 14
格式化的輸出函數 printf() 2.2 解析 C 語言 利用 printf() 函數在螢幕上印出字串 : 15
2.3 識別字及關鍵字 識別字 (identifier) 識別字是用來命名變數或函數的文字 識別字 16
關鍵字 (keyword)(1/2) 關鍵字是 C 語法的基本元素 2.3 識別字及關鍵字 關鍵字 (keyword) 或稱為保留字 (reserved word) 17
關鍵字 (keyword) (2/2) 下表為 C 語言的關鍵字 2.3 識別字及關鍵字 18
2.4 除錯 程式錯誤的分類 語法錯誤 (syntax error) 程式含有不合語法的敘述, 它無法被編譯程式翻譯 語意錯誤 (semantic error) 語意錯誤 ( 又稱邏輯錯誤 ), 就是程式的執行結果與寫程式者的預期不同 19
2.4 除錯 語法錯誤 下面是有語法錯誤的程式 : 20
2.4 除錯 語意錯誤 下面是語意錯誤的程式 : /* prog2_5a, 語意錯誤的程式 */ #include <stdio.h> #include <stdlib.h> 語意錯誤通常是你以為電腦會做的, 和電腦實際做的之間有落差. 誤會一場 int main(void) { int num = '2'; /* 宣告整數變數 num, 並設值為 '2' */ printf("i have %d dogs.\n", num); system("pause"); return 0; } /* prog2_5a OUTPUT --- I have 50 dogs. ---------------------------------*/ 21
提高程式的可讀性 (1/4) 列印程式碼時請用固定字距 2.5 提高程式的可讀性 22
提高程式的可讀性 (2/4) 2.5 提高程式的可讀性 列印程式碼時使用非固定字距, 且斜體字的程式碼, 較難閱讀 23
提高程式的可讀性 (3/4) 程式碼縮排與對齊, 分隔不同的細節層次 2.5 提高程式的可讀性 24
提高程式的可讀性 (4/4) 註解有助於程式的閱讀與偵錯 2.5 提高程式的可讀性 25
C 是 Free Format 的語言 #include<stdio.h> #include<stdlib.h> int main(void){ printf("helloworld!\n"); system("pause"); return 0; } #include<stdio.h> #include<stdlib.h> int main(void){printf("helloworld!\n");system("pause");return 0;} int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++ Hell\ oworld!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);} The International Obfuscated C Code Contest http://www.ioccc.org/years.html 26
Winner of the international C obfuscation contest in 2001 #include <unistd.h> #include <curses.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <sys/time.h> #define o0(m,w) mvprintw(w,m?m-1:m,"%s%s ",M?" ":"",_) #define O0(M,W) M##M=(M+=W##M)-W##M #define l1(m,w) M.tv_##W##sec #define L1(m,M,l,L,o,O) for(l=l;l--;)((char*)(m))[o]=((char*)(m))[o] #define I1 ll,(struct sockaddr*)&il #define i1 COLS #define j LINES #define L_ ((j%2)?j:j-1) fd_set I;struct socka\ ddr_in il;struct host\ ent*li; struct timeval IL,l;char L[9],_[1<<9] ;void (int ){_[ --]=+0;if( ++ ) (-- );_ [ ]='=';}double o,oo=+0,oo=+0.2; long O,OO=0,oO=1,ii,iI,Ii,Ll,lL, II=sizeof(il),Il,ll,LL=0,i=0,li, li;int main(int\ il,char *Li[]){\ initscr();cbreak ();noecho();nonl (); (li=i1/4); _[0]='[';_[lI-1] =']';L1(&il,&_,\ II,O,+O,+lI);il. sin_port=htons(( unsigned long)(\ PORT&0xffff));lL =l_;if(il=!--il) {il. sin_addr.\ s_addr=0;bind(i1,ii);listen(ll,5 );ll=accept(i1,& II);}else{oO-=2; LI=gethostbyname (Li[1]);L1(&(il. sin_addr),(*li). h_addr_list[0],\ LI->h_length,iI, ii,ii);(*(&il)). sin_family=(&(*\ LI))->h_addrtype ;connect(i1,ii); }ii=ii=(o=i1*0.5 )- li/2;ii=l_-1;o =li=l_*0.5;while (_){mvaddch(+oo, oo,' ');o0(ii,ii );o0(ii,il-=il); mvprintw(li-1,il,"%d\n\n%d",i,ll );mvhline(li,+0, '- ',i1);mvaddch( O,o,'*');move(li,Il);refresh();\ timeout(+speed); gettimeofday(&il,+0);ll=getch(); timeout(0);while (getch()!=err);\ if(ll=='q'&&il)\ write(ll,_+1,1); if(ii>(ll=0)&&ll ==','){write(ll, _,-(--Il));}else if(ll=='.'&&ii+\ li<i1){write(ll, _+li,++il);}else if(il!il)write (ll,_+li-1,4-3); gettimeofday(&l, 0);II=((II=l1(IL,)+(l1(l,u)-=l1( IL,u))-l1(l,)+(\ l1(l,)-=l1(il,)) )<0)?1+II-l1(l,) +1e6+(--l1(l,)): II;usleep((II+=\ l1(l,)*1e6-speed *1e3)<0?-II:+0); if(ll=='q'&&!il) break;fd_zero(&i );FD_SET(lL,&I); memset(&*&il,ll, sizeof(l));if((\ Ll=select(lL+1,& I,0,0,&IL)));{if (read(ll,&l,ll+1 )){if(!*l){ll++; }else if(*l==ll[ _]){ll--; }else\ if(*(&(*l))==1[_ ]){break;}}else{ break;}}o0(o,o); O0(O,o);if(o<0){ o*=-1;oo*=-1;}if (o>i1){o=i1+i1-o ;Oo*=-1;}if(o>=( Ii+=ll)&&O<1&&oO <0&&o<Ii+lI){O=2 ;oo=~-- oo;oo+=ll *4e-1;}if(O<0){O =ii;ll++;}if(o>= (ii+=il)&&o>ii-1 &&oo>0&&o<ii+li){o=ii- 2;oO=~--oO;Oo+=Il*4e-1 ;}if(+o>+ii){o- =O;i++; }}endwin();return(0);} Network based Pong game 27