Presentation is loading. Please wait.

Presentation is loading. Please wait.

第一篇 C語言基礎入門應用程式設計 本篇內容精緻實用、由淺入深、並參佐實作範例。為初學者作基礎入門學習、易學易懂、且建立實作能力。特別適用於各級學校、作為教學教材。

Similar presentations


Presentation on theme: "第一篇 C語言基礎入門應用程式設計 本篇內容精緻實用、由淺入深、並參佐實作範例。為初學者作基礎入門學習、易學易懂、且建立實作能力。特別適用於各級學校、作為教學教材。"— Presentation transcript:

1 第一篇 C語言基礎入門應用程式設計 本篇內容精緻實用、由淺入深、並參佐實作範例。為初學者作基礎入門學習、易學易懂、且建立實作能力。特別適用於各級學校、作為教學教材。

2 第一章 導述 本章目的在導引您迅速窺得C之架構全貌。 輕鬆了解、進而寫出C語言程式。至於細節道理、將於爾後各章節作有系統的介紹。

3 1-1 第一個C程式 1-2 變數(Variables) 與 運算(Arithmetic) 1-3 For 敘述式 1-4 符號常數(Symbolic Constants) 1-5 Unix(or Linux)系統中一些應用程式 1-6 陣列(Arrays) 1-7 函數程式(Function) 1-8 傳值參數(Argument—Call by Value) 1-9 字元陣列(Character Arrays) 1-10 區域觀念(Scope):外部變數(External Variables) 1-11 實作範例

4 1-1 第一個C程式 寫電腦程式時、我們會面臨 (1)程式寫在那裡(Create program text)? (2)如何編譯(Compile)? (3)如何執行(Run)? 本書鼓勵讀者、以Unix/Linux為研習環境,如果讀者沒有Unix/Linux系統之環境,或無需演練本書網路程式,為了簡單方便、亦可使用Turbo C編譯器,有關執行步驟、請參酌附錄B。 若讀者、對Unix (Linux)不熟習。可先閱讀演練本書 “附錄 A”。在很短時間內、您將能在Unix (Linux)系統內、操作自如。本節將以Unix/Linux環境、導引讀者演練您的第一個C程式。

5 1-2 變數(Variables) 與 運算(Arithmetic)
變數宣告型態有: int 為整數(Integer) float 為浮點數(Floating point) char 為字元(Character) short 為短整數(Short integer) long 為長整數(Long integer) double 為倍精浮點數(Double precision floating point) 其他將在爾後詳述。

6 1-3 For 敘述式 for迴圈之三個條件參數(於本節範例中): fahr = 0、是迴圈之起始條件、僅執行一次。
fahr = fahr + 20、每次執行迴圈一次、即再設定fahr一次,每次加20。

7 1-4 符號常數(Symbolic Constants)
在程式中、總是有一些特別數值(Magic Number)。為了增加可讀性與記憶性,可於函數式前、以 “#define” 先行定義之。

8 1-5 Unix/ Linux系統中一些應用程式
在Unix/ Linux/系統中、我們可看到許許多多精彩的C程式。本節僅將一些有關字元之簡單程式、摘錄供您參考了解。至於細節詳述、留待爾後各章節再述。

9 1-6 陣列(Arrays) 陣列宣告,其元素是ndigit[0]、ndigit[1]、‧‧‧、ndigit[9]。

10 1-7 函數程式(Function) 在C程式語言、函數程式部份、可將繁長之程式作有條理的分解,增加其可讀性與方便性。
並非所有C程式都要有傳回值,若無傳回值、即如其他程式語言所稱之 “副程式(Subroutine)”。Unix/ Linux C均稱之為函數程式(Function),並不強調副程式(Subroutine)此名稱。

11 1-8 傳值參數(Argument—Call by Value)
在一般語言程式設計、主程式(main)與函數程式(function)間之參數(argument)傳遞、有(1)参數傳值(call by value) (2)參數傳址(call by reference) (3)參數拷貝結果(copy restore) (4)参數傳名(call by name)。 C語言則僅為 “参數傳值(call by value)”。當主程式呼叫函數程式時、參數值僅可從主程式傳遞至函數程式,不可從函數程式直接傳回至主程式。

12 1-10 區域觀念(Scope):外部變數(External Variables)
於1-9節上述程式中、main程式內的變數(如line、save等)、因其是在main區域內作的宣告,故僅提供在main之區域(Scope)內使用,其他函數程式則不得直接使用。同理、在其他函數內宣告的變數、也僅提供於該函數區域內使用。例如、在getline內宣告的i與在copy內宣告的i、彼此間是毫無關係的。這些當地變數(Local Variables)是隨所屬函數之存在而存在,即當所屬函數被呼叫時、其內所宣告的變數才隨之產生,當所屬函數執行結束時、其內所宣告的變數也隨之消失。我們可稱之謂 “自動變數(Automatic Variables)”,相較於其他程式語言稱之為 “機動變數(Dynamic local Variables)在名稱上有所不同,我們將於第四章解述。 本節下述程式、將以 “全域變數(Global Variables)” 比較 “自動變數(Automatic Variables)”。其功能與1-9節之例程完全一樣。 宣告全域變數(Global Variables)於各函數之外端(Extern),各函數程式共用存取,也不隨函數之存在而存在,並取代參數在兩函數間之傳遞功能。

13 第二章 資料型態(Types),運算元(Operators) 和運算式(Expressions)
C程式的變數和常數、須在宣告中、歸類於適當之型態,稱為資料型態(Type)。運算元(Operator)是運算機制,如 + - * / 等。運算式(Expression)是將常數、變數、運算元、依其運算意義、產生新值。

14 2-1 變數名稱(Variable Names)
C程式之變數名稱、有下列不可越軌之限制: (1) 名稱由字元和數字組成,但數字不得置於最前端。 (2) 英文字母大小寫、代表不同之名稱。通常變數用小寫;符號常數用大寫。 (3) 名稱長度不超過八個字元。 (4) 凡已被系統採用之保留字、要避讓。 (5) 當設定名稱時、要考量其可讀性與代表性。

