?? 第12章 函數(shù)(一).htm
字號:
<P>這行代碼在屏幕上打出一行:"Hello world!"。</P>
<P>除了教學上,或其它一些特殊要求,我們幾乎不寫控制臺式的程序了,我們最終目標是寫Windows下的GUI(圖形用戶界面)程序,而這些控制臺輸入輸出函數(shù),都不能用在GUI程序中。所以,當課程例中用到的某個控制臺庫函數(shù),我會臨時解釋一下,其它的,大家就不必花時間了。</P>
<P> </P>
<P><B>3、轉(zhuǎn)換函數(shù):</B></P>
<P>這類函數(shù)完成各種數(shù)據(jù)類型之間的轉(zhuǎn)換,比如把字符串“123”轉(zhuǎn)換數(shù)字123,或把小寫字母轉(zhuǎn)換為大寫字母等等。</P>
<P> </P>
<P><B>5、目錄管理函數(shù):</B></P>
<P>目錄就是我們現(xiàn)在常說的“文件夾”啦。這些函數(shù)可以建立,刪除,切換文件夾。一般地,我們已經(jīng)不再使用,轉(zhuǎn)而使用Windows提供的相關(guān)函數(shù)。請參看下面的Windows
API函數(shù)說明。</P>
<P> </P>
<P><B>6、數(shù)學函數(shù):</B></P>
<P>例如我們前面說的sin()函數(shù),其它的各種三角函數(shù),還有求整,求絕對值,求隨機數(shù),求對數(shù)等。</P>
<P>這些函數(shù)大都枯燥無味,其中的隨機函數(shù)倒是有趣點。很多游戲程序都要使用到它。這里粗略講講。</P>
<P>什么叫隨機?大白話說就是:一件事情的結(jié)果有幾種相同概率的可能。比如你扔一個硬幣到地上,可能是正面,也可能是反面朝上,兩種可能的概率都是50%。但如果你要考慮硬幣還有“立”著在地上的可能,那么這種可能就不屬于隨機的范疇了。下面的程序隨機生成一個0~99的數(shù),然后要求你輸入一個0~99之間的數(shù),如果這你輸入的和它生成的數(shù)相等(概率為1%),就表示你中獎了。</P>
<P> </P>
<P>//雖然屬于數(shù)學類函數(shù),但隨機函數(shù)其實放在標準庫(stdlib)里:</P>
<P>#include <stdlib.h></P>
<P>#include <iostream.h></P>
<P> </P>
<P>int main(int argc, char* argv[])</P>
<P>{<BR> //在第一次調(diào)用隨機數(shù)之前,要調(diào)用一次這個函數(shù),</P>
<P> //這個函數(shù)稱為“隨機種子函數(shù)”</P>
<P> randomize();</P>
<P></P>
<P> //隨機函數(shù):random(int n)的用法:</P>
<P> //隨機返回一個 0~ (n-1) 之間的整數(shù),</P>
<P> //如: int x = random(100),則x值將是0到99之間的一個數(shù)。</P>
<P> </P>
<P> int x = random(100);</P>
<P> </P>
<P> int y;</P>
<P> </P>
<P> cout << "請輸入一個0~99的整數(shù):";</P>
<P> </P>
<P> cin >> y;</P>
<P> </P>
<P> if( x == y) //可能性為1%</P>
<P> cout << "恭喜!您中獎了!" <<
endl;</P>
<P> else</P>
<P> cout << "謝謝使用。" << endl;</P>
<P>}</P>
<P> </P>
<P><B>7、字符串函數(shù):</B></P>
<P>我們在學習字符串時將用到。</P>
<P><B>8、內(nèi)存管理管理函數(shù):</B></P>
<P>我們在學習內(nèi)存管理時將用到。</P>
<P><B>9、雜七雜八的其它函數(shù)。</B></P>
<P>這個且不說。</P>
<H5><A name=12.2.1.2>12.2.1.2</A> 操作系統(tǒng)的 API 函數(shù)</H5>
<P>大家總該知道什么叫操作系統(tǒng)吧?Windows就是一套操作系統(tǒng),另外如UNIX,Linux也是,當然我們最常用的是前者。操作系統(tǒng)有兩個主要任務(wù):</P>
<P>第一是給普通用戶提供一套界面,比如桌面啦,任務(wù)條啦,及任務(wù)條上的開始按鈕,桌面上的圖標;還有資源管理器等等。這一些我們都稱為“用戶界面”。它的作用是讓用戶“用”這臺電腦。因此我們也可以稱它為用戶與電腦之間的“接口”。</P>
<P>第二就是給我們這些程序員的接口,我們所寫的程序是運行在操作系統(tǒng)上,就必須和操作系統(tǒng)有著千絲萬縷的關(guān)系。比如我們想在屏幕上顯示一個窗口,那么我們所做的事是“請求操作系統(tǒng)為我們在屏幕上畫一個窗口”,同樣在有了窗口后,我們想在窗口上畫一條直線,那么也是“請求操作系統(tǒng)在座標(2,1)-(100,200)之間畫一條直線”。</P>
<P>那么,這些“請求”是如何實現(xiàn)的呢?其實也是調(diào)用函數(shù),調(diào)用操作系統(tǒng)為我們準備的各種函數(shù)。這些函數(shù)同樣是放在庫文件里,當然,由于這些庫文件是操作系統(tǒng)提供的,每一臺裝有相同操作系統(tǒng)的電腦都有這些庫,所以它不用安裝,所以它當然采用了動態(tài)庫的形式。
對于我們正在用的Windows,這些庫一般都放在Windows的安裝目錄:Windows,主要是Windows\System或System32下。那里有一堆的.dll,其中有不少文件就是操作系統(tǒng)的動態(tài)庫文件。</P>
<P>我們寫的程序,一般稱為“應(yīng)用程序”(Application
Program),所以Windows為我們提供的庫函數(shù)也就稱為“應(yīng)用程序接口”(Application Program
Interface),縮寫即:API。</P>
<P>在本部教程,我們主要學習C++語言本身,只有學好C、C++語言,才有可能學會用C、C++語言來和操作系統(tǒng)打交道。要知道所有在API函數(shù)都聲明為C語言的形式,這是因為,Windows本身也是主要用C語言寫成的。結(jié)論是:學習C、C++語言非常重要,并且,如果想在操作系統(tǒng)上寫程序,那么學習C、C++當然最合算!</P>
<H5><A name=12.2.1.3>12.2.1.3</A> VCL 庫函數(shù)</H5>
<P>VCL意為:可視化控件庫(Visual Component
Library),事事都直接和Windows的API打交道,編程效率將非常的低。主要表現(xiàn)兩個方面:第一,由于使用API編程是非可視化的,我們將不得不花費非常冗長的時間在處理界面顯示的事務(wù)上,而界面顯示其實不是我們程序的主要邏輯。第二,有關(guān)顯示等工作的大量代碼事實上有很大的相似性,大量重復(fù)。我們要么仍受每寫一個程序就重復(fù)寫一堆千篇一律的代碼,要么像早期的Windows程序員一樣自已動手寫一套的類庫用來“包裝”這段代碼,以求每次可以得重復(fù)利用。但這是件龐大而靈活的工作,顯然我們不值得這樣做,事實上也不具備這樣的能力。筆者在Windows3.1下寫程序時,曾經(jīng)購買過國人高手寫的一套這種類庫,事實上錢花得不值。很快筆者轉(zhuǎn)向了當時Borland提供的類庫:OWL和微軟的MFC。</P>
<P>VCL提供的也主要是類庫,我們暫未學到“類”的概念,所以這時且不詳談。</P>
<P> </P>
<H4><A name=12.2.2>12.2.2</A> 調(diào)用者必須能“找”得到被調(diào)用者</H4>
<P> </P>
<P>調(diào)用函數(shù)前提之一:調(diào)用者必須能看到被調(diào)用者。</P>
<P> </P>
<P>一個“者”字,可能讓你以為這里說的是“人”,其實不是,這里說的調(diào)用者指的是當前程序,而被調(diào)用者當然是“將被調(diào)用”的函數(shù)。</P>
<P>不過,確實,這里拿人來比喻是再合適不過了。</P>
<P>就拿前面說的“找電視修理工”的例子來說:</P>
<P> </P>
<P>要修電視,顯然要能找到電視修理工。這個道理很明顯。</P>
<P>所以本小節(jié)的重點其實是:程序如何才能找到要調(diào)用的函數(shù)呢?</P>
<P> </P>
<P>有三種方法:</P>
<P> </P>
<P><B>第一種、將被調(diào)用的函數(shù)寫在當前代碼前面</B></P>
<P> </P>
<P>修理工正在我家喝茶呢!是啊,我有個朋友是干這活的,有一天他來我家串門,而我家電視正好壞了。</P>
<P> </P>
<P>下面我先寫一個函數(shù),這個函數(shù)的大部分代碼我沒有寫出來--根本寫不出來。我只是要用它表示一個叫“修理電視”的功能。</P>
<P> </P>
<P>//本函數(shù)實現(xiàn)“修理電視”</P>
<P>void XiuliDianshi()</P>
<P>{</P>
<P> ......</P>
<P>}<BR></P>
<P>盡管我們稍后才能學如何自已寫函數(shù),但你現(xiàn)在要記住了,上面那幾行代碼就是一個函數(shù),它的函數(shù)名為:XiaoliDianshi,意為“修理電視”。</P>
<P> </P>
<P>好!有了“修理電視”的函數(shù)了,如何調(diào)用它呢?下圖表示的是正確的情況:</P>
<P><IMG height=290 src="第12章 函數(shù)(一).files/ls12.h2.gif" width=384
border=0></P>
<P>當我們寫程序要調(diào)用一個函數(shù),而這個函數(shù)位于我們現(xiàn)在在寫的代碼前面時,我們就可以直接調(diào)用它,這就像修理工就在我們家里一樣。注意這里的前面并非僅限于“跟前”,如果你的代碼很多行,這個函數(shù)在“很前面”,也不妨礙我們調(diào)用它。</P>
<P>要注意的是另一面:當函數(shù)在我們的代碼后面時,代碼就“看”不見這個函數(shù)了。下面即為這種錯誤情況:</P>
<P><IMG height=256 src="第12章 函數(shù)(一).files/ls12.h3.gif" width=384
border=0></P>
<P><B>第二種、將被調(diào)用的函數(shù)聲明寫在當前代碼前面</B></P>
<P> </P>
<P>修理工不在我家,不過,他曾經(jīng)留給我一張名片,名片上寫著:“張三,電視修理工,Tel:1234567,住址:……”。所以我們也能知道他會修理電視,并且知道他的電話和住址,這樣就不愁找不到他了,對不?</P>
<P> </P>
<P>函數(shù)也可以有名片,在程序中我們稱為函數(shù)的“聲明”。</P>
<P> </P>
<P>下面的代碼演示了什么叫函數(shù)的“聲明”,及它所起的作用:</P>
<P><IMG height=256 src="第12章 函數(shù)(一).files/ls12.h6.gif" width=384
border=0></P>
<P> </P>
<P><B>第三種:使用頭文件</B></P>
<P> </P>
<P>當我們手里有了電視修理工的名片,有了冰箱修理工的名片,有了電腦修理工的名片……名片多了,我們可以將名片整理到一個名片夾。這樣做至少有兩個好處:</P>
<P>其一:便于管理。家里任何電器壞了,只需找“家用電器修理工名片”的名片夾即可。</P>
<P>其二:便于多人共用,比如隔壁家想找一個電視修理工,只需上你家借名片夾即可。</P>
<P> </P>
<P>C,C++中,類似“名片夾”功能的文件,稱為“頭文件”。頭文件的擴展名為
.h(head)。頭文件是放置函數(shù)聲明的好地方。如何寫函數(shù)聲明下面再說,現(xiàn)在要明白,“函數(shù)聲明”就是給編譯器看的函數(shù)說明,或曰函數(shù)的“自我介紹”。至于為什么叫“頭”文件呢?是因為它總是要在程序代碼文件的開頭。就你我們在交談時,開頭總是大家各作一番介紹一樣。(該說法未經(jīng)證明,僅供參考:)</P>
<P>說千道萬,不如先簡單地看一眼真實的頭文件吧。</P>
<P>啟動C++ Builder。然后新建一個控制臺應(yīng)用工程。在CB6里,新建控制臺工程在File | New | Others
去找,別忘了。</P>
<P><FONT color=#c0c0c0>(CB6啟動為什么這么慢啊!我且先上趟洗手間)</FONT></P>
<P> </P>
<P>然后在代碼窗口里,加上一行:</P>
<P>#include <stdlib.h></P>
<P>并且用鼠標在這一行點一下,現(xiàn)在代碼窗口里的內(nèi)空看起來如下:</P>
<P><IMG height=158 src="第12章 函數(shù)(一).files/ls12.h1.gif" width=421
border=0></P>
<P> </P>
<P>確保輸入光標在單詞“stdlib.h” 上面閃爍!現(xiàn)在按 <B>Ctrl + 回車</B>,CB將打開光標所在處的文件。</P>
<P>(如果你出現(xiàn)的是一個文件打開對話框,那有兩點可能,其一是你沒有把光標移到指定的單詞上,另一可能是你安裝CB時沒有選擇“Full”模式的安裝,造成CB沒有安裝源文件。)</P>
<P>以下就是打開的 stdlib.h 頭文件:</P>
<TABLE width="100%" border=0>
<TBODY>
<TR>
<TD width="62%"><IMG height=179 src="第12章 函數(shù)(一).files/ls12.h4.gif"
width=411 border=0></TD>
<TD width="38%"><IMG height=97 src="第12章 函數(shù)(一).files/ls12.h5.gif"
width=234 border=0>
<P>(選擇ReadOnly可以把當前文件設(shè)置為只讀)</P></TD></TR></TBODY></TABLE>
<P> </P>
<P>打開的文件是C++ Builder工程師為我們所寫的頭文件,請注意千萬不要有意無意地改動它!為了保險起見,通過右鍵菜單,選擇Read
Only將當前文件設(shè)置為只讀(如上面右圖)。請大家將這當作一條準則來執(zhí)行:不管出于什么原因打開CB提供的源文件,立即將其設(shè)置為只讀。</P>
<P>好,我們說過“只看一眼”的。關(guān)于頭文件,在講完函數(shù)以后,還會專門講到頭文件在工程中應(yīng)用。現(xiàn)在重復(fù)頭文件的目的:</P>
<P><B>函數(shù)可以統(tǒng)一在一個頭文件中聲明,代碼中需要使用這些函數(shù),只需通過“include”語句包含這個頭文件,就可以讓編譯器找到函數(shù)。</B></P>
<P>用一句大白話講就是:要想用函數(shù)?請包含它所在的名片夾(頭文件)。</P>
<P> </P>
<P>函數(shù)的“聲明”有時被稱為函數(shù)的“原型”,比如在講到編譯過程時。當我們閱讀其它文章時,如果看到“函數(shù)原型”一說,希望大家也能明白。</P>
<P> </P>
<H4><B><A name=12.2.3>12.2.3</A> 調(diào)用者必須傳遞給被調(diào)用者正確的參數(shù)</B></H4>
<P>現(xiàn)在,我能找到修理工,而且他已經(jīng)到我家。</P>
<P>“電視呢?”他說。</P>
<P>“就是它”我指著家里的蘇泊爾高壓鍋,“勞駕,把它修修,最近它總漏氣。”</P>
<P>“可是,我好象是來修理電視的?”</P>
<P>“知道,現(xiàn)在你先修高壓鍋。”</P>
<P>“好吧,我試試……先用電筆試試它哪里短路。”</P>
<P> </P>
<P>顯然我這是在胡攪蠻纏。電視修理工要開始干活,就得給他電視。給他一只高壓鍋他不能開工。</P>
<P>函數(shù)也一樣,函數(shù)的目的是實現(xiàn)某個特定功能,當我們調(diào)用它時,我們一般需要給它一些數(shù)據(jù),這些數(shù)據(jù)可能是讓它直接處理,也可能是輔助它實現(xiàn)具體的功能。</P>
<P>當然有些函數(shù)不需要任何外部數(shù)據(jù),它就能完成任務(wù)。這也很好理解,修理工修理電視是得有臺電視,但叫一位歌手到家里隨便哼幾句歌,你就不用給他什么。</P>
<P>關(guān)鍵一句話:<B>函數(shù)要不要外部傳給它數(shù)據(jù),要什么類型的數(shù)據(jù),要多少數(shù)據(jù),由函數(shù)本身決定,而非調(diào)用者決定</B>。本例中,電視修理工需要一臺電視,這是他決定的,不能由請他的人決定。</P>
<P>傳給函數(shù)的數(shù)據(jù),我們稱為“參數(shù)”,英文為:parameter。</P>
<P> </P>
<P>基于此,我們發(fā)現(xiàn)所寫的
XiuliDianshi()函數(shù)有很大的不足,那就是它沒有參數(shù)。現(xiàn)在我們假設(shè)有一種數(shù)據(jù)類型為“電視機”,嗯,就假設(shè)這種數(shù)據(jù)類型叫作:TDianshi。</P>
<P>加入?yún)?shù)的XiuliDianShi()函數(shù)變?yōu)椋?lt;/P>
<P> </P>
<P>XiuliDianshi (TDianshi ds)</P>
<P>{</P>
<P>}</P>
<P> </P>
<P>看一個實際的例子。上一章我們曾經(jīng)學過sin()函數(shù)。現(xiàn)在我們來看看sin()函數(shù)的聲明。看看它聲明需要什么參數(shù)。</P>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -