《高級(jí)程序設(shè)計(jì)技術(shù)》課件第1章_第1頁(yè)
《高級(jí)程序設(shè)計(jì)技術(shù)》課件第1章_第2頁(yè)
《高級(jí)程序設(shè)計(jì)技術(shù)》課件第1章_第3頁(yè)
《高級(jí)程序設(shè)計(jì)技術(shù)》課件第1章_第4頁(yè)
《高級(jí)程序設(shè)計(jì)技術(shù)》課件第1章_第5頁(yè)
已閱讀5頁(yè),還剩128頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第1章程序設(shè)計(jì)基礎(chǔ)

1.1.程序設(shè)計(jì)語(yǔ)言與語(yǔ)言處理程序1.2程序設(shè)計(jì)的步驟1.3程序執(zhí)行過(guò)程與編程工具1.4程序的調(diào)試方法1.5參數(shù)傳遞相關(guān)技術(shù)1.6完整的C程序結(jié)構(gòu)1.7良好的程序風(fēng)格習(xí)題1

實(shí)驗(yàn)11.1程序設(shè)計(jì)語(yǔ)言與語(yǔ)言處理程序1.1.1程序設(shè)計(jì)語(yǔ)言為了有效地實(shí)現(xiàn)人與計(jì)算機(jī)之間的通信,人們?cè)O(shè)計(jì)出多種詞匯少、語(yǔ)法簡(jiǎn)單、意義明確的適合于計(jì)算機(jī)使用的語(yǔ)言,這樣的語(yǔ)言被稱為計(jì)算機(jī)語(yǔ)言。計(jì)算機(jī)語(yǔ)言從狹義的角度看是計(jì)算機(jī)可以執(zhí)行的機(jī)器語(yǔ)言,從廣義角度看是一切用于人與計(jì)算機(jī)通信的語(yǔ)言,包括程序設(shè)計(jì)語(yǔ)言,各種專用的或通用的命令語(yǔ)言、查詢語(yǔ)言、定義語(yǔ)言等。程序設(shè)計(jì)語(yǔ)言(programminglanguage)泛指一切用于書(shū)寫(xiě)計(jì)算機(jī)程序的語(yǔ)言,包括匯編語(yǔ)言、機(jī)器語(yǔ)言,以及稱為高級(jí)語(yǔ)言的完全符號(hào)形式的、獨(dú)立于具體計(jì)算機(jī)的語(yǔ)言。程序設(shè)計(jì)語(yǔ)言是計(jì)算機(jī)語(yǔ)言的一個(gè)子集。程序設(shè)計(jì)語(yǔ)言可分為低級(jí)語(yǔ)言與高級(jí)語(yǔ)言兩大類。低級(jí)語(yǔ)言是與機(jī)器有關(guān)的語(yǔ)言,包括機(jī)器語(yǔ)言和匯編語(yǔ)言。高級(jí)語(yǔ)言是與機(jī)器無(wú)關(guān)的語(yǔ)言。

1.機(jī)器語(yǔ)言機(jī)器語(yǔ)言是以“0”、“1”二進(jìn)制代碼形式表示的機(jī)器基本指令的集合,是計(jì)算機(jī)硬件唯一可以直接識(shí)別的語(yǔ)言。機(jī)器語(yǔ)言是最早出現(xiàn)的計(jì)算機(jī)語(yǔ)言,屬于第一代程序設(shè)計(jì)語(yǔ)言。使用機(jī)器語(yǔ)言編寫(xiě)程序十分不便,因?yàn)檫@種語(yǔ)言直觀性較差,難閱讀、難修改。而且,由于每臺(tái)計(jì)算機(jī)的指令系統(tǒng)往往各不相同,因此在一臺(tái)計(jì)算機(jī)上執(zhí)行的程序要想在另一臺(tái)計(jì)算機(jī)上執(zhí)行,必須重新編寫(xiě)程序,造成了重復(fù)工作。但是,由于使用的是針對(duì)特定型號(hào)計(jì)算機(jī)的語(yǔ)言,故機(jī)器語(yǔ)言的運(yùn)算效率是所有語(yǔ)言中最高的。

2.匯編語(yǔ)言匯編語(yǔ)言是為了解決機(jī)器語(yǔ)言難于理解和記憶的缺點(diǎn),用易于理解、記憶的名稱和符號(hào)表示的機(jī)器指令。例如,用“ADD”代表加法,“MOV”代表數(shù)據(jù)傳遞等。匯編語(yǔ)言比機(jī)器語(yǔ)言直觀,使程序的編寫(xiě)、糾錯(cuò)和維護(hù)變得相對(duì)簡(jiǎn)單了,但其基本上還是一條指令對(duì)應(yīng)一種基本操作,對(duì)機(jī)器硬件十分依賴,移植性不好。由于匯編語(yǔ)言還是針對(duì)特定硬件的一種程序設(shè)計(jì)語(yǔ)言,因此效率仍十分高,能準(zhǔn)確發(fā)揮計(jì)算機(jī)硬件的功能和特長(zhǎng),程序精練而質(zhì)量高,所以至今仍是一種常用的軟件開(kāi)發(fā)工具。不論是機(jī)器語(yǔ)言還是匯編語(yǔ)言,都是面向硬件具體操作的,語(yǔ)言對(duì)機(jī)器的過(guò)分依賴要求使用者必須對(duì)硬件結(jié)構(gòu)及其工作原理都十分熟悉,這對(duì)非計(jì)算機(jī)專業(yè)人員是難以做到的,對(duì)于計(jì)算機(jī)的推廣應(yīng)用是不利的。

3.高級(jí)語(yǔ)言高級(jí)語(yǔ)言是人們?yōu)榱私鉀Q低級(jí)語(yǔ)言的不足而設(shè)計(jì)的程序設(shè)計(jì)語(yǔ)言。它是由一些接近于自然語(yǔ)言和數(shù)學(xué)語(yǔ)言的語(yǔ)句組成的,因此更接近于要解決問(wèn)題的表示方法,并在一定程度上與機(jī)器無(wú)關(guān)。用高級(jí)語(yǔ)言編寫(xiě)程序,易學(xué)、易用、易維護(hù)。但是由于機(jī)器硬件不能直接識(shí)別高級(jí)語(yǔ)言中的語(yǔ)句,因此高級(jí)語(yǔ)言必須通過(guò)編譯系統(tǒng)編譯或解釋成低級(jí)語(yǔ)言后才能被計(jì)算機(jī)執(zhí)行。高級(jí)語(yǔ)言不依賴于計(jì)算機(jī)系統(tǒng),不同的編譯程序可以把相同的高級(jí)語(yǔ)言程序編譯成不同計(jì)算機(jī)下有意義的低級(jí)語(yǔ)言,這些低級(jí)語(yǔ)言是不同的,但它們的意義是一樣的,執(zhí)行的效果也是一樣的。高級(jí)語(yǔ)言分為面向過(guò)程的語(yǔ)言和面向?qū)ο蟮恼Z(yǔ)言,現(xiàn)在面向?qū)ο蟮恼Z(yǔ)言已逐步成為程序設(shè)計(jì)的主流。用高級(jí)語(yǔ)言編程的效率高,但執(zhí)行速度沒(méi)有低級(jí)語(yǔ)言快。高級(jí)語(yǔ)言的設(shè)計(jì)是很復(fù)雜的。因?yàn)樗仨殱M足兩種不同的需要:一方面它要滿足程序設(shè)計(jì)人員的需要,可以方便、自然地描述現(xiàn)實(shí)世界中的問(wèn)題;另一方面還要能夠構(gòu)造出高效率的翻譯程序,能夠把語(yǔ)言中的所有內(nèi)容翻譯成高效的機(jī)器指令。從20世紀(jì)50年代中期第一個(gè)實(shí)用的高級(jí)語(yǔ)言誕生以來(lái),人們?cè)O(shè)計(jì)出幾百種高級(jí)語(yǔ)言,但今天實(shí)際使用的通用高級(jí)語(yǔ)言也不過(guò)數(shù)十種。下面介紹幾種目前最常用的高級(jí)語(yǔ)言。

(1)?FORTRAN語(yǔ)言。它是使用最早的高級(jí)語(yǔ)言。FORTRAN語(yǔ)言從20世紀(jì)50年代中期到現(xiàn)在,經(jīng)過(guò)幾十年的實(shí)踐檢驗(yàn),廣泛用于科學(xué)計(jì)算程序的編制,人們稱之為用于科學(xué)計(jì)算的“公式翻譯語(yǔ)言”。

(2)?COBOL語(yǔ)言。它是主要面向商業(yè)的通用語(yǔ)言,創(chuàng)始于20世紀(jì)50年代末期,使用了十分接近于英語(yǔ)的語(yǔ)句,很容易理解,在事務(wù)處理中有著廣泛的應(yīng)用。

(3)?BASIC語(yǔ)言:它是20世紀(jì)60年代初為適應(yīng)分時(shí)系統(tǒng)而研制的一種交互式語(yǔ)言,全稱是Beginner’sAllPurposeSymbolicInstructionCode,意為“初學(xué)者通用符號(hào)指令代碼”,是最容易掌握的語(yǔ)言之一。BASIC簡(jiǎn)化了FORTRAN操作,為無(wú)經(jīng)驗(yàn)的人提供一種簡(jiǎn)單的編程語(yǔ)言,目前使用仍很廣泛。VisualBASIC或QBASIC都屬于BASIC語(yǔ)言的發(fā)展,不過(guò)VisualBASIC.net和傳統(tǒng)的BASIC已經(jīng)有了很大的區(qū)別。

(4)?LOGO語(yǔ)言。1967年美國(guó)麻省理工大學(xué)為兒童設(shè)計(jì)了一種LOGO編程語(yǔ)言,用于啟發(fā)孩子們的學(xué)習(xí)與思考,于是LOGO成為一種熱門(mén)的計(jì)算機(jī)教學(xué)語(yǔ)言。

(5)?Simula67語(yǔ)言。1967年挪威科學(xué)家推出了Simula67語(yǔ)言。該語(yǔ)言第一次提出類的概念,能夠把應(yīng)用中的概念直接用編程語(yǔ)言描述。該語(yǔ)言由于一些原因沒(méi)能流行,但它是面向?qū)ο缶幊陶Z(yǔ)言的概念基礎(chǔ)。

(6)?C語(yǔ)言。C語(yǔ)言于1970年由美國(guó)貝爾實(shí)驗(yàn)室研制成功。由于它表達(dá)簡(jiǎn)潔,控制結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)完備,具有豐富的運(yùn)算符和數(shù)據(jù)類型,移植性強(qiáng),編譯質(zhì)量高,因此得到了廣泛的使用。

(7)?Pascal語(yǔ)言。它于1971年研制成功,是第一個(gè)系統(tǒng)地體現(xiàn)了結(jié)構(gòu)化程序設(shè)計(jì)概念的高級(jí)語(yǔ)言。與BASIC、C等語(yǔ)言相比,Pascal語(yǔ)言更適合科學(xué)計(jì)算,其運(yùn)行速度最快,編譯能力也最強(qiáng)。其發(fā)展從Pascal5.5、6.0、7.0一直到現(xiàn)在的Delphi、.NET。

(8)?PROLOG語(yǔ)言。它是1972年誕生于法國(guó),后來(lái)在英國(guó)得到完善和發(fā)展的一種邏輯程序設(shè)計(jì)語(yǔ)言,廣泛應(yīng)用于人工智能領(lǐng)域。

(9)?ADA語(yǔ)言。它是美國(guó)國(guó)防部直接領(lǐng)導(dǎo)下的、1975年開(kāi)始開(kāi)發(fā)的一種現(xiàn)代模塊化語(yǔ)言,便于實(shí)現(xiàn)嵌入式應(yīng)用,已被許多國(guó)家選定為軍用標(biāo)準(zhǔn)語(yǔ)言。

(10)?C++語(yǔ)言。20世紀(jì)70年代中期,BjarneStroustrup在劍橋大學(xué)計(jì)算機(jī)中心工作。他以C為背景,以Simula思想為基礎(chǔ),在1979年開(kāi)始從事將C改良為帶類的C的工作。1983年該語(yǔ)言被正式命名為C++。C++?支持C語(yǔ)言語(yǔ)法,但C++?并不只是一個(gè)C語(yǔ)言的擴(kuò)展版本。實(shí)際上,在C++?和C語(yǔ)言之間存在著一個(gè)很大的區(qū)別,就是面向?qū)ο蠛徒Y(jié)構(gòu)化思想之間的區(qū)別。C++?是面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言,而C語(yǔ)言則是一種標(biāo)準(zhǔn)的結(jié)構(gòu)化語(yǔ)言。C++?在標(biāo)準(zhǔn)化之后迅速成為了程序開(kāi)發(fā)的主流語(yǔ)言。

(11)?Java語(yǔ)言。Java是純面向?qū)ο箝_(kāi)發(fā)語(yǔ)言,也是目前非常流行的面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言之一。Java的最大優(yōu)點(diǎn)是它的跨平臺(tái)特性,即借助于運(yùn)行在不同平臺(tái)上的Java虛擬機(jī),用Java編寫(xiě)的程序可以在多種不同的操作系統(tǒng)甚至硬件平臺(tái)上運(yùn)行,實(shí)現(xiàn)“一次編寫(xiě),處處運(yùn)行”。Java的語(yǔ)法和C++?具有很多相似的地方,因此,如果在學(xué)習(xí)Java之前就已經(jīng)對(duì)C++?比較了解了,可能會(huì)感覺(jué)比較容易一些。不過(guò)C++?有一些特性卻是Java沒(méi)有的。

(12)?C#?語(yǔ)言。C#?是Microsoft公司設(shè)計(jì)的下一代面向?qū)ο蟮恼Z(yǔ)言產(chǎn)品。微軟給它的定義是:“C#?是從C和C++?派生出來(lái)的一種簡(jiǎn)單、現(xiàn)代、面向?qū)ο蠛皖愋桶踩木幊陶Z(yǔ)言。C#試圖結(jié)合VisualBASIC的快速開(kāi)發(fā)能力和C++?的強(qiáng)大靈活的能力。”C#?有很多方面和Java類似。隨著可視化技術(shù)的發(fā)展,出現(xiàn)了VisualBASIC、VisualC++、Delphi、.NET等可視化的開(kāi)發(fā)環(huán)境,更加方便了程序員寫(xiě)出更有效率的軟件。1.1.2語(yǔ)言處理程序用高級(jí)程序設(shè)計(jì)語(yǔ)言編寫(xiě)程序,通常要經(jīng)過(guò)編輯、語(yǔ)言處理、裝配連接后,才能夠在計(jì)算機(jī)上運(yùn)行。編輯是指計(jì)算機(jī)通過(guò)編輯程序?qū)⑷藗兙帉?xiě)的源程序送入計(jì)算機(jī)。編輯程序可以使用戶方便地修改源程序,包括添加、刪除、修改等,直到用戶滿意為止。語(yǔ)言處理程序是把用一種程序設(shè)計(jì)語(yǔ)言表示的程序轉(zhuǎn)換為與之等價(jià)的另一種程序設(shè)計(jì)語(yǔ)言表示的程序的處理程序。在計(jì)算機(jī)軟件中經(jīng)常用到的語(yǔ)言處理程序是把匯編語(yǔ)言或高級(jí)語(yǔ)言“翻譯”成機(jī)器語(yǔ)言的翻譯程序。被翻譯的程序稱為源程序或源代碼,經(jīng)過(guò)翻譯程序“翻譯”出來(lái)的結(jié)果程序稱為目標(biāo)程序。翻譯程序有兩種典型的實(shí)現(xiàn)途徑,分別稱為解釋方式與編譯方式。

(1)解釋方式。解釋方式是按照源程序中語(yǔ)句的執(zhí)行順序,逐句翻譯并立即予以執(zhí)行。即由事先放入計(jì)算機(jī)中的解釋程序把匯編語(yǔ)言或高級(jí)語(yǔ)言源程序語(yǔ)句逐條翻譯成機(jī)器語(yǔ)言,翻譯一句執(zhí)行一句,直到程序全部翻譯、執(zhí)行完為止,如圖1.1所示。解釋方式類似于人類不同語(yǔ)言的口譯工作。翻譯員(解釋程序)拿著外文版的說(shuō)明書(shū)(源程序)在車(chē)間現(xiàn)場(chǎng)對(duì)操作員作現(xiàn)場(chǎng)指導(dǎo)。對(duì)說(shuō)明書(shū)上的語(yǔ)句,翻譯員逐條譯給操作員聽(tīng);操作員根據(jù)聽(tīng)到的話(他能懂的語(yǔ)言)進(jìn)行操作。翻譯員每翻譯一句,操作員就執(zhí)行該句規(guī)定的操作。翻譯員翻譯完全部說(shuō)明書(shū),操作員也執(zhí)行完所需全部操作。由于未保留翻譯的結(jié)果,因此若需再次操作,仍要由翻譯員翻譯,操作員操作。圖1.1解釋過(guò)程示意圖

(2)編譯方式。編譯方式先由翻譯程序把源程序靜態(tài)地翻譯成目標(biāo)程序,然后執(zhí)行并得到結(jié)果,如圖1.2所示。這種實(shí)現(xiàn)途徑可以劃分為兩個(gè)明顯的階段:前一階段稱為生成階段;后一階段稱為連接運(yùn)行階段。采用這種途徑實(shí)現(xiàn)的翻譯程序,如果源語(yǔ)言是一種高級(jí)語(yǔ)言,目標(biāo)語(yǔ)言是某一計(jì)算機(jī)的機(jī)器語(yǔ)言或匯編語(yǔ)言,則這種翻譯程序稱為編譯程序。如果源語(yǔ)言是計(jì)算機(jī)的匯編語(yǔ)言,目標(biāo)語(yǔ)言是相應(yīng)計(jì)算機(jī)的機(jī)器語(yǔ)言,則這種翻譯程序稱為匯編程序。圖1.2編譯過(guò)程示意圖編譯方式類似于不同語(yǔ)言的筆譯工作。例如,某國(guó)的一個(gè)作家發(fā)表了某個(gè)劇本(源程序),我們計(jì)劃在國(guó)內(nèi)上演。首先必須由懂得該國(guó)語(yǔ)言的翻譯(編譯程序)把該劇本筆譯成中文本(目的程序)。翻譯工作結(jié)束,得到了中文本后,才能交給演出單位(計(jì)算機(jī))去演(執(zhí)行)這個(gè)中文本(目標(biāo)程序)。在后面的演出(執(zhí)行)階段,并不需要原來(lái)的外文劇本(源程序),也不需要翻譯(編譯程序)。正像只懂漢語(yǔ)的人與只懂英語(yǔ)的人交談需要英語(yǔ)翻譯,與只懂日語(yǔ)的人交談就需要日語(yǔ)翻譯一樣,使用不同的高級(jí)語(yǔ)言也需要不同的翻譯程序。如果使用BASIC語(yǔ)言,需要在計(jì)算機(jī)系統(tǒng)中安裝BASIC語(yǔ)言的解釋程序或編譯程序;如果使用C語(yǔ)言,就需要在機(jī)器內(nèi)安裝C編譯程序。如果機(jī)器內(nèi)沒(méi)有安裝匯編語(yǔ)言或高級(jí)語(yǔ)言的翻譯程序,計(jì)算機(jī)是決不能夠理解用相應(yīng)語(yǔ)言編寫(xiě)的程序的。比較而言,在翻譯同樣一篇外文文章的情況下,逐句翻譯比整篇翻譯的效率低,但一種語(yǔ)言的翻譯程序類型不是由使用者,而是由系統(tǒng)軟件的生產(chǎn)者決定的。目標(biāo)程序只是一個(gè)個(gè)獨(dú)立的程序段,還不能直接執(zhí)行,因?yàn)槌绦蛑杏玫降膸?kù)函數(shù)和一些其他資源還沒(méi)有掛上,所以需要進(jìn)行連接。連接的作用就是將各個(gè)目標(biāo)程序,包括庫(kù)函數(shù)等整合成一個(gè)可執(zhí)行文件。1.2程序設(shè)計(jì)的步驟程序設(shè)計(jì)的基本過(guò)程一般由分析問(wèn)題、抽象數(shù)學(xué)模型、選擇合適算法、編寫(xiě)程序、調(diào)試運(yùn)行程序及整理結(jié)果幾個(gè)階段構(gòu)成,如圖1.3所示。圖1.3用計(jì)算機(jī)解決問(wèn)題的基本過(guò)程分析問(wèn)題:對(duì)要解決的問(wèn)題進(jìn)行分析,理解題意。抽象數(shù)學(xué)模型:找出問(wèn)題的運(yùn)算操作與變化規(guī)律,經(jīng)歸納,建立數(shù)學(xué)模型,確定問(wèn)題的解決方案。選擇合適算法:根據(jù)特定的數(shù)學(xué)模型,選擇適合用計(jì)算機(jī)解決問(wèn)題的算法,可將處理思路用流程圖表示出來(lái)。(算法描述的主要流程圖參見(jiàn)6.1.3節(jié)。)編寫(xiě)程序:選擇一種程序設(shè)計(jì)語(yǔ)言,按算法思路編寫(xiě)程序。調(diào)試運(yùn)行程序:調(diào)試運(yùn)行程序,得到執(zhí)行結(jié)果。整理結(jié)果:對(duì)程序的執(zhí)行結(jié)果進(jìn)行分析。如果發(fā)現(xiàn)錯(cuò)誤,找出錯(cuò)誤原因,重新調(diào)試,并形成試驗(yàn)報(bào)告。下面以一個(gè)古代的“百錢(qián)百雞”問(wèn)題為例進(jìn)一步說(shuō)明。中國(guó)古代數(shù)學(xué)家張丘建在他的《算經(jīng)》中提出了著名的“百錢(qián)百雞問(wèn)題”:雞翁一,值錢(qián)五;雞母一,值錢(qián)三;雞雛三,值錢(qián)一;百錢(qián)買(mǎi)百雞,翁、母、雛各幾何?

1.分析問(wèn)題這是一個(gè)典型的數(shù)值型問(wèn)題。對(duì)于簡(jiǎn)單的問(wèn)題,這一步驟通常在腦子里會(huì)一閃而過(guò),明白題意后,進(jìn)行下一步。

2.抽象數(shù)學(xué)模型對(duì)于簡(jiǎn)單的問(wèn)題,數(shù)學(xué)模型也就是我們平時(shí)說(shuō)的數(shù)學(xué)方程。復(fù)雜的問(wèn)題可能會(huì)涉及數(shù)據(jù)結(jié)構(gòu)等因素。假設(shè)要買(mǎi)x只公雞、y只母雞、z只小雞,根據(jù)題目的意思可以得到兩個(gè)方程:x?+?y?+?z?=?100?①

根據(jù)題目的意思,可以確定x和y的取值范圍:0≤x、y、z≤100。

3.確定算法本題可采用窮舉法進(jìn)行求解。對(duì)于變量x、y、z的不同組合,看它們是否滿足上面的兩個(gè)方程。如果滿足了,就是問(wèn)題的一個(gè)解;如果不滿足,就不是問(wèn)題的解。采用三重嵌套的循環(huán)對(duì)變量x、y、z進(jìn)行組合。

4.編寫(xiě)程序

【程序1.1】#include<stdio.h>main(){intx,y,z,j=0; /*j為計(jì)數(shù)器,記錄解的數(shù)量*/for(x=0;x<=100;x++) /*窮舉變量x*/for(y=0;y<=100;y++) /*窮舉變量y*/for(z=0;z<=100;z++) /*窮舉變量z*/if(x+y+z==100&&5*x+3*y+z/3==100) /*判斷是否滿足兩個(gè)方程*/printf("%2d:cock=%2dhen=%2dchicken=%2d\n",++j,x,y,z);}

5.調(diào)試運(yùn)行

1:cock=0hen=25chicken=75

2:cock=3hen=20chicken=77

3:cock=4hen=18chicken=78

4:cock=7hen=13chicken=80

5:cock=8hen=11chicken=81

6:cock=11?hen=6chicken=83

7:cock=12?hen=4chicken=84

6.整理結(jié)果第2、4、6組解中,小雞的數(shù)量不能被3整除。問(wèn)題到底出在什么地方呢?我們進(jìn)行進(jìn)一步分析,將這些解代入方程②,可以看到:顯然,這三組解不滿足數(shù)學(xué)方程,但由于我們?cè)贑語(yǔ)言中進(jìn)行整型除法時(shí),77/3的結(jié)果就是25,80/3的結(jié)果就是26,83/3的結(jié)果就是27,也就是說(shuō),計(jì)算機(jī)在進(jìn)行整型數(shù)據(jù)除法運(yùn)算時(shí),對(duì)于商的小數(shù)部分不再進(jìn)行處理,而是直接截?cái)唷K跃驮斐闪嗽跀?shù)學(xué)上本來(lái)不成立的方程,在計(jì)算機(jī)中成立了。產(chǎn)生這個(gè)問(wèn)題的根本原因,就是我們?cè)诜治鰡?wèn)題的過(guò)程中忽略了一個(gè)重要條件,變量z要能夠被3整除。為了解決這個(gè)問(wèn)題,應(yīng)在原來(lái)兩個(gè)方程的基礎(chǔ)上增加一個(gè)判斷條件:

z%3==0因此,得到程序1.2。【程序1.2】

#include<stdio.h>

main()

{intx,y,z,j=0;

for(x=0;x<=100;x++)

for(y=0;y<=100;y++)

for(z=0;z<=100;z++)

if(z%3==0&&x+y+z==100&&5*x+3*y+z/3==100)

printf("%2d:cock=%2dhen=%2dchicken=%2d\n",++j,x,y,z);}

運(yùn)行結(jié)果:

1:cock=0hen=25chicken=75

2:cock=4hen=18chicken=78

3:cock=8hen=11chicken=81

4:cock=12hen=4chicken=84

結(jié)果正確。思考:該問(wèn)題可否有更快的解法?1.3程序執(zhí)行過(guò)程與編程工具1.3.1C源程序執(zhí)行過(guò)程一個(gè)C源程序從輸入到執(zhí)行需要經(jīng)過(guò)編輯、編譯、連接、執(zhí)行這些步驟。

1.編輯編輯源程序的作用是建立與修改源程序。編輯的對(duì)象是源程序,源程序是以ASCII碼的方式輸入與存儲(chǔ)的。Windows中的記事本以及1.3.2節(jié)介紹的編程工具均帶有編輯功能。

2.編譯所謂編譯,就是將編寫(xiě)好的源程序翻譯為二進(jìn)制的目標(biāo)代碼,由相應(yīng)的編譯程序來(lái)完成。不同的高級(jí)語(yǔ)言需要不同的編譯程序。編譯以后產(chǎn)生的二進(jìn)制目標(biāo)代碼一般擴(kuò)展名為obj,它不能直接運(yùn)行。

3.連接編譯產(chǎn)生的二進(jìn)制目標(biāo)代碼是對(duì)每一個(gè)模塊直接翻譯產(chǎn)生的,需要將各個(gè)模塊與系統(tǒng)模塊相連接,才可以產(chǎn)生后綴為?.exe的可執(zhí)行文件。

4.執(zhí)行運(yùn)行可執(zhí)行文件就可以獲得我們所需要的結(jié)果。圖1.4表示了從輸入源程序到產(chǎn)生可執(zhí)行目標(biāo)程序的全過(guò)程。圖1.4C源程序從編輯到運(yùn)行的過(guò)程

1.3.2C語(yǔ)言編程工具介紹很多初學(xué)者將C、TurboC(簡(jiǎn)稱TC)、VisualC++(簡(jiǎn)稱VC)等的關(guān)系搞不清楚,認(rèn)為T(mén)C和VC也是一種編程語(yǔ)言。正確理解是:C是一種編程語(yǔ)言,TC和VC都是C的集成開(kāi)發(fā)環(huán)境。集成開(kāi)發(fā)環(huán)境(IntegeratedDevelopmentEnvironment,IDE)是一種集成了代碼編輯器、編譯器、調(diào)試器以及執(zhí)行等與開(kāi)發(fā)有關(guān)的實(shí)用工具的軟件。由于大部分常用工具都集成在一起了,因此使用IDE來(lái)進(jìn)行開(kāi)發(fā)效率會(huì)很高。下面主要介紹C語(yǔ)言的三種集成開(kāi)發(fā)環(huán)境。

1.TurboC

TurboC(簡(jiǎn)稱TC)是Borland公司開(kāi)發(fā)的DOS下16位C語(yǔ)言集成開(kāi)發(fā)工具,目前主要有2.0和3.0版本。2.0版本只支持C語(yǔ)言的編譯且不支持鼠標(biāo)操作,還需設(shè)置路徑;而3.0版本可以支持C/C++?兩種語(yǔ)言編譯,而且還支持鼠標(biāo)和“//”注釋方式,并且在安裝好后就可以使用,無(wú)需設(shè)置。由于TC最初是在DOS環(huán)境下使用的,一切都需要用鍵盤(pán)來(lái)操作,對(duì)目前絕大多數(shù)習(xí)慣用鼠標(biāo)的Windows用戶來(lái)說(shuō),很不方便。但TC的編譯速度快,代碼執(zhí)行速度高,程序調(diào)試也比較方便,界面簡(jiǎn)單,因此很多高校一般以TC為IDE開(kāi)發(fā)環(huán)境講授C語(yǔ)言。

(1)啟動(dòng)TC。雙擊TC文件夾下的TC.exe(?.exe由于設(shè)置不同可能不顯示),出現(xiàn)如圖1.5所示界面。按Esc鍵后,出現(xiàn)黃色光標(biāo)閃爍,此時(shí)就可以編寫(xiě)程序了。圖1.5TC界面屏幕最上方是程序下拉菜單,下面是程序的編輯區(qū)域。在編輯窗口上方,是所編輯程序文件的相關(guān)信息。如Line表示正在編輯的行號(hào),Col表示正在編輯的列號(hào),Insert表示正在插入狀態(tài)下編輯,“C:NONAME.C”表示正在編輯的程序文件名以及存放盤(pán)符。特別提示:在編輯的過(guò)程中有時(shí)候會(huì)不小心按下鍵盤(pán)的Insert鍵,這會(huì)把輸入時(shí)的插入狀態(tài)變?yōu)楦膶?xiě)狀態(tài),Insert提示也消失。此時(shí)按下一個(gè)鍵后,光標(biāo)所在位置的原來(lái)字符就會(huì)被改寫(xiě)為當(dāng)前按下的字符。若要回到插入狀態(tài),只需再次按下Insert鍵即可。編輯區(qū)域的下方是Message窗口,編譯程序時(shí),可顯示編譯的相關(guān)信息。按F5鍵可關(guān)閉該窗口。窗口最下方是一些常用快捷鍵

(2)編寫(xiě)程序與保存。編寫(xiě)程序時(shí)為了使程序美觀、易懂,最好按層次縮進(jìn),而不是全部左對(duì)齊。在編寫(xiě)程序之前、中間或結(jié)束后都可以對(duì)程序進(jìn)行保存。保存程序時(shí)選擇“File”菜單下的“Save”命令,或按F2鍵,在彈出的窗口中輸入程序存放的路徑和程序名稱即可,如圖1.6所示。圖1.6保存程序

特別提示:很多初學(xué)者在編寫(xiě)了十幾行甚至更多代碼時(shí),程序的名稱還是默認(rèn)名稱“NONAME.C”,如果此時(shí)電腦出現(xiàn)故障,死機(jī)或斷電,所編寫(xiě)的代碼就會(huì)丟失。因此,建議在編寫(xiě)幾行代碼后即保存程序,之后在編寫(xiě)若干行后,直接按F2鍵進(jìn)行快捷保存。另外程序編譯和執(zhí)行前也最好先保存,以免程序運(yùn)行崩潰而造成代碼丟失。

(3)編譯與連接。“Compile”菜單下的“CompiletoOBJ”、“MakeEXEfile”,“LinkEXEfile”分別是“編譯為目標(biāo)代碼”、“生成可執(zhí)行文件”、“連接為可執(zhí)行文件”。以上步驟可按F9鍵一步完成。此時(shí),程序如果有錯(cuò)誤,就會(huì)在Message窗口中顯示相關(guān)錯(cuò)誤信息。

(4)運(yùn)行與查看程序結(jié)果。選擇“Run”菜單下的“Run”,或按Ctrl+F9鍵運(yùn)行程序,程序界面閃了一下,此時(shí),程序已經(jīng)執(zhí)行完成。選擇“Run”菜單下的“UserScreen”或按Alt+F5鍵,可將界面切換到用戶界面,以觀察程序結(jié)果。之后按任意鍵可回到編輯窗口。特別提示:F9鍵用于編譯、連接;Ctrl?+?F9鍵用于執(zhí)行可執(zhí)行程序,如果按Ctrl?+?F9鍵時(shí)沒(méi)有可執(zhí)行的程序,則其自動(dòng)生成可執(zhí)行程序而后再執(zhí)行,如圖1.7所示。在程序最后加入getchar();語(yǔ)句,程序執(zhí)行完后會(huì)自動(dòng)停留在用戶界面下,供用戶觀察結(jié)果,省去了按Alt+F5鍵的麻煩。圖1.7TC環(huán)境下C源程序從編輯到運(yùn)行的過(guò)程在TC下編寫(xiě)C程序的過(guò)程總結(jié)如下:●打開(kāi)TC。雙擊TC目錄下的TC.exe?!窬帉?xiě)代碼。如果要打開(kāi)已有的文件,按F3鍵?!癖4嫖募?。用File菜單中的Save或Writeto保存。●編譯、連接。直接按F9鍵,如果沒(méi)有錯(cuò)誤則提示成功;否則會(huì)提示出錯(cuò),調(diào)試并修改錯(cuò)誤后繼續(xù)編譯、連接●運(yùn)行、測(cè)試。按Ctrl?+?F9鍵?!窨唇Y(jié)果。按Alt?+?F5鍵。

(5)?TC使用中常見(jiàn)問(wèn)題。開(kāi)始使用TC時(shí),同學(xué)們經(jīng)常會(huì)被下面兩個(gè)編譯錯(cuò)誤所困擾,

Unabletoopenincludefile'XXX.h'

Unabletoopeninputfile'COS.OBJ'這些都是因?yàn)闆](méi)有設(shè)置好路徑引起的。TC一般有兩種版本:一種是下載后需要安裝的,安裝過(guò)程中路徑已經(jīng)設(shè)置好;另一種是不需要安裝的。我們一般使用的是第二種版本,此時(shí),路徑的設(shè)置就很重要。要正確設(shè)置路徑,首先需要了解幾個(gè)路徑的含義:

Includedirectories:TC頭文件路徑。

Librarydirectories:TC庫(kù)文件路徑。

Outputdirectories:輸出文件路徑,即obj與exe文件的存放路徑。

TurboCdirectories:TC路徑。假設(shè)TC文件夾被放在F盤(pán),如圖1.8所示。圖1.8TC的假設(shè)路徑那么,路徑的設(shè)置應(yīng)該為:

Includedirectories:F:\TC\Include

Librarydirectories:F:\TC\Lib

Outputdirectories:

TurboCdirectories:F:\TC如果不設(shè)置輸出文件路徑,那么源程序在編譯、連接過(guò)程中產(chǎn)生的?.obj和?.exe文件默認(rèn)放在TC目錄下,這樣會(huì)使得TC目錄下很混亂。因此,建議大家設(shè)置該路徑。

2.?Win-TC

Win-TC是一個(gè)TCWindows平臺(tái)開(kāi)發(fā)工具。該軟件使用TC為內(nèi)核,提供Windows平臺(tái)的開(kāi)發(fā)界面,因此也就支持Windows平臺(tái)下的功能,例如剪切、復(fù)制、粘貼和查找替換等,方便了程序修改。

Win-TC需要安裝,讀者可從網(wǎng)上下載,默認(rèn)安裝即可。不過(guò),如果想看到執(zhí)行結(jié)果,就一定要在程序最后加上getch()。另外,Win-TC沒(méi)有提供程序調(diào)試工具,這點(diǎn)極大地限制了其推廣使用。圖1.9是Win-TC的界面。圖1.9Win-TC界面