15 2-2 資料型態(Data Types) Unix (or Linux)系統中、變數型態種類並不繁雜。一般計有:
char 字元,長度為本機系統、含恃一個字元的位元數。(一般電腦均是8個位元,但Honeywell 6000 是9個位元)。 int 整數,長度為本機系統、含恃一個常用數字的位元數。(一般電腦是16個位元,但Honeywell 6000 是36個位元,IBM 370是32個位元)。 float 浮點數,含有小數點的數。長度為本機系統、含恃一個常用浮點數的位元數。(一般電腦是32個位元,但Honeywell 6000 是36個位元)。 double 倍精浮點數。(一般電腦是64個位元,但Honeywell 6000 是72個位元)。 為增加效果性、另增列 short int 與 long int。其長度分別為16 與 32 位元。

16 2-3 常數(Constants) 整數常數(int)、小數常數(float)己於前節解釋。尚有指數常數(float)如 e-7或 0.12E3。 八進位整數是以“零(0)”前導、如0123。十六進位整數是以“零(0)x”前導、如0x123。 一些操作字元常數、如 \n(新行列new line)、\t(空格tab)、\0(無null)、\\(返程backslash)、\’(單引號single quote)、等等,看似兩個字元、實以一個字元計之。 字串常數如“abcd123”、須以雙引號(“ ”)括含。在技術上、字串是一種陣列,且編譯程式會自動加置\0於其尾端。‘x’相較於“x”、前者是一字元、後者是一字串、且尾端有\0。

17 2-5 數學運算元 常用數學運算元有 加(+)、減(-)、乘(*)、除(/)、餘數(%)、負號(-)。
整數相除,設若x為整數、y為整數,則 餘數(x%y) 亦為整數,小數部份自動沖失。%運算元將不援引float或double。 運算元之運算優先次序以正負號(+)(-)最優先;其次是乘(*)、除(/)、餘數(%);再其次是加(+)、減(-)。若同級者同時出現時、式中位置在左端者優於在右端者(Left to Right)。在本章結尾、將展列一圖表,提供參照。

18 2-6 關係運算元(Relational Operators) 與 邏輯運算元(Logical Operators)
關係運算元、有 “ >、>=、<、<=” 與 “==、!=”,其運算優先次序為、後組優於前組。 邏輯運算元、有 “&&” 與 “| |”、其運算優先次序為、前者優於後者。 “關係運算元” 之運算優先次序優於 “邏輯運算元”。 設有一式: (i < lim-1) && ((c = getchar()) != ‘\n’) && (c != EOF) 可改為: i < lim-1 && (c = getchar()) != ‘\n’ && c != EOF 因“關係運算元” 之運算優先次序優於 “邏輯運算元”。

19 2-7 轉型(Type Conversions)
當運算式中之各運算資料(Operands)為不同型態時、其中部份資料會自動轉型、成為一致相同的資料型態、如此才可完成運算。

20 資料轉型、可以下列三大法則轉換之: 1, 以下列規則與優先次序作轉換: (1), char、short 轉型至 int; float轉型至 double。 (2), 然後、若有任一double、則其他均轉為double、結果亦是double。 (3), 否則、若有任一long、則其他均轉為long、結果亦是long。 (4), 否則、若有任一unsigned、則其他均轉為unsigned、結果亦是unsigned。 (5), 否則、運算資料必為int、結果亦是int。 2, 除此之外、等於符號(=)之右端運算資料、隨著其左端運算資料之型態而轉換 3, 最後、可以 (type_name) expression 強力轉型

21 2-8 增加1(Increment) 與 減少1(Decrement) 運算元
C提供兩組特殊運算元 “+ +” 與 “- -”。前者是將運算資料加1、後者是將運算資料減1。位置有置於前端(Prefix)、如 ++n、--n;有置於後端(Postfix)、如 n++、--n。 ++n指當使用n前、先將n加1;n++指當已使用n後、才再將n加1。--n n—亦同。設 n = 5 則於 x = ++n 中、x之值是6;於 x = n++ 中、x之值為5。

22 2-9 位元邏輯運算元(Bitwise Logical Operators)
C提供位元邏輯運算元如下,但這些邏輯運算元、無法作用於float或double: & 位元AND | 位元inclusive OR ^ 位元exclusive OR << 位元左移 >> 位元右移 ~ 1’ 補數

23 2-10 指定運算元(Assignment Operators) 與 運算式(Expression)
可設置通用式如下: e1 op= e2 (其意為 e1 =( e1) op( e2)) 其中e1、e2是運算式;op有 +、-、*、/、%、<<、>>、&、^、|;op= 為指定運算元。

24 2-11 條件運算式(Conditional Expressions)
條件運算式如下: if (a > b) z = a; else z = b;

25 2-12 運算優先次序(Precedence and Order of Evaluation)
Precedence Operator ( ) [ ] -> . ! ~ (type) * & sizeof * / %4+ - << >> < <= > >= == != & ^ | && | | ?: = += -=. ,

26 第三章 程式流程控制(Control Flow)
對任何一種程式語言而言、程式流程控制(Control Flow)是安排運算式之執行次序、並使其順利完成執行。C之某些程式流程控制形態、我們已在前述章節範例見識一些,本章將再完全針對這個項目、作精僻解述。

27 3-1 敘述式(Statements) 與 區塊(Blocks)
運算式、如 x = 0 或 i++ 或 printf(“abce\n”)等。若在每一式尾端加上分號,即改稱作敘述式、如 x = 0; 或 i++; 或 printf(“abce\n”);。在C、分號是敘述式之結束符號;相較於其他如Algol類語言、分號是分隔符號。 括弧{ }、是將一組宣告變數(Declarations)和敘述式(Statements)、組括在一起、稱之謂組合敘述式(Compound Statement)、或謂區塊(Block)。 括弧{ }、用於函數程式區塊;及用於 if、else、while、for 等區塊。分號不得置於括弧{ }之右端。

