計算機概論:C/C++程式設計

 

 

1章、程式設計基本概念

 

 


授課教師:陳慶瀚

WWW : http://www.miat.ee.isu.edu.tw/cpp

E-mail : pierre@isu.edu.tw   

 

1. 程式設計基本概念

Software developers are today's heroes.

They bring to life and try to tame mysterious armies of symbols.

They shepherd the creation of new worlds—tools and environments that emerge reluctantly out of a chaos of conflicting, half-articulated, and half-understood goals and needs.

-John M. Carroll, 2000 Massachusetts Institute of Technology-

1.1  電腦和程式語言

現代人沒有用過電腦的人已經越來越少了。上網、文書處理、電腦繪圖、電子試算表相信已經成為許多上班族或學生的生活和工作中部可缺少的一個工具。對於工程師來說,可以使用電腦來幫忙做一些複雜的、大量而又重複性很高的計算,使用電腦模擬來取代昂貴又費時的實驗,使用電腦輔助設計來開發高品質的工程系統或電路,使用電腦來擷取、分析和監控工廠的儀器設備。而所有這些工作都必須透過軟體(software)才得以實現。

我們都知道,電腦硬體(hardware)是由一堆冷冰冰的金屬、塑膠和電子材料組合而成,它沒有認知、感覺、思考、決策和行動能力,電腦的一切工作都是在於執行由程式設計師所設計出來的程式。程式設計師把外在世界的資訊、所要達成的目標、解決問題的方法和步驟、以及解題過程中可能發生的選擇和判斷,詳細而嚴謹的將它們編寫成一個程式,再交由電腦去執行。這個過程就是程式設計(programming)

電腦硬體透過程式與外在世界溝通,或者說,人們透過程式與電腦溝通,所以程式是電腦與人的界面。任何的溝通都需要一種語言,電腦與人溝通的語言就是程式語言。如同人類世界所使用的各式各樣的自然語言一樣,電腦世界也存在各式各樣的程式語言。其中,有直接與硬體溝通的機器語言,如下列程式碼:

0000 0100 0100 1110

1010 0011 0010 0010

0000 0110 0001 1010

1100 1001 0010 0110

.... .... .... ....

使用機器語言的好處是效率極高,但必須對於硬體架構要非常清楚,而且程式的維護和修改都相當困難,而且除了程式設計師本身之外,他人想理解機器語言所寫的程式幾乎是不可能的,也因為如此,現今大概沒有任何一位程式設計師會願意用機器語言寫一個二元一次方程式求解的程式了。

MOV  EDX,[EAX].Mode

SUB  EDX,fmClosed

CMP  EDX,fmInOut-fmClosed

JA      @@notAssigned

LEA  EAX,[EAX].FileName

PUSH EAX

......................

組合語言也是一種非常接近硬體的程式語言,和機器語言不同的是,組合語言使用一堆較容易記憶和理解的符號來替代像天書一般的01程式碼,譬如說,我們使用

MOV A, B

把資料從B處搬到A處。看起來比前面的

0000 0100 0100 1110

要容易理解一些。撰寫組合語言程式需要具備微處理機的背景知識才能得心應手。此一語言的效率甚高,而且可以充分使用硬體資源,對於許多電腦硬體工程師來說,組合語言正是他們的專業利器。

儘管如此,組合語言程式設計要花許多時間跟硬體打交道,程式的除錯(debug)也相對困難,特別對那些應用系統的工程師,他們希望將心力投注在較高階(相對於低階的硬體)的演算法的規劃和設計。多數應用程式的開發都使用所謂的高階語言,這些語言具有抽象程度較高,也較合於人們直覺的語法(syntax),因此它們具有容易學習和設計、容易維修擴充、可靠度高等優點。由於這些特色,程式設計的門檻因而大幅降低,任何非電腦專業的人員都可以藉由一種的高階語言來設計特定應用的程式。表一是最常見的高階語言。

表一是最常見的高階語言

高階語言

主要用途範疇

C

系統軟體的設計

C++

C語言的擴充,支援物件導向程式設計

Pascal

嚴謹的,適合教學的結構化程式設計語言

Fortran

適合科學與工程計算

BASIC

簡易的、效率較低的直譯式程式語言

COBOL

執行商業資料處理應用

Ada

美國國防部指定的程式語言,適合即時系統設計

Lisp

人工智慧應用程式設計

Prolog

以二元邏輯推論為基礎的人工智慧應用程式設計

SmallTalk

彈性很大但效率較低的物件導向程式設計

1.2  C/C++語言的發展

C語言是由AT&T Bell實驗室的研究員Dennis Ritchie1972年所發展出來的一種高階語言。C語言原始的設計目的是為了撰寫UNIX作業系統,而隨後這個語言也被用來開發各種作業系統。由於它的高效率和彈性,伴隨市面上出現許多高品質的C語言編譯器(compiler),到了80年代,C語言很快的成為工業界最廣受採用的程式語言,而且它的應用範疇早已從系統程式擴充到各式的應用程式。

最有名的學習C語言的用書是KerniganRitchie所著 "The C Programming language",這本書大概也是最多的程式設計師研讀過的書。

198912ANSI制訂了ANSI-C標準,使C語言成為真正工業標準。

ANSI-C大致依循KerniganRitchie所定義的C語言,但增加一些新的特徵(feature),因而兩個版本並不完全相容。

C++語言可視為C語言的一個延伸的版本。C++Bjarne Stroustrup1980Bell實驗室發展的。一開始,他稱這個新的程式語言為「C with Classes

,在1983年正式更名為C++語言。

C++語言被創造出,最重要的因素是80年代開始,很多程式設計師注意到軟體的複雜度越來越高,使用C語言撰寫大型應用程式的困難度也大幅增加。根據經驗,當C語言的程式碼超過25,000行到100,000行的幅度,程式設計師將不再能夠全盤掌控程式。C++語言的原始目的之一就在於突破這個瓶頸,希望藉由C++語言,得以使程式設計師可以理解、管理和發展更大型、複雜的程式。

StroustrupC++語言在原來的C語言基礎上增加了物件導向程式設計的支援,他的靈感來自一個早期的物件導向語言:Simula67。由於它繼承了C語言高效率,又擁有物件導向語言的高彈性,因此立刻引起原本C語言程式設計師的矚目。

C++語言的三個主要的版本更新時間是1985年、1989年和1994年,1994年的更新同時是ANSI制訂了C++標準,C++的標準化的工作一直持續但緩慢的進行。1991年由C++協會所出版的「Annotated C++ Reference Manual」是第一份標準化的C++文件,最新的版本則是19954月由美國和國際標準協會(ISOANSI)所共同制訂的標準,目前市面上最主要的C++編譯器多支援這個最新的標準,例如Borland C++, C++ Builder, Visual C++, IBM VisualAge for C++, Symantec C++或是UNIX上免費的GCC都支援此一標準。

1.3  為什麼要學習C++語言

長久以來,在工程與科學計算領域,Fortran一直都是最普遍使用的程式語言,但是近年來C/C++語言卻已逐漸取而代之,其中C++語言又取代C語言成為主流。為什麼有這樣的趨勢?下列特色是C++語言成為工程與科學計算的主流程式語言的主要原因:

可用性。科學家或工程師可能會在任何一種電腦平台上面撰寫他們的程式碼:個人電腦、麥金塔、工作站、大型主機、甚至是超級電腦,他們希望使用一種在每一個平台上都可以編譯的程式語言。由於當今大多數的系統程式均使用C/C++語言所發展,當然C++的編譯器就普遍存在每一種電腦平台。

移植性。程式設計師常常希望將程式搬移到不同的電腦上面執行,這個過程稱為移植。C++語言是經由ISOANSI定義的標準化程式語言,目前不管在哪一種電腦上,絕大多數的C++編譯器都支援這個標準,因此它具有最高的移植性。

高效率。使用電腦硬體來增進程式的效能當然非常顯著,但是相對的必須付出很大的成本。在相同的硬體架構下,我們會選擇一種程式語言,使其能夠被編譯成高效率的執行檔,C/C++語言是目前所有高階程式語言當中執行效率最高的一種,也因為如此,C++(稍早則是C)語言總是備用來設計系統程式。

正確性。比起其它高階程式語言,在撰寫程式碼的過程當中,使用C++語言更容易在編譯即鏈結階段就偵測出程式的問題。

泛用性。C++並不僅止於設計系統程式或執行工程與科學運算,它已經被廣泛的用來設計解決各種問題領域的程式,在1.4節,我們將看到不同應用領域的列舉。

函式庫。當我們要開發一個完整的應用程式,除了設計自己想要的功能之外,常常需要跟作業系統溝通、或跟繪圖函式庫溝通、或跟一些特定的硬體溝通,有時候,我們需要直接使用他人所設計完成的特殊用途函式庫。C++語言在這一方面的資源最為豐富,各種免費的或商業用途的函式庫(Windows API函式庫),或物件類別庫(Object Class Library,如MFCVCL),或者與硬體溝通的界面函式庫。

1.4  物件導向程式設計有何好處?