3.?VisualC++

VisualC++(以下簡(jiǎn)稱VC)是一個(gè)面向?qū)ο蟮目梢暬_(kāi)發(fā)環(huán)境,主要支持C++?語(yǔ)言,但也可以運(yùn)行C程序。VC運(yùn)行于Windows下,因此習(xí)慣了圖形界面的用戶非常容易接受。VC需要安裝,本書(shū)以使用比較普遍的VisualC++?6.0?為例,介紹如何在VC環(huán)境下編寫(xiě)C程序。圖1.10啟動(dòng)VisualC++6.0圖1.11VisualC++6.0界面

(2)創(chuàng)建文件。選擇菜單“File”→“New”,在彈出的對(duì)話框中選擇“File”選項(xiàng)卡,在左邊的列表中選擇“C++SourceFile”,同時(shí)在右邊輸入文件的名稱以及保存位置,如圖1.12所示。點(diǎn)擊“OK”鍵,在出現(xiàn)的白色區(qū)域內(nèi)編寫(xiě)代碼,如圖1.13所示。圖1.12給文件起名圖1.13VC程序邊界界面在TC環(huán)境下,我們雖然使用“stdio.h”文中的printf()?和scanf()?等函數(shù),但可以不包含“stdio.h”頭文件,因?yàn)镃編譯器能找到它們。但在VC環(huán)境下,使用任何函數(shù)時(shí)都必須包含其所在的頭文件。另外,在TC環(huán)境下,main()函數(shù)的返回值類型可以不寫(xiě)(此時(shí)默認(rèn)是int類型),函數(shù)體中也可以不出現(xiàn)return語(yǔ)句;但在VC環(huán)境下,一個(gè)函數(shù)如果有返回值,則函數(shù)體中一定要有return語(yǔ)句,若函數(shù)沒(méi)有返回值,則必須寫(xiě)上void,這點(diǎn)要求比較嚴(yán)格。

(3)編譯、連接與運(yùn)行。選擇菜單“Build”→“CompileHello.c”,會(huì)彈出一個(gè)對(duì)話框,如圖1.14所示,選擇“是(Y)”,如果程序沒(méi)有錯(cuò)誤,則在下方會(huì)出現(xiàn)編譯成功的提示,如圖1.15所示。圖1.14編譯時(shí)的提示圖1.15編譯成功我們知道,編譯的結(jié)果是生成了目標(biāo)文件Hello.obj,還不能運(yùn)行,必須通過(guò)連接生成可執(zhí)行文件Hello.exe之后才能運(yùn)行。選擇菜單“Build”→“BuildHello.exe”,會(huì)生成可執(zhí)行文件“Hello.exe”。最后,選擇菜單“Build”→“!ExecuteHello.exe”,執(zhí)行程序,程序的運(yùn)行結(jié)果會(huì)顯示出來(lái),如圖1.16所示。圖1.16程序運(yùn)行結(jié)果通常我們喜歡將編譯、連接一起進(jìn)行,因此,可以直接選擇菜單“Build”→“BuildHello.exe”進(jìn)行連接,中間會(huì)自動(dòng)進(jìn)行編譯?;蛘甙垂ぞ邫谏系膱D標(biāo)(編譯)、(連接)、

(執(zhí)行)進(jìn)行編譯、連接與運(yùn)行。在文件保存路徑“C:\CTest”下除了生成“Hello.obj”和“Hello.exe”文件之外,還生成如圖1.17所示的文件(夾)。圖1.17VC環(huán)境下運(yùn)行C程序生成的文件特別提示:作為初學(xué)者,我們除了關(guān)心?.c文件、.obj文件和?.exe文件之外,其余的文件可暫時(shí)不予關(guān)心。其中?.obj和?.exe文件都在Debug文件夾下。Debug文件夾一般都比較大,因此如果要拷走程序,只需拷貝?.c文件,在目標(biāo)環(huán)境下重新生成?.obj和?.exe文件即可。除了上述的三種C語(yǔ)言編程工具外,還有BolandC也比較常用,感興趣的讀者可以找有關(guān)資料去學(xué)習(xí)。

IDE開(kāi)發(fā)環(huán)境只是方便了程序的編寫(xiě)、編譯、運(yùn)行和調(diào)試,程序設(shè)計(jì)的核心還是程序設(shè)計(jì)語(yǔ)言。因此,學(xué)好程序設(shè)計(jì)語(yǔ)言才是根本。作者推薦使用TC2.0或VC6.0作為C語(yǔ)言的IDE開(kāi)發(fā)環(huán)境。1.4程序的調(diào)試方法很多初學(xué)者在調(diào)試完程序的語(yǔ)法錯(cuò)誤后,以為大功告成,但執(zhí)行完程序后,結(jié)果卻很讓人失望。此時(shí),他們往往不知所措,不知道程序什么地方出錯(cuò)了,不知道下一步該怎么修改。下面我們一起來(lái)解決這些問(wèn)題。1.4.1錯(cuò)誤分類程序中常見(jiàn)的錯(cuò)誤有三種:語(yǔ)法錯(cuò)誤、運(yùn)行錯(cuò)誤和邏輯錯(cuò)誤。語(yǔ)法錯(cuò)誤是不符合程序設(shè)計(jì)語(yǔ)言語(yǔ)法規(guī)則的錯(cuò)誤,這類錯(cuò)誤通常在源程序被編譯時(shí)就能及時(shí)發(fā)現(xiàn)(系統(tǒng)提示出錯(cuò)信息),因此比較容易修改。運(yùn)行錯(cuò)誤是程序在運(yùn)行過(guò)程中產(chǎn)生的,比如除數(shù)為0錯(cuò)誤、數(shù)組下標(biāo)越界錯(cuò)誤、空指針或錯(cuò)誤指針錯(cuò)誤。這類錯(cuò)誤有時(shí)候會(huì)導(dǎo)致程序異常終止,有時(shí)候會(huì)產(chǎn)生莫名奇妙的結(jié)果,一般需要程序員的細(xì)心才能發(fā)現(xiàn)。邏輯錯(cuò)誤是指程序運(yùn)行后得不到所期望的結(jié)果(或正確的結(jié)果),也就是說(shuō)程序并沒(méi)有按照程序設(shè)計(jì)者的思路來(lái)運(yùn)行。比如一個(gè)最簡(jiǎn)單例子是:我們的目的是求兩個(gè)數(shù)的和,應(yīng)該寫(xiě)成C?=?A?+?B;,由于書(shū)寫(xiě)錯(cuò)誤寫(xiě)成了C?=?A?-?B;,這就是邏輯錯(cuò)誤。邏輯錯(cuò)誤是編譯程序發(fā)現(xiàn)不了的,也是最不容易修改的,一般要用戶通過(guò)單步跟蹤運(yùn)行過(guò)程才能發(fā)現(xiàn)。下面列出一些初學(xué)者常犯的錯(cuò)誤。1.編程功底不牢固

(1)少加括號(hào)。如經(jīng)常有類似下面的程序出現(xiàn):

for(i=0;i<n;i++)

j=i*i;

printf("%d*%d=%d\n",i,i,j);該程序的本意是執(zhí)行一次for循環(huán)時(shí)執(zhí)行循環(huán)體內(nèi)的2條語(yǔ)句,但因?yàn)槿鄙倮ㄌ?hào),使得結(jié)果大不一樣!

(2)忘記加分號(hào)。這種錯(cuò)誤在編譯時(shí)就能發(fā)現(xiàn),但一般被指出有錯(cuò)的一行并不會(huì)發(fā)現(xiàn)錯(cuò)誤,此時(shí)需要看一下上一行是否漏掉了分號(hào)。

(3)多加分號(hào)。如:

inti,k=0;

for(i=0;i<10;i++);

if(i%2==0)k++;最后的if語(yǔ)句本來(lái)應(yīng)在for循環(huán)內(nèi),現(xiàn)在卻在for循環(huán)之外了。

(4)輸入變量時(shí)少加&。如:

inta,b;

scanf("%d%d",a,b);這是不合法的,因?yàn)閟canf函數(shù)的作用是按照a、b在內(nèi)存的地址將a、b的值存進(jìn)去,所以要加&。

(5)輸入字符串時(shí)多加了&。如:

charstr[50];

scanf("%s",&str);數(shù)組名本身就是地址,因此不需要加&。

(6)變量輸入方式與要求方式不符。如:

scanf("%d%d",&a,&b);輸入時(shí)不能用逗號(hào)作兩個(gè)數(shù)據(jù)間的分隔符,那么下面的輸入方式不合法:

3,4

輸入數(shù)據(jù)時(shí),在兩個(gè)數(shù)據(jù)之間以一個(gè)或多個(gè)空格間隔,也可用回車(chē)鍵、跳格鍵Tab間隔。如對(duì)于

scanf("%d,%d",&a,&b);在“格式控制”字符串中除了格式說(shuō)明以外還有其他字符,則在輸入數(shù)據(jù)時(shí)應(yīng)輸入與這些字符相同的字符。合法的輸入是:

3,4

若此時(shí)不用逗號(hào)而用空格或其他字符是不對(duì)的,不合法的輸入是:

34

或3:4