28 3-2 if-else 敘述式 if-else敘述式是用於做決策,其語法如下: if (expression) statement-1

29 3-3 else-if敘述式 語法結構如下: if (expression) statement else if (expression)

30 3-4 switch 敘述式 switch 敘述式、亦是一多重多層作決策之敘述式。 請參考範例。

31 3-5 while 迴圈(Loop) while (expression) statement
當條件expression被測試、若是“真(non-zero)”、將執行statement、然後再重覆測試expression。直到expression被測試為“非(zero)”為止。而執行指標(point execution)也移至statement的下一式。

32 3-5 for 迴圈(Loop) for (expr1; expr2; expr3) statement
for-loop的此三expressions、expr1是初始條件; expr2是結束條件; expr3是變化運算式。在型態上、expr1和expr3可以是指定運算式(Assignments)、或是函數呼叫程式(Function calls); expr2是關係運算式(Relational expression)。三者於必要時、均可省略,但逗點 “;” 不可省略。

33 3-6 do-while迴圈(Loops) do statement while (expression)
主體敘述式(Statement)執行後,再作expression條件測試,測試如果是真(True)、則再一次執行主體敘述式(statement);測試如果是非(False)、則結束並跳離loop。

34 3-7 break之應用 for-loop、while-loop經過頂端測試,do-while-loop經過底端測試,才得進入loop區塊。一旦進入後、須將區塊內敘述式執行完畢、才可離開。C提供break、可在區塊內、尚未將區塊內敘述式執行完畢前、跳離loop區塊。

35 3-8 continue 之應用 continue之應用、與break類似,不同之處、break在跳離loop後、將不再回頭測試loop、不再進入loop;而continue在跳離loop後、立即回頭測試loop、進入loop。下列片斷程式、是以continue作有關正值(positive value)之事宜;跳過有關負值(negative value)之事宜。

36 3-9 goto 與 label 之應用 C提供了無限橫衝直撞(Infinitely abusable)的goto敘述,以及導引標號label。使用goto、可到達任意指定之label位置,很是好用且方便,也因如此、可能會破壞程式之區塊架構。本書建議、非不得已、不輕易使用。

37 第四章 函數程式 與 程式設計架構(Functions and Program Structure)
將一個大程式、按其功能、分割成一些小程式,這些小程式即謂函數程式。當程式設計師設計程式時、對有些已寫好完成的函數程式、無須再展開寫入,可就其功能需要、撿取其函數名稱、置於程式中即可。 一個完整的程式、本就應是由呼叫其所需之函數程式、繫組而成的。而非是僅僅一個費神費力的龐大單一程式。C將一些有用的函數程式、先寫好置入程式庫(Library)中。程式設計師設計程式時、由Library中、撿取所需函數之名稱、置於程式中即可。例如我們熟悉的I/O(input/output)函數getchar、putchar;數學運算函數sin、cos、sqrt等皆是。

38 4-1 基礎架構 下列程式、為主程式呼叫一函數之基礎型態: 1 main() 2 { 3 testsub(); 4 } 5
2 { testsub(); 4 } 5 6 testsub() 7 { printf("This is the string from testsub"); 9 } 列1~4 是主程式。 列3 由主程式呼叫函數testsub( )。 列6~9 是函數、由主程式列3 呼叫執行。

39 4-2 非數值(int)之函數回傳值(Functions Returning Non-Integers)

40 4-3 函數之參數(Function Arguments)
一般語言程式設計、有(1)参數傳值(call by value) (2)參數傳址(call by reference) (3)參數拷貝結果(copy restore) (4)参數傳名(call by name)。 C語言則僅為 “参數傳值(call by value)”。當呼叫程式呼叫函數程式時、參數值僅可從呼叫程式傳遞至被呼叫之函數程式,不可從函數程式傳回至呼叫程式。

41 4-4 外部變數(External Variables)
一個C語言程式、都會搭配一些外部項目(External Objects),通常這些外部項目、是變數(Variables)或是函數程式(Functions)。 外部(External)之相對者、是內部(Internal),亦即將參數(Arguments)與自動變數(Automatic Variables)定義於函數之內部。外部變數(External Variables)定義於函數之外部、且提供給多處函數程式使用,即謂全域(Global)變數。至於函數程式、祗有外部函數、並無內部函數。

42 4-5 區域規則(Scope Rules) 因為有了函數與外部變數、讓C程式可不必限制在同一時間內、作編譯(be compiled),也不必要放置在同一檔案(File)內。當時之程式、可將先前已編譯完成之程式碼、或別處檔案之程式碼、轉載過來、共同完成當時程式預期要求之結果。 每一區域(Scope)、可以一個名稱(Name)定義之。對宣告在一個函數內的自動變數(Automatic Variable)來說、該函數的名稱、即是其區域,這些變數、與其他別的區域無關係。同理、在這區域函數名稱內之參數(Arguments)也是一樣。

43 4-6 靜態變數(Static Variables)
在自動變數(Automatic Variables)、外部變數(External Variables)之外、第三種變數、是謂靜態變數(Static Variables)。靜態變數可分為兩種、內部靜態變數(Internal Static Variables)與外部靜態變數(External Static Variables)。 內部靜態變數、與內部變數(Internal Variables)一樣、宣告於函數內,僅供該函數使用,而不同之處、是並不隨函數之存在而存在,是一直獨立存在的。

44 4-7 暫存器變數(Register Variables)
暫存器(Register)是一種最快速存取的記憶體,通常罝於CPU內,且數量有限。 當要處理資料時、資料及運算元將被拮取(Fetch)至CPU、並置於功能暫存器內加以處理,處理結束後、暫存器再換進另一組待處理的資料及運算元,若某一資料的使用率非常高、其編譯程式(Compile)會考量該資料不必從暫存器換出,以節省常常換進換出所付的代價。