雖然C++是一種混合式(hybrid)的程式語言,它繼承C語言的程序式的設計典範(paradigm),也結合如同SmallTalk語言一般的物件導向設計。但是物件導向設計的好處在哪裡呢?引用原創人的話:

(C++語言)得以在清晰的、具擴充性的、易於維修的而且又不損及效率的情況下,進行結構化的程式設計」

首先,我們先看看物件導向設計的三大基本精神:

A.  封裝(Encapsulation)

封裝是一個把資料和演算法綑綁在一起的機制,以便隱藏一些繁瑣的細節,使其內部的資料受到更安全的保障,免得無意間的遭到綽物的資料存取。另一方面,透過封裝的界面,使用者(或程式設計師)以一種整體的方式來理解和使用這個封裝的實體,而不致於受到太多實作(implementation)細節的干擾。這個封裝的實體就是物件(object)。一個物件必然包含一些屬性(attributes),以及一些可以修改或存取這些屬性的方法。在C++語言當中,物件的屬性是藉由資料來表示,而物件的方法就是演算法了。

在一個物件內部,我們若將某些資料指定成private,則任何物件以外的方法都無法存取或修改它,另外如果資料被指定為protected,那麼它允許被存取或修改的條件就被放寬了一些,至少,所有繼承這個物件的方法都可以直接使用到這些資料。

封裝概念提供C++語言彈性化的資料安全性的設計。除此,它讓程式設計師可以創造自己的資料型態(data type)C++語言有一些基本的資料型態,如整數(int)、字元(char)、浮點數(float)等等,我們可以將各種基本的資料型態封裝成一個物件實體。譬如我們定義一個新的資料型態叫做person,它可以包含有出生年、月、日、姓名、性別等基本資料,一旦我們使用person的物件,就如同使用整數、字元等基本資料一樣方便快速。這個特性使得程式設計師可以用相當直覺的方式來從事模組化的程式設計。

B.多型(Polymorphism)

多型的特徵是「一個界面,多重方法(one interface, multiple methods)」。也就是說,一個界面可以允許不同種類的使用方式。至於被選擇的特定使用方法是根據使用當時的情況的特性而定。

舉一個實例說明。如果把汽車油門踏板是為一個界面(它執行加油的動作),當我們想要車子稍微加速,就輕踩踏板,想要加加速更快就重踩踏板,不管是使用98無鉛汽油、95無鉛汽油或柴油的汽車,這個操作界面都是一樣的。我們很難想像,每當我們換開一輛車,就要重新學習一次加油的操作方式有多麼不便。

對於程式設計,這個原理是類似的。比方我們想設計兩個矩陣相加的界面(C++函式),通常我們馬上會想到矩陣的元素均為實數,所以我們會設計兩個實數(符點數)矩陣相加的界面;但是立刻地,我們會發現在某些機會,這兩個矩陣可能是整數的矩陣,那麼就要再設計另一個界面(C++函式)來執行兩個整數矩陣相加的運算;萬一有一個矩陣是整數矩陣,另一個是實數矩陣,那麼又要另一個界面來執行了。顯而易見,這種方式有如為使用不同汽油的汽車設計不同的使用者界面一樣,叫人無法忍受。

多型應用來整合那些功能一樣,但使用不同資料的界面。這個機能大幅降低了程式的複雜度,並使程式更易於理解和使用。至於如何選擇正確的界面?這個工作是由編譯器根據界面應用時的情況來決定,程式設計師無需操心。

C.繼承(Inheritance)

繼承是物件導向程式設計的一個重要概念。它使得程式中的一個物件被產生時就可以立即擁有別的物件的一些屬性和方法。它與「分類」或「階層」的概念有密切的聯繫,而這些概念在真實世界中已經被相當普遍的應用。譬如,美國五爪蘋果和富士山蘋果這兩類蘋果都屬於「蘋果」這個大類別,而蘋果這個類別則包含在「水果」這個更大的類別,至於「水果」這個類別又包含在「食物」的類別中。

沒有「類別」和「階層」的觀念,每一個物件都必須單獨地、完整地定義它們的所有屬性和方法,而這些屬性和方法極可能絕大多數都是重複的,程式設計師必須不厭其煩的並且小心的(因為可能有部分屬性有細微的差異)重複為每一個物件做個別的設計。在一個大型的程式計畫中,這可能是一件非常辛苦的工作。