如對(duì)于

scanf("a=%d,b=%d",&a,&b);輸入應(yīng)如以下形式:

a=3,b=4

如:

scanf("%7.2f",&a);這樣寫(xiě)是不合法的,因?yàn)檩斎霐?shù)據(jù)時(shí)不能規(guī)定精度。

(7)字符輸入問(wèn)題。在用“%c”格式輸入字符時(shí),“空格字符”和“轉(zhuǎn)義字符”都作為有效字符輸入。如:

scanf("%c%c%c",&c1,&c2,&c3);如果輸入:abc

,則將字符“a”送給c1,字符“”送給c2,字符“b”送給c3,因?yàn)?c只要求讀入一個(gè)字符,不需要用空格作為兩個(gè)字符的間隔。以下輸入合法:

abc

(將“a”送給c1,“b”送給c2,“c”送給c3)當(dāng)在一個(gè)字符前面輸入過(guò)其他類型數(shù)據(jù)時(shí),因?yàn)榇_認(rèn)輸入時(shí)用過(guò)回車(chē),因此后面的字符輸入就會(huì)“跳過(guò)”,而直接將回車(chē)送入該字符。如對(duì)于

scanf("%s",str);

scanf("%c",&c);輸入:northwest

,則輸入結(jié)束,原因是將“northwest”送入str,將“\n”送入c。這種問(wèn)題的解決辦法是在輸入單個(gè)字符前加fflush(stdin)函數(shù),清空輸入流緩沖區(qū),即

scanf("%s",str);

fflush(stdin);

scanf("%c",&c);

(8)字符串輸入。字符串輸入時(shí),以空格或回車(chē)作為結(jié)束標(biāo)志。如對(duì)于

scanf("%s",name);輸入:Wangmeili

,則name中的值為“wang”,而不是“wangmeili”。

(9)定義數(shù)組時(shí)誤用變量。如:

intn;

scanf("%d",&n);

inta[n];數(shù)組名后用方括號(hào)括起來(lái)的是常量表達(dá)式,可以包括常量和符號(hào)常量,不能是變量即C不允許對(duì)數(shù)組的大小作動(dòng)態(tài)定義。

(10)在定義數(shù)組時(shí),將定義的“元素個(gè)數(shù)”誤認(rèn)為是可使用的最大下標(biāo)值。如:

main()

{staticinta[10]={1,2,3,4,5,6,7,8,9,10};

printf("%d",a[10]);

}

C語(yǔ)言規(guī)定:定義時(shí)用a[10],表示a數(shù)組有10個(gè)元素,其下標(biāo)值由0開(kāi)始,所以數(shù)組元素a[10]是不存在的。

2.書(shū)寫(xiě)錯(cuò)誤

(1)函數(shù)名字書(shū)寫(xiě)錯(cuò)誤,一般在連接時(shí)會(huì)提示出錯(cuò),比較容易修改。

(2)變量書(shū)寫(xiě)錯(cuò)誤,包括大小寫(xiě)錯(cuò)誤、漏寫(xiě)或多寫(xiě)字符。如果寫(xiě)錯(cuò)的變量本身沒(méi)有定義,編譯時(shí)會(huì)提示出錯(cuò)。但如果寫(xiě)錯(cuò)的變量本身已經(jīng)定義,比如在表達(dá)式中用到變量j時(shí)誤寫(xiě)成了i,那么編譯程序是找不出來(lái)的,修改這種錯(cuò)誤只能靠用戶自己細(xì)心查找。

(3)“=”與“==”的錯(cuò)誤。如:

if(a=3)

printf("thevalueofais3");該語(yǔ)句的本意是判斷變量a的值是否等于3,如果等于3,則輸入一句話。但寫(xiě)成上述語(yǔ)句之后,無(wú)論a是否等于3,都會(huì)輸出“thevalueofais3”,并且將a的值改為3,因?yàn)椤?”是賦值而不是判斷是否相等。

3.括號(hào)不完整大、小括號(hào)經(jīng)常不成對(duì)出現(xiàn)。該錯(cuò)誤也很好避免,那就是在需要用到括號(hào)的時(shí)候,先把一對(duì)括號(hào)都打出來(lái),然后在中間輸入,這樣就不會(huì)忘記另一半括號(hào)了。

4.縮進(jìn)格式這本身不是一種錯(cuò)誤,但如果編寫(xiě)的程序沒(méi)有任何格式,則其可讀性很差,格式的混亂經(jīng)常會(huì)直接導(dǎo)致邏輯錯(cuò)誤。如果正確地運(yùn)用縮進(jìn)格式,大部分的錯(cuò)誤就會(huì)一目了然。1.4.2調(diào)試方法

1.靜態(tài)查錯(cuò)靜態(tài)查錯(cuò)是指不執(zhí)行程序,僅根據(jù)程序和框圖對(duì)求解過(guò)程的描述來(lái)發(fā)現(xiàn)錯(cuò)誤。由于有些錯(cuò)誤在運(yùn)行時(shí)很難查出,但在靜態(tài)查錯(cuò)中卻容易發(fā)現(xiàn),比如說(shuō)前面說(shuō)到的書(shū)寫(xiě)錯(cuò)誤,因此,靜態(tài)查錯(cuò)往往是不可忽視的審查步驟。靜態(tài)查錯(cuò)一般順序?yàn)橄炔槌绦蚓植?,后查程序整體。查局部主要是獨(dú)立地檢查各個(gè)子模塊的功能是否按照算法要求實(shí)現(xiàn),查整體主要是檢查各個(gè)局部之間的接口是否吻合,是否缺少某些功能。在靜態(tài)查錯(cuò)階段,可以有針對(duì)性地檢查上面所列舉的各類型錯(cuò)誤。在這個(gè)階段查出的錯(cuò)誤越多,節(jié)省的調(diào)試時(shí)間也就越多。

2.動(dòng)態(tài)查錯(cuò)靜態(tài)查錯(cuò)能夠查出錯(cuò)誤,但無(wú)法保證查出所有錯(cuò)誤,因?yàn)檫@里有一個(gè)人為的因素在里面,只要一不小心,就可能漏掉一個(gè)錯(cuò)誤。因此,我們需要?jiǎng)討B(tài)查錯(cuò)與之相結(jié)合來(lái)找出遺漏的錯(cuò)誤。與靜態(tài)查錯(cuò)相對(duì),動(dòng)態(tài)查錯(cuò)是指通過(guò)跟蹤程序的執(zhí)行過(guò)程,核對(duì)輸出結(jié)果來(lái)發(fā)現(xiàn)錯(cuò)誤。動(dòng)態(tài)查錯(cuò)的技巧可分為兩大部分:測(cè)試用例的設(shè)計(jì)和測(cè)試的方法。我們主要講測(cè)試方法。動(dòng)態(tài)查錯(cuò)的測(cè)試方法可以按照以下兩種標(biāo)準(zhǔn)進(jìn)行分類:

(1)按照測(cè)試用例的設(shè)計(jì)依據(jù)的不同,可分為黑箱測(cè)試法和白箱測(cè)試法。只知程序的輸入與輸出功能,而不知程序的具體結(jié)構(gòu),通過(guò)列舉各種不同的可能情況來(lái)設(shè)計(jì)測(cè)試用例,通過(guò)執(zhí)行測(cè)試用例來(lái)發(fā)現(xiàn)錯(cuò)誤的測(cè)試方法叫做黑箱測(cè)試法。已知程序的內(nèi)部結(jié)構(gòu)和流向,根據(jù)程序內(nèi)部邏輯來(lái)設(shè)計(jì)測(cè)試用例,通過(guò)執(zhí)行測(cè)試用例來(lái)發(fā)現(xiàn)錯(cuò)誤的測(cè)試方法叫做白箱測(cè)試法。在進(jìn)行底層模塊測(cè)試的時(shí)候可以使用白箱測(cè)試法,通過(guò)專門(mén)的測(cè)試條件和測(cè)試數(shù)據(jù)來(lái)考查程序在不同點(diǎn)上的狀態(tài)是否符合預(yù)期的要求。在總體調(diào)試的時(shí)候則可以使用黑箱測(cè)試法,脫離程序內(nèi)部結(jié)構(gòu)來(lái)考察對(duì)于不同情況下的測(cè)試數(shù)據(jù),程序是否能夠正確輸出。對(duì)于中間模塊,可以用黑箱,也可以用白箱,或是兩者兼用,具體要看適合哪種測(cè)試法。一般說(shuō)來(lái),結(jié)構(gòu)復(fù)雜的模塊使用黑箱測(cè)試法,結(jié)構(gòu)簡(jiǎn)單的使用白箱測(cè)試法。最后要說(shuō)的是,由于白箱測(cè)試法測(cè)試用例設(shè)計(jì)比較困難,所以在時(shí)間緊張的情況下,可以一律采用黑箱測(cè)試法,這樣效率比較高。