45 4-8 區塊架構(Block Structure)
C並非是一個完完全全的區塊架構(Block Structure)語言。變數(Variables)可在區塊內作定義(Be defined)或作宣告(Be declared); 函數却有所不同、僅可在區塊內作宣告(Be declared)、而不可作定義(Be defined)。

46 4-9 變數初值之設定(Initialization)
當變數未作初值設定時、外部變數(External Variables)與靜態變數(Static Variables)將自動被設定0為初值; 而自動變數(Automatic Variables)與暫存器變數(Register Variables)則無初值設定。

47 4-10 遞迴(Recursion) C之函數、可直接或間接的自己呼叫自己、此謂遞迴(Recursion)。
當函數自己呼叫自己時、將會不停的呼叫下去。因此、遞迴函數至少有兩個基本設計,一是停止機制區;一是呼叫區。

48 4-11 前罝處理程式(Preprocessor)
(1)#include為延伸使用曾經完成的程式檔案; (2)#define為簡單巨集代入。因寫在檔案之前端、全域性(Globe)的供同一檔案內之各函數使用。

49 第五章 指標 與 陣列(Pointers and Arrays)
指標(Pointer)是一種變數、是另外一個變數的地址(the address of another variable)。 在指標之使用上、C語言特別靈巧、往往能因此寫出令人難以相信的絕佳程式風格。也往往會產生一些不易了解的困擾。

50 5-1 指標與地址(Pointers and Addresses)
因指標(Pointer)含著另一個資料的地址,故由指標、可間接(Indirectly)存取該資料。對初學者來言、指標型態往往不易了解。 設x 為變數、亦即記憶體名稱;6 為記憶體的內容;pi 為指標。當指標指向變數之記憶體時,指標內容為該記憶體變數之地址(address),因此、經由該指標可間接存取(Access)該記憶體。

51 指標(Pointer)在運算式(Statements)中之功能型態
(1) y = *px + 1; 將指標px指向之變數記憶體內容、加1、置放於y內。 (2) d = sqrt((double) *px); 將指標px指向之變數記憶體內容、改為double、平方根後、置放於d內。 (3) y = *(px + 1); 將指標px指向之變數記憶體地址、加1、將新地址之記憶體內容、置放於y內。 (4) *px = 0; 也可將*px置於等號(=)之左端,將0置入指標px指向之記憶體內。 (5) *px += 1; (*px)++; px = py; 三者均屬合法。

52 5-2 指標 與 函數参數(Pointers and Function Arguments)
於1-8節、我們曾述及、C語言函數間之参數傳遞、是參數傳值(Call by Value)。 當呼叫程式呼叫函數程式時、參數值僅可從呼叫程式傳遞至被呼叫之函數程式,不可從被呼叫之函數程式直接傳回至呼叫程式。如果必須要將參數值、從被呼叫之函數程式傳回至呼叫程式,可先將一般變數之參數、改為指標型之参數,參數值即可從函數程式傳回至呼叫程式。

53 5-3 指標與陣列(Pointers and Arrays)
在C語言、指標與陣列之關係是非常密切的。凡是可經由陣列執行的、幾乎也均可經由指標來完成。

54 注意的重點: pa = &a[0]; 當指標pa指向陣列a時、其實是指向陣列a之第一項a[0]。
x = *pa; 是將陣列a第一項a[0]的內容值10、拷貝入x內,即 x = 10。 x = *(pa+1); 是將陣列a第二項a[1]的內容值11、拷貝入x內,即 x = 11。 同理、x = *(pa+i); 是將陣列a第i+1項a[i]的內容值、拷貝入x內。 pa = a; a是該陣列之名稱、也可視為是指向該陣列之指標是該陣列之名稱,其內容與(1)pa = &a[0]意義相同。 a[i]; 與 *(a+i); 意義相同。由 (3)可知 a[i]; 與 *(pa+i); 意義相同。再由(4)得知 a[i] 與 *(a+i) 意義相同而得証。我們可看出、陣列之索引法(Indexing)與指標位移(Pointer Arithmetic)是非常相似的。 &a[i]; 與 a+i; 意義相同。由(5)得知得証。 pa = a; pa++; 為合法式(legal),因pa是指標(Pointer)、是變數(Variable), 但a = pa; a++; y = &a; 均為非法式(illegal),因a是陣列(array)名稱、是地址(address),不是變數。

55 5-4 地址移位(Address Arithmetic)
設p為指標,則p++指向次一個地址之記憶體。 同理、p += i 指向次i個地址之記憶體。此謂地址移位(Address Arithmetic)。

56 5-5 字元指標與函數程式(Character Pointers and Functions)
當程式以一字串為參數、呼叫函數時(如sub(“abcde”)),被呼叫之函數、並無法將該字串(“abcde”)以參數承接下來,能做的僅是承接該字串(“abcde”)的起始地址。 C語言、在參數傳遞上、無法傳遞兩個或兩個以上單元之資料。我們常用的內建函數 printf(“This is my first Program\n”);、參數看起來是一字串,其實祗是字串的起始地址。

57 5-6 指標非整數(Pointers are not Integers)
在一般正常之狀況下、指標指向記憶體時、即是指向該記憶體之地址。 既然是地址、當然也就是整數。但也可能會有萬一之意外、不是整數,為避免這 “萬一誤差之意外”、造成另一個更大的 “誤差之意外”,在設計程式時、儘可能以int規範之。

58 5-7 多維陣列(Multi-Dimensional Arrays)
C提供了多維陣列,本節將以兩函數實例解說其用法、及其與指標間應注意的關聯。

59 5-8指標陣列(Pointer Arrays)
指標本身是變數,當指向一處記憶體時、其內容是該記憶體的地址。 因而、又當一陣列(Array)之內容是一連串其他各記憶體之地址時、該陣列即成為陣列指標(Pointer Arrays)。