藉由分類(classification),我們把許多具有相同屬性和方法的物件集合成一個類別(class)—例如「水果」,一旦完成這個類別的設計工作,而讓一些有部分比例屬性相同,但有部分差異的物件形成另一個類別—例如「蘋果」,讓它繼承前一個類別(水果),則在「蘋果」的類別中,我們無需去定義那些已經存在於「水果」類別中的方法和屬性。如此,我們就可以節省很多重複定義的工作時間,程式也會變得非常精簡。更重要的是,一旦我們在必要時修改了某個上層類別—如「水果」的屬性,則其繼承者—如「蘋果」會自動隨之更改,而不需要程式設計師動手去修改每一個出現這個屬性的類別。

這確實是一個令程式設計師非常方便的特性。使用「繼承」,我們可以以直覺的方式將真實世界的問題抽象化,進而在最短時間內設計出簡潔的、高度可靠的程式。

1.5  C++語言的應用

以下是一些在歐美地區使用 C++而且成功開發應用程式的領域:

商業與金融

郵件和購票系統

薪資和會計系統

存貨控制

(飛機、火車)訂位系統

文書處理

資料管理

電子試算表

EFT(電子資金轉移)

ATM(電子櫃員機)

電子郵件

24小時電子銀行

保險請求處理

工業

機器人控制

CAD(電腦輔助設計)

CAM(電腦輔助製造)

CIM(電腦整合製造)

電腦輔助生產管理

生產規劃

視覺化製程監控

電腦視覺

政府

防衛系統

太空計畫

人口普查資料分析

天氣預測

自動交通流量控制

電腦彩券

美國國家犯罪資訊系統

醫學

腦部斷層掃描和核磁共振掃描

病例資訊管理

生命維持系統的監測

電腦輔助專家診斷系統

娛樂

動畫、著色

電影特殊效果

電動玩具

科學

分析分子構造

結晶研究

遙測影像分析

食品品質測試

複雜動態系統模擬

解特殊微分方程式

上述領域只是部分應用範例,事實上有更多已經完成的或正在進行的C++語言的應用系統開發計畫,特別是在工業應用領域。根據一項199812個歐盟國家的初略估計,大概有80%的工業級應用程式研發計畫採用C++語言,7%採用C語言,其餘百分比才由其它高階語言平均分配。可見C++語言的主流地位。

1.6  發展一個C++程式的步驟

程式的目的,是為了解決問題。當我們觀察到一個問題,希望藉助電腦來解決,我們必須先有一個解決方法和程序,到目前為止,電腦還無法為人類主動創造解決問題的方法。例如當你只告訴電腦一個物體的質量和受力,電腦無法算出這個物體的加速度,除非你同時給它牛頓定律。

因此,要撰寫一個程式來解決特定問題,必需先知道解決問題的程序,這個程序就叫做演算法(algorithm)。比方我們要撰寫一個計算物體加速度的程式,可以規劃如下列演算法:

步驟一、要求使用者輸入物體的質量m

步驟二、要求使用者輸入物體的受力F

步驟三、將mF代入牛頓定律公式,求得加速度a = F / m

步驟四、將加速度值a輸出至螢幕

,使用一個文字編輯器(editor),根據演算法開始撰寫C++程式的原始碼(source code)。網路上有各式各樣免費的文字編輯器可以下載,連Windows 98所附的記事本用起來也綽綽有餘。事實上,市面上絕大多數的C++編譯器(compiler)都提供整合發展環境(IDE),其中一項必要的附件就是文字編輯器。

編輯完成C++程式碼,接著開始除錯(debug)的工作,我們必需執行編譯(compilation)。編譯的目的是把高階的C++語言程式碼轉譯成電腦可以執行的低階機器語言,這就是編譯器的主要功能。編譯器可以幫助我們找出原始碼中語法錯誤的地方,並指出錯誤的根源。瞭解程式碼程式碼的語法錯誤,我們可以立即在編譯器中進行修正,在重新編譯,直到語法完全正確無誤為止。

如果你的程式引進(include)某一些特定的函式庫,此時就應該把它們鏈結(linking)進來。除非是函式庫的檔案不存在、或指定的檔案目錄錯誤,否則這個階段通常不會有什麼問題。

最後就是執行這個程式了。程式碼沒有語法錯誤並不代表程式能夠正確執行。例如有一行C++程式碼如下:

a = F / m :

這裡有一個語法錯誤,行末的「:」應該是「;」這是語法錯誤,編譯器會找出來。但是如果寫成

a = F + m ;

那麼程式的語法沒有錯,編譯過程會順利通過。但是公式寫錯了,因為我們把除號寫成加號,編譯器無法偵測出來,但在執行的時候會產生不正確的答案。這類的錯誤稱為(run-time errors)