(2)按照測(cè)試順序的不同,可分為由底向上測(cè)試和從頂向下測(cè)試。由底向上測(cè)試是先測(cè)最底層的模塊,然后依次向上測(cè)試,最后測(cè)試主模塊。從頂向下測(cè)試剛好與之相反,先測(cè)主模塊,然后按照從頂向下設(shè)計(jì)的順序依次測(cè)試各個(gè)模塊。為了加快調(diào)試的速度,建議采用從頂向下的測(cè)試順序,只在發(fā)現(xiàn)某個(gè)模塊有錯(cuò)時(shí)才進(jìn)入下一層調(diào)試,這樣對(duì)迅速定位錯(cuò)誤也有很大幫助。在運(yùn)用這些測(cè)試方法時(shí),我們要注意哪些問(wèn)題呢?首先,對(duì)自己所編的程序的結(jié)構(gòu)、模塊的功能一定要了如指掌。采用從頂向下的測(cè)試方法時(shí),經(jīng)常是一個(gè)模塊還沒(méi)有測(cè)試完,就轉(zhuǎn)到了下一個(gè)模塊,因而特別容易忘記和疏漏。如果對(duì)程序結(jié)構(gòu)心中沒(méi)有概念,就很容易被弄糊涂。又如果對(duì)模塊的功能不是很清楚,則難以判斷模塊執(zhí)行結(jié)果的對(duì)錯(cuò),從而無(wú)法準(zhǔn)確確定錯(cuò)誤所在。其次,測(cè)試需要有條理地進(jìn)行。堅(jiān)持使用同一個(gè)測(cè)試用例直到輸出正確為止;在一個(gè)模塊沒(méi)有測(cè)試完畢時(shí),不要進(jìn)行下一個(gè)模塊的測(cè)試,除非這個(gè)模塊是當(dāng)前模塊的子模塊且在當(dāng)前模塊的測(cè)試中發(fā)現(xiàn)這個(gè)子模塊有錯(cuò)。最后,在每次修改了源代碼之后一定要把已經(jīng)測(cè)過(guò)的所有測(cè)試用例再測(cè)一遍,以防產(chǎn)生新的錯(cuò)誤。

3.跟蹤調(diào)試跟蹤調(diào)試通常是一件繁瑣的事,它需要足夠的耐心和細(xì)心。選擇哪些變量進(jìn)行跟蹤也是至關(guān)重要的,準(zhǔn)確的變量選擇可以起到事半功倍的效果。一般來(lái)說(shuō),首先要跟蹤的是存放輸入數(shù)據(jù)的變量,尤其對(duì)于那些需要對(duì)輸入數(shù)據(jù)進(jìn)行一定處理的程序來(lái)說(shuō)更是如此,輸入數(shù)據(jù)不正確,即使是正確的程序,其輸出也會(huì)與答案不符合;其次是那些頻繁用到的全局變量,這些變量往往貫穿于整個(gè)程序中,一旦某處出錯(cuò),會(huì)影響到其他模塊的正確性,由此造成定位錯(cuò)誤,出錯(cuò)的地方?jīng)]有測(cè)試,正確的地方反而反復(fù)測(cè)試,因此對(duì)于這些全局變量的變化要密切加以關(guān)注,不可放過(guò)任何錯(cuò)誤;再次就是那些循環(huán)變量了,跟蹤循環(huán)變量可以準(zhǔn)確地得知程序的執(zhí)行進(jìn)度,從時(shí)間上把握錯(cuò)誤所在;最后是其他的變量,需要根據(jù)實(shí)際情況加以選擇,對(duì)使用較多的變量應(yīng)優(yōu)先加以跟蹤。1.4.3TC環(huán)境下的程序調(diào)試

TC集成開(kāi)發(fā)環(huán)境下的程序調(diào)試技術(shù)包括以下兩種:①單步跟蹤程序的執(zhí)行(F7鍵或Run→Traceinto,F(xiàn)8鍵或Run→Stepover);②設(shè)置斷點(diǎn)和觀測(cè)項(xiàng)。當(dāng)一個(gè)程序的執(zhí)行結(jié)果與預(yù)期結(jié)果不同時(shí),首先進(jìn)行靜態(tài)查錯(cuò),對(duì)錯(cuò)誤位置進(jìn)行人為定位,看看有沒(méi)有1.4.1節(jié)中提到的一些常見(jiàn)錯(cuò)誤。當(dāng)靜態(tài)查錯(cuò)失效,也就是查不出錯(cuò)誤時(shí),就應(yīng)該進(jìn)行跟蹤調(diào)試。

(1)直接單步跟蹤調(diào)試。直接按F7鍵或F8鍵,程序便從main函數(shù)開(kāi)始執(zhí)行。執(zhí)行的過(guò)程中,通過(guò)設(shè)置觀測(cè)項(xiàng)(Break/Watch→AddWatch)查看一些變量的值,來(lái)診斷程序在何時(shí)出錯(cuò)。其中,F(xiàn)7鍵和F8鍵的區(qū)別是:如果遇到一個(gè)用戶自定義函數(shù)時(shí),按F7鍵會(huì)進(jìn)入該函數(shù),繼續(xù)跟蹤調(diào)試;而按F8鍵不會(huì)進(jìn)入該函數(shù),而是直接將該函數(shù)的功能執(zhí)行完。

(2)設(shè)置斷點(diǎn)后單步跟蹤調(diào)試。有時(shí)候程序比較長(zhǎng),而我們通過(guò)靜態(tài)查錯(cuò)知道開(kāi)始的一段程序沒(méi)有錯(cuò)誤,那么如果用F7鍵或F8鍵來(lái)調(diào)試,則會(huì)浪費(fèi)很多時(shí)間,尤其是當(dāng)這段程序有一個(gè)次數(shù)不少的循環(huán)時(shí)。此時(shí),就需要先設(shè)置斷點(diǎn)。方法是:將光標(biāo)移到可能會(huì)出錯(cuò)的第一行代碼,選擇Break/watch→Togglebreakpoint,該行變色。此時(shí)開(kāi)始執(zhí)行程序,當(dāng)程序執(zhí)行到該斷點(diǎn)處時(shí)會(huì)停止執(zhí)行,此后再用F7鍵或F8鍵,設(shè)置一些觀測(cè)項(xiàng)來(lái)進(jìn)一步排錯(cuò)。另外,如果要查看程序的輸出結(jié)果,可以用Run→Userscreen或按Alt?+?F5鍵進(jìn)行切換。特別提示:有些程序編譯后會(huì)出現(xiàn)很多錯(cuò)誤,初學(xué)者往往不知所措。如果有些錯(cuò)誤不能明顯確定所在位置,那么當(dāng)改正一條明顯的錯(cuò)誤后,應(yīng)該先編譯一下,也許此時(shí)就不再有錯(cuò)誤了。出現(xiàn)這種情況是因?yàn)榫幾g器也不是想象中的那么完美,出現(xiàn)的很多錯(cuò)誤可能都是因?yàn)橐粭l錯(cuò)誤引起的。1.4.4VC環(huán)境下的程序調(diào)試在VC環(huán)境下調(diào)試程序,首先需要設(shè)置斷點(diǎn):將光標(biāo)移到斷點(diǎn)處,選擇工具欄上的圖標(biāo)就設(shè)置了一個(gè)斷點(diǎn)(可以設(shè)置多個(gè)斷點(diǎn));然后選擇開(kāi)始調(diào)試程序。程序會(huì)在斷點(diǎn)處停止執(zhí)行,并出現(xiàn)一個(gè)調(diào)試工具欄,如圖1.18所示。常用的幾個(gè)功能是第一排的后4個(gè)。它們分別代表:進(jìn)入函數(shù)調(diào)試(類似TC的F7鍵)、跳過(guò)函數(shù)執(zhí)行(類似TC的F8鍵)、從函數(shù)中跳出和直接執(zhí)行到光標(biāo)所在位置。圖1.18VC調(diào)試工具欄調(diào)試的過(guò)程中,可在屏幕下方的Varible工具欄(如圖1.19(a)所示)中查看當(dāng)前變量的值,也可以在Watch工具欄(如圖1.19(b)所示)中輸入需要查看的變量名,在Value欄中會(huì)顯示該變量的值。(a)(b)圖1.19VC的Watch和Varible工具欄1.5參數(shù)傳遞相關(guān)技術(shù)1.5.1參數(shù)傳遞

參數(shù)傳遞是函數(shù)之間進(jìn)行信息交換的重要渠道。首先區(qū)分幾個(gè)概念:傳值、傳地址、值傳遞、地址傳遞。傳值和傳地址是主調(diào)函數(shù)向被調(diào)函數(shù)傳的內(nèi)容,分為傳值和傳地址兩類。值傳遞和地址傳遞是實(shí)參替換形參的方式,其中,值傳遞表示將實(shí)參的值傳遞給形參,地址傳遞表示將實(shí)參的地址傳遞給形參。

C語(yǔ)言中,可以傳值,也可以傳地址,但實(shí)參代替形參的方式為值傳遞方式。更詳細(xì)的內(nèi)容可參見(jiàn)3.4節(jié)。1.5.2函數(shù)結(jié)果的返回方式值傳遞方式最大的缺點(diǎn)是被調(diào)用函數(shù)不能通過(guò)參數(shù)向調(diào)用函數(shù)返值,原因是值參數(shù)的作用域只在函數(shù)內(nèi)部,無(wú)法返回結(jié)果值。如果要返回一個(gè)結(jié)果值,可以使用return方式。如果函數(shù)結(jié)果需要返回多個(gè)值,該怎樣實(shí)現(xiàn)呢?可以有以下兩類方式實(shí)現(xiàn):①通過(guò)全局變量方式返回;②通過(guò)地址傳遞(數(shù)組方式、結(jié)構(gòu)體方式、指針?lè)绞?返回。