60 5-10 指標與多維陣列(Pointer vs. Multi-dimensional Arrays)
若我們宣告二維陣列a、指標陣列b: int a[5][10]; int *b[5]; 在使用上、a與b是很相似,現就其異同解述如下: a是一個完整的二維陣列,確確實實的據有50個單位(Elements)且是連續的記憶體。 b是一指標陣列,陣列內有5個指標,若每一指標、各自指向一據有10個單位(Elements)且是連續的記憶體時、a與b在程式設計使用上、可謂完全一樣。 但此時、a與b在實體上之差異為: (a) b據有的空間、在50個單位記憶體之外、另還有5個指標據有的空間,故共據有55個單位記憶體。而a僅據有50個。 (b) 若 b內5個指標、各自指向一據有10個單位(Elements)且是連續的記憶體,但這5個連續的記憶體、彼此間却不一定是連續的。而a是連續的。 (3) b是一指標陣列,陣列內5個指標各自指向一陣列,這5個陣列之長度並非是一致的,而是隨須要自行調整的。

61 5-11 指令參數(Command-line Arguments)
main(argc, argv, envp) argc 是指令參數之數量(包括執行檔名稱)。如上例 “cc First.c -o First.out” argc = 4。 argv 是指令陣列。如上例 argv[0] = “cc”; argv[1] = “First.c”; argv[2] = “-o”; argv[3] = “First.out”。 envp 是環境資料。

62 5-12 指向函數之指標(Pointers to Function)
當指標指向變數記憶體時、指標的內容是該變數記憶體的地址(Address)。 換言之、一般來言、指標是指向變數的。 函數本身並不是變數,但在C、指標可指向函數 。

63 第六章 結構型態(Structures) 結構型態(Structures)是多個變數的組合,這些變數可能是不同之型態(Type)、組合在同一個名稱之下、方便於使用。 有些程式語言、稱之為資料錄(Record)。例如我們常見到的薪津資料錄,其中員工資料(employee)、有姓名(char name)、地址(char address)、身份証號碼(char number)、薪俸(int salary)等。

64 6-1 基礎樣式(Basics) 在第五章、我們曾討論有關年(year)、月(month)、日(day)、一年中的第幾日(yearday)、月名稱(mon_nam)e等五個變數。這五個變數、可以以結構型態、放置於date組合內、以一個結構型態之名稱date統合之: struct date { int day; int month; int year; int yearday; char mon_name[4]; }; 上為結構型態之宣告樣式。宣告變數date,包括五個宣告,是謂date的成員(member)。

65 6-2 結構型態 與 函數(Structures and Functions)
(1) 其中最明顯的、是結構型態無法將其全部之組合成員、在函數間之参數上同時作傳遞。必須作一些改變、才可作傳遞: (a) 組合內各成員(member)、分別作 傳遞。 (b) 以指標作全部成員之傳遞。 (2) 僅外部結構型態(External Structures)與靜態結構型態(Static Structures)可作初值設定、其他如自動結構型態(Automatic Structures)則不可。

66 6-8 同位集合(Union) 同位集合(Union)是指一變數、在不同時間、以不同型態、不同大小作宣告。
亦即在不同時間、同一記憶體可供不同型態之資料使用。

67 6-9 定義型態(Typedef) C可定義新的資料型態,如: “typedef int AAA”。 執行後、AAA即有int一樣的功能。
int len, maxlen; 可改寫為: AAA len, maxlen; int *lengths[ ]; 可改寫為: AAA *lengths[ ];

68 第七章 輸入輸出(Input and Output)
輸入輸出(I/O)並非C語言之一部分。 故在本章之前、我們一直未強調敘述。但在程式設計上、必須配合系統之輸入輸出(I/O)環境、才能有完整的架構。因此在本章、我們將依附 “標準I/O函數庫(standard I/O library)” 各函數、給予C語言最適當之輸入輸出設計。

69 7-1 使用標準函數庫(Access to the Standard Library)
任何程式檔、當要使用標準I/O函數庫(standard I/O library)之各函數時、都要在檔案內容起始處、增寫: #include <stdio.h> 以 < >括弧 取代我們常用的 “ ”括弧,是導引Compiler去搜尋標準I/O函數庫(standard I/O library)之各函數。

70 7-2 標準輸入輸出—getchar 與 putchar
簡單的輸入函數getchar、是由標準輸入裝置、一次輸入一個字元。當讀取到EOF時、即完成輸入、函數getchar( )回傳 –1、結朿輸入執行。故須注意回傳值要宣告為int。 相對的輸出函數putchar、是由標準輸出裝置、一次輸出一個字元。

71 7-3 格式控制輸出函數(標準輸出裝置)--printf
函數printf、以格式控制字串(control)、控制印出各參數(arg1, arg2, …)。格式控制字串(control)樣式如 %-10s,其含意為: (1) %、為格式控制字串(control)之起始符號。 (2) 負號、為向左對齊(left adjustment)。 (3) 數值、為印出長度(field length)。 (4) 更換字元(conversion character)、為決定印出資料的型態。常用者有: d 印出十進位型態(decimal notation)。 o 印出八進位型態(octal notation)。 x 印出十六進位型態(hexadecimal notation)。 u 印出無負號之十進位型態(unsigned decimal notation)。 c 印出單字元型態(singer character)。 s 印出字串型態(string)。 f 印出浮點型態(float如123.45)。 e 印出浮點型態(float如 [-] e[±]5)。

72 7-4格式控制輸入函數(標準輸入裝置)--scanf
函數scanf、以格式控制字串(control)、控制輸入資料、並按序儲存於各參數(arg1, arg2, …)。必須注意、各參數須是指標(pointer)、指向對應之儲存記憶體。格式控制字串%5d %f: (1) %、為格式控制字串(control)之起始符號。 (2) 數值、為印出長度(field length)。可省略。 (4) 更換字元(conversion character)、為決定資料輸入的型態。常用 者有: d 輸入型態為十進位整數、對應參數須是指標。 o 輸入型態為八進位整數、對應參數須是指標。 x 輸入型態為十六進位整數、對應參數須是指標。 c 輸入型態為一個字元、對應參數須是指標。 s 輸入型態為字元字串、對應參數須是指標。 f 輸入型態為浮點數、對應參數須是指標。