一旦出現執行時期錯誤,我們又需要回到文字編輯器修改原始碼。由於編譯器無法告訴我們明確的錯誤根源,這類的錯誤一般而言較難偵測。大多數整合發展環境因而提供有除錯器(debuger),除錯器可以讓程式設計師一行一行的監看程式的執行,藉以找出問題發生的位置。再回到文字編輯器修改。

總結發展一個C++程式的基本流程:

文字編輯(Edit)—編譯(compile)—鏈結(link)—執行(run)

1.7你所需要的準備工作

本書所有的實例完全根據1995ISOANSI所制訂的 C++標準而撰寫,所以讀者們應該可以使用市面上任何一個來測試或練習。書中所負的原始碼都分別使用Turbo C++ 3.0Borland C++ 5.0Borland C++ Builder 4.0測試無誤。由於Turbo C++ 3.0是一個叫早期的C++編譯器,只支援1991年所訂的標準,所以有一部分的C++特徵不能使用,像template功能,或bool基本資料型態在Turbo C++ 3.0當中都不存在。

Borland C++ 5.0Borland C++ Builder 4.0(或者它的早期版本1.02.0)都支援所有最新的C++標準。Borland C++ 5.0可以讓你開發16位元DOS的應用程式、16位元(Windows 3.1)和32位元(Windows 9598NT)的應用程式,不過現在多數程式設計師都已使用C++ Builder 取代Borland C++來開發Windows平台的應用程式,所以我們僅以Borland C++ 5.0來撰寫純文字模式(或稱為console mode)的應用程式。如果讀者想要開發Windows視覺化界面(例如選單、對話箱或結合一些影音效果等等),那麼,C++ Builder是理想的工具。

本書並不打算介紹Borland C++ 5.0C++ Builder的操作或功能的使用,有興趣的讀者可以自行參考相關的書籍。但是為了讓讀者有一個立即可用的工具,以便快速進入C++的世界,我們簡單展示了Borland C++ 5.0C++ Builder 4.0的安裝和使用的基本選項設定。

因為不打算使用Borland C++ 5.0來開發圖形界面的是窗應用程式,所以我們展示如何解除一些不必要的安裝選項,以節省硬碟空間。圖1.1到圖1.6是安裝過程幾個比較重要的設定步驟。

至於C++ Builder 4.0,如果你的硬碟夠大,建議你完全安裝。如此,一旦有需要開發一些專業級的Windows版本的應用程式時,就可立即派上用場。

1.1Borland C++ 5.0的安裝畫面,選擇custom安裝模式

1.2、選擇支援不同平台的編譯器

1.3、解除資料庫預設安裝選項

1.4、解除Examples安裝選項內的部分項目

1.5、解除Help安裝選項內的部分項目

1.6、開始安裝畫面

安裝好了軟體,我們馬上可以看看能不能用。由於本書的目的式學席C++語言程式設計,視窗軟體開發的細節並不是我們最關心的。所以在此僅展示如何使用Borland C++ 5.0C++ Builder 4.0來開發console mode的程式,並使用DOS模式執行。

1.7和圖1.8展示開啟一個新的文字編輯視窗,先預存一個新檔名在E碟的MyCPP目錄裡,往後Borland C++ 5.0在編譯、鏈結時所產生的鏈結檔和執行檔都會放在同一個目錄裡。接著,就可以在文字編輯視窗中開始撰寫原始程式碼。

1.7、開啟一個新的文字編輯視窗

1.8、預存一個新檔名在E碟的MyCPP目錄

1.9、開始撰寫原始程式碼

C++ Builder 4.0的開發環境,由於它僅支援Windows程式的開發,而且每一個程式都由一組至少4個以上的檔案構成,稱為專案(project)。所以它的操作界面也完全不同於Borland C++ 5.0。圖1.10是進入C++ Builder 4.0的整合發展環境畫面。

1.10C++ Builder 4.0的整合發展環境

1.11至圖1.13展示開啟一個新專案,並選擇專案型態為console mode

1.11、開啟一個新專案

1.12、選擇console wizard

1.13、選擇console mode

選項確定後,C++ Builder 4.0自動產生一個專案,其中主檔案包含了一個C++的主程式框架。我們把需要撰寫的程式碼填入其中就可以了。

1.14C++ Builder自動產生專案和主程式框架

接下來的工作就是撰寫程式碼了。下一章我們將介紹一個簡單的C++程式,並由這個範例導引讀者瞭解C++程式的結構、變數宣告、輸入/輸出等最基本的語法和使用。

 


 

計算機概論:C/C++程式設計

義守大學電機系 陳慶瀚  
2001.10.02