(1)全局變量方式:不需要返回,對(duì)全局變量修改后,該程序中的其他函數(shù)均可得到改變后的值。

(2)數(shù)組方式:如果要返回的是多個(gè)相同類型的值,則可以將這些值放到一個(gè)數(shù)組中,然后返回?cái)?shù)組的指針或首地址。

(3)結(jié)構(gòu)體方式:如果要返回的是多個(gè)不同類型的值,則可以將這些值放到一個(gè)結(jié)構(gòu)體中,然后返回結(jié)構(gòu)體的指針或全局變量。但必須注意的是,該結(jié)構(gòu)體必須是在全局范圍內(nèi)定義的結(jié)構(gòu)體。

(4)指針?lè)绞剑和ㄟ^(guò)參數(shù)列表傳遞,參數(shù)列表中的參數(shù)如果為指針類型,則在被調(diào)函數(shù)中改變了指針?biāo)竼卧闹?,返回到主調(diào)函數(shù)后,指針?biāo)竼卧闹当3指淖兒蟮闹怠Mㄟ^(guò)以下示例,說(shuō)明以上返回方式的使用。【程序1.3】

函數(shù)結(jié)果返回方式示例。

#include<stdio.h>

#include<stdlib.h>

typedefstruct

{

intmax,min;

}Data;

intMIN;/*全局變量*/intfun1(inta[],intn)/*通過(guò)函數(shù)return返回最大值,通過(guò)全局變量MIN返回最小值*/{inti,max;max=MIN=a[0];//給最大值、最小值賦初值

for(i=0;i<n;i++){if(a[i]>max)max=a[i];if(a[i]<MIN)MIN=a[i];}return(max);}int*fun2(inta[],intn)/*將最大、最小值放到數(shù)組b中,通過(guò)return返回*/{staticintb[2];b[0]=b[1]=a[0];//給最大值、最小值賦初值

inti;for(i=1;i<n;i++){ if(a[i]>b[0]) b[0]=a[i]; if(a[i]<b[1]) b[1]=a[i];}return(b);}Data*fun3(inta[],intn)/*將最大、最小值放到結(jié)構(gòu)體指針p中,通過(guò)return返回*/{ Data*p; inti; p=(Data*)malloc(sizeof(Data*));//指針初始化

p->max=p->min=a[0];//給最大值、最小值賦初值

for(i=1;i<n;i++) { if(a[i]>p->max) p->max=a[i]; if(a[i]<p->min) p->min=a[i]; } return(p);}Datafun4(inta[],intn)/*將最大、最小值放到結(jié)構(gòu)體p中,通過(guò)結(jié)構(gòu)體p返回值*/{ Datap; inti; p.max=p.min=a[0];//給最大值、最小值賦初值

for(i=1;i<n;i++) { if(a[i]>p.max) p.max=a[i]; if(a[i]<p.min) p.min=a[i]; } return(p);}voidfun5(inta[],intn,int*p,int*q)/*用指針?lè)祷刂?,指針p指向最大值,指針q指向最小值*/{ inti; *p=*q=a[0];//給最大值、最小值賦初值

for(i=1;i<n;i++) { if(*p<a[i]) *p=a[i]; if(*q>a[i]) *q=a[i]; }}voidmain(){inta[10]={1,3,9,8,4,2,5,0,7,6},max,*p;Data*q;

Dataz;int*x,*y;

x=(int*)malloc(sizeof(int*));y=(int*)malloc(sizeof(int*));max=fun1(a,10);printf("max=%dmin=%d\n",max,MIN);p=fun2(a,10);printf("max=%dmin=%d\n",p[0],p[1]);

q=fun3(a,10);printf("max=%dmin=%d\n",q->max,q->min);z=fun4(a,10);printf("max=%dmin=%d\n",z.max,z.min);

fun5(a,10,x,y);printf("max=%dmin=%d\n",*x,*y);}1.6完整的C程序結(jié)構(gòu)一個(gè)結(jié)構(gòu)合理的C程序是由很多函數(shù)組成的,每個(gè)函數(shù)稱為一個(gè)模塊。模塊是一個(gè)具有獨(dú)立功能的程序,可以單獨(dú)設(shè)計(jì)、調(diào)試與管理。模塊化程序的設(shè)計(jì)思想是將一個(gè)大的程序按功能分割成一些模塊,使每一個(gè)模塊都成為功能單一、結(jié)構(gòu)清晰、接口簡(jiǎn)單、容易理解的小程序。模塊化程序設(shè)計(jì)的原則有:

(1)用“自頂向下”的方法進(jìn)行系統(tǒng)設(shè)計(jì),即由整體到局部。

(2)按功能劃分法把模塊組成樹(shù)狀結(jié)構(gòu),使層次清楚。

(3)模塊的大小要適中,代碼量一般在100行以內(nèi)。

(4)各模塊間的接口要簡(jiǎn)單,盡可能使每個(gè)模塊只有一個(gè)入口,一個(gè)出口。模塊化設(shè)計(jì)的優(yōu)點(diǎn)是:

(1)復(fù)雜系統(tǒng)化大為小,化繁為簡(jiǎn)。

(2)便于維護(hù)。

(3)提高系統(tǒng)設(shè)計(jì)效率(多人可并行開(kāi)發(fā))。

C語(yǔ)言的函數(shù)式程序結(jié)構(gòu)即是模塊化的一種體現(xiàn)。通過(guò)參數(shù)傳遞,可實(shí)現(xiàn)各模塊間的數(shù)據(jù)交換。因此,一個(gè)完整的、可執(zhí)行的C程序文件一般有兩種結(jié)構(gòu),如圖1.20所示。圖1.20C程序文件的兩種結(jié)構(gòu)圖1.20中的每行表示一段語(yǔ)句或程序,[]中的內(nèi)容表示可選。所謂可選,并不是說(shuō)可有可無(wú),而是要根據(jù)實(shí)際情況看是否需要它們。對(duì)于一個(gè)完整的、可執(zhí)行的C程序而言,主函數(shù)是必不可少的,它是一個(gè)程序的入口。換句話說(shuō),計(jì)算機(jī)執(zhí)行一個(gè)程序的時(shí)候,是從主函數(shù)的位置開(kāi)始執(zhí)行的。還有一點(diǎn)需要說(shuō)明的是,主函數(shù)的函數(shù)名必須使用main()。另外,如果子函數(shù)的返回值為int類型,則可以不在主函數(shù)之前聲明,而直接在主函數(shù)之后實(shí)現(xiàn),但不建議這樣做。圖1.20(a)所示結(jié)構(gòu)有一個(gè)缺點(diǎn):當(dāng)子函數(shù)之間互相有調(diào)用,且被調(diào)用函數(shù)返回值類型不是int時(shí),被調(diào)用函數(shù)必須出現(xiàn)在調(diào)用函數(shù)之前,這樣限制太多。因此,建議采用圖1.20(b)的結(jié)構(gòu),這樣子函數(shù)在聲明時(shí)不受互相調(diào)用的限制,其最簡(jiǎn)單的方式為:返回值類型函數(shù)名();/*參數(shù)可以暫時(shí)省略*/思考:包含文件語(yǔ)句可否出現(xiàn)在宏定義語(yǔ)句之后?【程序1.4】C程序結(jié)構(gòu)舉例。/*****************************************************文件名稱:test.c功能:演示C程序一般結(jié)構(gòu)作者:XXX修改日期:2008年11月12日*****************************************************/#include"stdio.h"#defineN5voidadd();/*函數(shù)聲明時(shí)可以沒(méi)有參數(shù),但必須寫(xiě)清返回值類型*/voidsubstract();main(){inta[N]={1,3,5,7,9},b[N]={2,4,6,8,10},c[N],d[N];

add(a,b,c);/*兩個(gè)一維數(shù)組相加,結(jié)果放在c中*/substract(a,b,d);/*兩個(gè)一維數(shù)組相減,結(jié)果放在d中*/}/************************************************************函數(shù)名稱:add函數(shù)功能:將兩個(gè)整型一維數(shù)組相加后的結(jié)果放在另一個(gè)一維數(shù)組中參數(shù)說(shuō)明:x,y,z均為一維數(shù)組,大小為N。將x和y相加后,結(jié)果放在z中返回值:無(wú)返回值************************************************************/voidadd(intx[],inty[],intz[]){inti;/*i為循環(huán)變量*/for(i=0;i<N;i++)z[i]=x[i]+y[i];}voidsubstract(intx[],inty[],intz[]){inti;for(i=0;i<N;i++)

z[i]=x[i]-y[i];}1.7良好的程序風(fēng)格雖然我們開(kāi)始寫(xiě)的程序很簡(jiǎn)單,但良好的風(fēng)格應(yīng)該從一開(kāi)始就培養(yǎng)直至形成習(xí)慣。良好的風(fēng)格能使程序結(jié)構(gòu)一目了然,幫助你和別

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論