73 7-5格式控制輸出入函數(記憶體)—sprintf 與 sscanf
函數printf與scanf有一組兄弟函數sprintf與sscanf,所不同處在輸出入裝置,前者是標準輸出入裝置(如 鍵盤、螢幕等);後者是長串記憶體。輸出函數如: sprintf (string, control, arg1, arg2, …); 例:sprintf (name, “temp%d”, n);

74 7-6 檔案存取(File Access) 執行過程要考量:(1)開啟來源輸入檔案、或標的輸出檔案;(2)建立指向輸入或輸出檔案之指標。C提供宣告如: FILE *fopen( ), *fp; *fopen( ) 開啟輸入或輸出檔案; *fp 指向輸入或輸出檔案之指標。C提供指令式如: fp = fopen (name, mode); 當mode為 “r” 時、name是來源輸入檔案、開啟後、fp指向檔案name之位置。 當mode為 “w” 時、name是標的輸出檔案、開啟後、fp指向檔案name之位置。

75 7-7 差錯處理(Stderr and Exit)
程式執行遇到差錯時、多會設計印出發生差錯之可能原因。為了避免在印出時、誤導印入其他未預料之檔案內,C提供第二標準輸出檔案stderr、接受其輸出標的檔案。 在標準函數庫中、函數exit之功能為中止程式進行,如因有差錯而中止、設定為exit(1);如因圓滿完成而中止、設定為exit(0)。

76 7-8 整列內容之輸入輸出(Line Input and Output)
標準程式庫提供整列讀取函數fgets、其樣式如: fgets (line, MAXLINE, fp) 將檔案指標fp所指向之標準裝置、讀取MAXLINE – 1 個字元、存置於指標line指向之位址。標準程式庫也提供整列輸出函數fgets、其樣式如: fputs (line, fp) 將指標line指向之內容、輸出到指標fp指向之標準裝置。

77 第二篇 資料結構 研讀第一篇後、您已具備C語言程式設計之能力。但在設計工具的應用上、仍嫌不足。本篇援用資料結構應用程式。
一者提供您、大量C語言程式設計之練習;二者提供您、在爾後學習深入的C語言程式設計之前、先熟悉一般應用工具之設計。

78 第八章 鏈接串列(Linked List) 關於連串之資料、我們曾深入討論陣列(Array),但其在增加(Insert)、刪除(Delet)等作業、無法作靈活之執行。本章以此為討論重點、更深入磨練讀者C之設計能力。 鏈接串列、有三種基本執行應用:(1) 建立(Create);(2) 插入 (Insert);(3) 刪除(Delete)。本章將一一詳述。

79 第九章 堆疊(Stack) 與 佇列(Queue)
堆疊(Stack)是資料先進後出(FILO);佇列(Queue)是資料先進先出(FIFO)。

80 9-1 堆疊定義 堆疊是許多資料項目(Data Item)、作有序之組合。資料由同一端點、進出堆疊(Stack),此一端點稱為堆疊的頂端(Top)。

81 9-2 堆疊製作 堆疊的製作、可概分為: (1) 以陣列製作堆疊; (2) 以鏈接串列製作堆疊。

82 9-4 佇列之製作 佇列之基本運算為刪除(Delete)、與增入(Add)。在前端(Front)作刪除、在後端(Rear)作增入。
可概分為:(1) 陣列結構;(2) 鏈接串列結構。

83 第十章 圖形結構(Graph Structure)
一個複雜的問題、往往可以經過一個圖之描述、使得問題變得精簡、且易了解。 本章將討論 (1) 圖形結構之定義; (2) 圖形結構資料之表示法; (3) 圖形結構之應用。

84 10-1圖形結構之定義 圖形是一群有限數量節點(Vertices)之集合。節點與節點間、由邊(Edge)相互連接。圖形結構是由節點與邊所組成。 因此、圖形可以 G={V, E} 表示之。其中 V 是有限數量節點之集合。V = {v1,v2,…,vn};E 是有限數量邊之集合。E = {e12,e23,…}。

85 10-2 圖形結構資料之表示法 一、鄰接矩陣表示法(Adjacency Matix Representation)。
二、鄰接串列表示法(Adjacency List Representation)。 三、邊串列表示法(Edge List Representation)。 四、加權值圖形資料表示法。

86 10-3最短途徑(The Shortest Path)
演算法。 1、建立陣列。 (1) a[j][j] 其中(j = 1,n) (a為圖形之鄰接矩陣表示圖如:圖10-2-4表示圖)。 (2) visited[j] = 0 其中(j = 1,n) (每一節點均未拜訪過)。 (3) length[j] =a[start][j] 其中(j = 1,n) (將鄰接矩陣a之第start列拷貝至length內)。 (4) visited[start] = 1 (拜訪過之起始節點)。 (5) pass_by[j] = start 其中(j = 1,n) (設定中間節點)。 2、在未被拜訪過之節點中、找到某節點k、使得length[k]為最小值,然後設定 visited[k] = 1。 3、執行: for (j = 1; j <= n; j++) if (! visiter[j] && length[k] + a[k][j] < length[j]) { length[j] = length[k] + a[k][j]; pass_by[j] = k } 4、回到步驟2、直到所有節點都拜訪到。

87 第十一章 樹狀結構(Tree Structure)
樹狀結構、是圖形結構中的一種特殊結構。由節點(Node)與邊(Edge)構成。 樹狀結構有一特定節點謂樹根(Root),這是一般圖形結構所沒有的。

88 11-1 樹狀結構定義 1、樹根(Root):在樹狀結構的頂端。 2、子樹(Subtree):左子樹;右子樹。
3、父節點(Parent Node) 4、子節點(Son Node) 5、兄弟節點(Siblings) 6、樹葉(Leaf):沒有子節點的節點。 7、內部節點(Internal Node):不是樹根、不是樹葉的節點。 8、分支度(Degree):為節點上之分支、可細分為: (1) 指入分支度(Indegree):指向節點箭頭之數量。 (2) 指出分支度(Outdegree):由節點指向其他節點之箭頭數量。 7、路徑長度(Length of Path):由節點至另一個節點、所經過之邊的數量。 8、階度(Level) 9、方向樹(Directed Tree):(1) 無環繞現象;(2) Root之Indegree 為0;(3) 其他所有節點之Indegree至少為1。 10、無方向樹(Undirected Tree):不是方向樹之樹。

89 11-2 二元樹(Binary Tree) 在電腦應用上、二元樹是一種非常廣泛的用法。
其定義為:(1) 每一節點最多有兩個Outdegree;(2) 除Root外、每一節點最多有一個indegree。

90 11-3二元搜尋樹(Binary Search Tree)
將資料置入二元樹時、若一開始、就以二元搜尋樹建置、將有利而後排序、搜尋、刪除等作業之執行。 本節將討論二元搜尋樹之建置與資料排序

91 11-4 二元搜尋樹資料之搜尋 如果資料在二元樹上、沒有特定排序如11-3節時、搜尋就要去拜訪每個節點。 因此可先搜尋左子樹;再搜尋右子樹。

92 11-5 二元搜尋樹資料之刪除 若要刪除二元搜尋樹之節點、相較上節所述插入新節點、是要複雜得多。 在刪除節點上、要考量三種不同的情況:
11-5 二元搜尋樹資料之刪除 若要刪除二元搜尋樹之節點、相較上節所述插入新節點、是要複雜得多。 在刪除節點上、要考量三種不同的情況: (1) 刪除之節點為樹葉; (2) 刪除之節點僅有一顆子樹; (3) 刪除之節點有兩顆顆子樹。

93 11-6 AVL平衡樹(Adelson-Velskii-Landis Balanced Tree)
於建立二元搜尋樹時、運氣好、建立一顆有效率之平衡搜尋樹;或運氣不好、建立一顆無效率之非平衡搜尋樹。 本節將討論、如何確保所建立之二元搜尋樹、一定是平衡搜尋樹。

94 第三篇 網路系統應用程式設計 本篇介紹Uinx (Linux)環境下之工作程序、延續第一篇、第二篇C語言程式設計的能力、作程序間、資料傳遞之網際網路程式設計。 第十二章介紹網路資料、以標準輸入輸出裝置、作UDP/TCP傳遞;第十三章介紹網路資料、以檔案作UDP/TCP傳遞;第十四章以學理、實作為觀察點、介紹傳統加解密與近代加解之方法、及實作程式設計。特別注意、本篇各應用程式、必須是在Unix (Linux)系統環境下執行。

95 第十二章 UNIX/LINUX工作程序 與 網路系統程式設計(1)—鍵盤螢幕輸入輸出
在前述各章中、我們已詳盡了解C語言之程式設計與一般應用。本章、將在UNIX(LINUX)介面環境下、以C語言做更具有意義之程式設計--網路程式設計。 本章我們將討論 (1)在同一電腦系統環境內、工作程序(Process)間如何作資訊傳遞;(2)在不同電腦系統環境間、工作程序(Process)如何以網路作資訊傳遞。本章解述、在UDP與TCP中、發射工作程序端之資料如何以鍵盤輸入、再如何發射至網路上;接收工作程序端如何將資料接收到、如何再顯示在螢光幕上。

96 12-1 工作程序(Process) 在UNIX系統、當我們執行一個 “執行檔” 時、即向系統要求一個 “工作程序(Process)” 以執行之。 UNIX指令 “ps” 功能為列出 “工作程序” 及其有關資料(Reprot Process Statue)。

97 12-2 管線(Pipe Line) 管線(Pipe Line)、為在同一電腦系統環境內、工作程序(Process)間、作資訊傳遞的一個元件。UNIX C 提供函數 pipe( ) 建立管線

98 12-3 UNIX 網路系統程式設計(UDP) 本節討論非連接型式(Socket system calls for connectionless protocol)網路程式設計,以UDP實例(User Datagram Protocol, Internet)解述之。

99 12-4 UNIX 網路系統程式設計(TCP) 本節討論連接型式(Socket system calls for connection-oriented protocol)網路程式設計。TCP(Transmission Control Protocol, Internet)之與UDP(User Datagram Protocol, Internet)不同、是前者為連接型態、而後者是非連接型態。 TCP以呼叫系統函數 connect( ) 與 accept( )、將網路上的兩個工作程序作連接、然後作資料傳遞。因此。TCP較UDP具較高之可靠性。本節以TCP實例解述之。

100 第十三章 UNIX (LINUX) 網路系統程式設計(2)—檔案輸入輸出
在前章(第十二章)、我們討論了在不同電腦系統環境間、工作程序(Process)如何以網路作資訊傳遞,在UDP與TCP中、發射工作程序端之資料如何以鍵盤輸入、再如何發射至網路上;接收工作程序端如何將資料接收到、如何再顯示在螢光幕上。 本章將以UDP與TCP、討論檔案在網路上如何作資訊傳遞。UDP之可靠性不如TCP,在網路檔案傳遞時、經筆者反覆測試之經驗、平均每傳遞三個封包、就有一個封包會發生誤差、須將該誤差之封包、作重新補救再傳遞一次。因此、在鍵盤螢幕輸入輸出(如第八章所述)時、尚可執行,但作檔案網路傳遞時、則將無法執行。 為了讓UDP勉強作網路檔案傳遞、可將其封包作大、將檔案內容全部裝入、以一個封包傳遞之。一般來言、網路檔案傳遞、均以TCP執行之。

101 13-1 UNIX 網路系統程式設計(UDP)—檔案輸入輸出
本節討論非連接型式(Socket system calls for connectionless protocol)網路檔案傳遞程式設計,以UDP實例(User Datagram Protocol, Internet)解述之。

102 13-2 UNIX 網路系統程式設計(TCP)-- 檔案輸入輸出
本節討論連接型式(Socket system calls for connection-oriented protocol)網路程式設計。TCP(Transmission Control Protocol, Internet)之與UDP(User Datagram Protocol, Internet)不同、是前者為連接型態、而後者是非連接型態。 TCP以呼叫系統函數 connect( ) 與 accept( )、將網路上的兩個工作程序作連接、然後作資料傳遞。因此。TCP較UDP具較高之可靠性。本節以TCP實例解述之。

103 第十四章 UNIX (LINUX) 網路程式設計(3)—傳輸資料加解密
網路中、兩個工作程序相互傳遞資料、資料的隱密性亦隨著網路之蓬勃、顯得日益重要。本書即是討論到網路資料傳遞,自然也應討論資料如何加密。本章將以簡單的實例、讓讀者清礎了解、在資料加密中、如何作初步之程式設計。資料加密、可分類為:(1) 傳統加密法 與 (2) 近代公開金匙加密法。 在傳統加密法、本章將以換位法(Transposition)實例解說;在近代公開金匙加密法、以RSA(Rivest, Shamir, Adleman 三人提出)實例解說。

104 14-1傳統加解密--換位法(Transposition)
換位法、可作許多不同型態之設計。本節之設計為:加密時、在檔案資料讀取後、將每一字元或數碼加以特定數字。 解密時、將每一字元或數碼減以該特定數字、再寫入接收檔案內。該特定數字、可稱之為 “加解密金匙”。

105 14-2近代公開金匙加解密法--RSA 傳統密碼加密法、有其一定的不可靠風險。發射工作程序之加密金匙、與接收工作程序之解密金匙、其間關係密切。換言之、接收工作程序於設定加解密金匙後,自己保留解密金匙、還必須將加密金匙、隱密通知發射工作程序。在通知的過程中、即已有了不可避免的洩密風險。近代密碼加密法、針對此項洩密風險、加以改進。接收工作程序於設定加解密金匙後,自己保留解密金匙、另將加密金匙、不僅不須隱密通知對方、甚至將加密金匙公告大眾,其中神妙之處、令人驚嘆。 自1976年Diffie與Hellman提出單向暗門公開金匙加解密法之概念後、1978年美國麻省理工學院三位教授Rivest、Shamir和Adleman提出以分解因數的指數函數、做為單向暗門之公開金匙加解密法,即RSA。

106 (一)、暗門單向函數 設有一函數 y = f(x) 若已知 x、求 y 並不困難;但 若已知 y、求 x 卻很困難。是謂單向函數。
若設計z、致上述單向函數可輕易由y求得x、即是謂暗門單向函數。

107 (二)、單向函數常例 (1) 多項式: y = xn + an-1xn-1 + … + a0 (2) 指數與餘數: y = gx mod p
(3) 因式分解: y = p*q (p、q為大質數) n (4) 迷袋式: y = Σ xibi i=1

108 (三)、餘數同餘觀念 當任一整數m除以整數n時、其餘數將被分成n個剩 餘類(Residue Class)如下: C1 C2 C3 … Ck
S n n … (k-1)n S n n+1 … (k-1)n+1 S n n+2 … (k-1)n+2 … … … … … … Sn-1 n n n-1 … kn-1 Si 為剩餘類(Residue Class)。若將每一剩餘類、取一數為代表、形成一集合、是謂 “模n” 之完全剩餘系(Complete Set of Residue)。

109 (四)、縮剩餘系(Reduced Set of Residues)
由模n完全剩餘系中、將所有與n互質的剩餘類、組成一集合。則此集合是謂模n之縮剩餘系(Reduced Set of Residues)。例如:n = 10、則模10之完全剩餘系是 {0、1、2、3、4、5、6、7、8、9}。而其縮剩餘系是 {1、3、7、9}。 在模n之縮剩餘系中取一整數a、則必有另一整數b(屬於此縮剩餘系)使 ab = 1 mod n。例: a: b: x 1 x 7 x x x 3 x 9

110 (五)、尤拉商數(Euler’s Totient Function)
令Ø(n)為小於n、且與n互質所有整數之個數。則Ø(n)為模n縮剩餘系所有元素之個數。此Ø(n)即謂尤拉商數(Euler’s Totient Function)。

111 (六)、尤拉定理(Euler’s Theorem)
若 (a, n) = 1(即a、n互質)、則 aØ(n) = 1 mod n 証:(1) 若 (a, n) = 1、且 (b, n) = 1。則 (ab, n) = 1。 (2) 若 {r1、r2、…、rØ(n)}為模n之一縮剩餘系、且 (a, n) = 1。 則可由 (1) 得:{ar1、ar2、…、arØ(n)}亦為模n之 一縮剩餘系。 (3) 由 (2) 得:(r1*r2*…*rØ(n)) = (ar1*ar2*…*arØ(n)) mod n。 則 (r1*r2*…*rØ(n)) = aØ(n) (r1*r2*…*rØ(n)) mod n。 即 aØ(n) = 1 mod n。 得証#

112 (七)、費瑪定理(Fermat’s Theorem)
若 p 為質數、且 (a, p) = 1。 則 ap-1 = 1 mod p。 証:(1) 因 p 是質數、故其尤拉商數 Ø(p) = p - 1。 (2) 由 尤拉定理得知: aØ(p) = 1 mod p。 即 ap-1 = 1 mod p。 得証#


Download ppt "第一篇 C語言基礎入門應用程式設計 本篇內容精緻實用、由淺入深、並參佐實作範例。為初學者作基礎入門學習、易學易懂、且建立實作能力。特別適用於各級學校、作為教學教材。"

Similar presentations


Ads by Google