?? 第12章 函數(一).htm
字號:
<H3><A name=12.3>12.3</A> 自定義函數</H3>
<P>學會如何調用別人的函數,現在我們來學習如何自已寫一個函數。首先迅速看看函數的格式:</P>
<H4><A name=12.3.1>12.3.1</A> 函數的格式</H4>
<P>定義一個函數的語法是:</P>
<P> </P>
<P>返回類型 函數名(函數參數定義)</P>
<P>{</P>
<P> 函數體</P>
<P> </P>
<P> return 結果;</P>
<P>}</P>
<P> </P>
<P>其中:</P>
<P>1、返回類型: 指數據類型,如:int ,float,double, bool char ,void
等等。表示所返回結果的類型。如果是void則表示該函數沒有結果返回。</P>
<P>2、函數名:命名規則和變量命名一樣。注意要能夠表達出正確的意義。如果說一個變量命名重在說明它“是什么”的話,則一個函數重在說明它要“做什么”。比如一個函數要實現兩數相加,則可以命名為:AddTwoNum,這樣有助于閱讀。</P>
<P>3、函數參數定義:關于參數的作用,我們前面已說。現在看它的格式:</P>
<P>int AddTwoNum(int a,int b);</P>
<P>函數參數的定義有點類似定義變量,先寫參數的數據類型,上例中是int,然后再寫參數名。下面是不同之處:</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">3.1
多個參數之間用逗號隔開,而不是分號。最后一個變量之后則不需要符號。 請對比:</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">普通變量定義:</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">int a;
//<--以分號結束</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">int b;</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">函數中參數定義:</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">(int a, int b )
//以逗號分隔,最后不必以分號結束</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px"> </P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">3.2
兩個或多個參數類型相同時,并不能同時聲明,請對比:</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">普通變量定義:</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">int a,b;
//多個類型相同的變量可以一起定義。</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">函數中參數定義:</P>
<P style="MARGIN-LEFT: 10px; TEXT-INDENT: 40px">AddTwoNum(int a, b)
//這是錯誤的。</P>
<P>4、函數體:函數體用一對{}包括。里面就是函數用以實現功能的代碼。</P>
<P>5、return 結果:return
語句其實屬于函數體。由于它的重要性,所以單獨列出來講。“return”即“返回”,用來實現返回一個結果。“結果”是一個表達式。記住:當函數體內的代碼執行到return語句時,函數即告結束,如果后面還有代碼,則后面的代碼不被執行。依靠流程控制,函數體里可以有多個return語句。當然,對于不需要返回結果的函數,可以不寫return
語句,或者寫不帶結果的return語句。這些后面我們都將有例了演解。return 返回的結果,類型必須和前面“返回類型”一致。</P>
<P>一個最簡單的例子,也比一堆說明文字來得直觀,下面我寫一個函數,用于實現兩個整數,返回相加的和。這當然是一個愚不可及的函數,兩數相加直接用+就得,寫什么函數啊?</P>
<P> </P>
<P>//愚不可及的函數:實現兩數相加</P>
<P>//參數:a:加數1,b:加數2;</P>
<P>//返回:相加的和</P>
<P>int AddTwoNum(int a, int b)</P>
<P>{</P>
<P> return a + b;</P>
<P>}</P>
<P> </P>
<P>例子中,誰是“返回類型”,誰是“函數名”?誰是“參數定義”?哪些行是“函數體”?這些你都得自已看明白。這里只想指出:這是個極簡單的函數,它的函數體內只有一行代碼:即return
a+b;語句,直接返回了a+b的結果。</P>
<P> </P>
<P>最后說明一點:C,C++中,不允許一個函數定義在另一個函數體內。</P>
<P> </P>
<P>void A()</P>
<P>{</P>
<P> void B() //錯誤:函數B定義在函數A體內。</P>
<P> {</P>
<P> ....</P>
<P> }</P>
<P> </P>
<P> ...</P>
<P>}</P>
<P> </P>
<P>如上代碼中,函數B“長”在函數A體內,這不允許。不過有些語,如Pascal則允許這樣定義函數。</P>
<P> </P>
<H4><A name=12.3.2>12.3.2</A> 自定義函數實例</H4>
<P>下面我們將動手寫幾個函數,并實現對這些函數的調用。從中我們也將進一步理解函數的作用。</P>
<H5><A name=12.3.2.1>12.3.2.1</A> 小寫字母轉換為大寫字母的函數</H5>
<P><B>實例二:</B>自定義小寫字母到大寫字母的轉換函數。</P>
<P> </P>
<P>盡管這個功能很可能已經有某個庫函數實現了,但像這種小事,我們不妨自已動手。</P>
<P>之所以需要這個函數,緣于最近我們寫程序時,經常用到循環,而循環是否結束,則有賴我們向用戶提一個問題,然后判斷用戶的輸入;如果用戶輸入字母Y或y,則表示繼續,否則表示退出。</P>
<P>每次我們都是這樣判斷的:</P>
<P> </P>
<P>if(ch == 'Y' || ch == 'y')</P>
<P>{</P>
<P> ...</P>
<P>}</P>
<P> </P>
<P>平常我們的鍵盤一般都是在小寫狀態,因為用戶有可能不小心碰到鍵盤的“Caps
Lock”,造成他所輸入的任何字母都是大寫的--盡管鍵盤上有個大小寫狀態指示燈,但有誰會去那么注意呢?所以如果你的程序僅僅判斷用戶是否輸入‘y'字母,那么這個用戶敲了一個‘Y',結果程序卻“很意外”的結束了?顯然這會讓用戶很小瞧你:才三行程序就有BUG。</P>
<P> </P>
<P>(一般不傳之秘笈:用戶就像女友一樣,需要“哄”:有時你發現軟件中存在一項潛在的,系統級的嚴重BUG,你自已驚出一身冷;但在用戶那里,他們卻糾纏你立即改進某個界面上的小小細節,否則就要拋棄這個軟件--就像你的女友,天天和你吃蘿卜秧子沒有意見,但情人節那天忘了送花,她就對你失望透了。)</P>
<P> </P>
<P>言歸正傳!現在問題,我討厭每回寫那行條件都既要判斷大寫又要判斷小寫。解決方法是,在判斷之前,把用戶輸入的字母統統轉換為大寫!</P>
<P> </P>
<P>下面是將用戶輸入字符轉換為大寫的函數。要點是:</P>
<P>1、用戶輸入的字符不一定是小寫字母,說不定已經是大寫了,甚至可能根本就不是字母。所以在轉換之前需要判斷是否為小寫字母。</P>
<P>2、小寫字母‘a’的ASCII值比大寫字母‘A'大32,這可以從<A
href="http://www.d2school.com/bcyl/bhcpp/newls/ls05.htm#美國信息交換標準碼">第五章的ASCII碼表</A>中查到。不過我不喜歡查表,所以最簡單的方法就是直接減出二者的差距。所有字母的大小之間的差距都一樣。這是我們得以轉換大小寫字母的前提。</P>
<P> </P>
<P>//函數:小寫字母轉換為大寫字母。</P>
<P>//參數:待轉換的字母,可以不為小寫字母;</P>
<P>//返回:如果是小寫字母,返回對應的大寫字母,否則原樣不動返回。</P>
<P> </P>
<P>char LowerToUpper(char ch)</P>
<P>{</P>
<P> //判斷是否為小寫字母:</P>
<P> if(ch >= 'a' && ch <= 'z')</P>
<P> {</P>
<P> ch -= ('a' - 'A'); //相當于 ch -= 32; 或 ch
= ch - 32;</P>
<P> }</P>
<P> </P>
<P> //返回:</P>
<P> return ch;</P>
<P>}</P>
<P> </P>
<P>這個函數也再次提醒我們,在ASCII表里,大寫字母的值其實比小寫字母小。所以,小寫字母轉換為大寫,用的是“減”。小寫字母減去32,就搖身一變成了大寫。</P>
<P> </P>
<P>現在,有了這個函數,假設我們再遇上要判斷用戶輸入是’y'或‘n’的情況,我們就方便多了。</P>
<P>作為一種經歷,我們此次采用將函數放在要調用的代碼之前。</P>
<P> </P>
<P>//------------------------------------------------------------------------</P>
<P>//函數:小寫字母轉換為大寫字母。</P>
<P>//參數:待轉換的字母,可以不為小寫字母;</P>
<P>//返回:如果是小寫字母,返回對應的大寫字母,否則原樣不動返回。</P>
<P> </P>
<P>char LowerToUpper(char ch)</P>
<P>{</P>
<P> //判斷是否為小寫字母:</P>
<P> if(ch >= 'a' && ch <= 'z')</P>
<P> {</P>
<P> ch -= ('a' - 'A'); //相當于 ch -= 32; 或 ch
= ch - 32;</P>
<P> }</P>
<P> </P>
<P> //返回:</P>
<P> return ch;</P>
<P>}</P>
<P>//------------------------------------------------------------------------</P>
<P>int main(int argc, char* argv[])</P>
<P>{</P>
<P> char ch;</P>
<P> do</P>
<P> {</P>
<P> cout << "繼續嗎?(Y/N)";</P>
<P> cin >> ch;</P>
<P> </P>
<P> //調用函數,將可能小寫字母轉換為大寫:</P>
<P> ch = LowerToUpper(ch);</P>
<P> }</P>
<P> while(ch == 'Y');</P>
<P> </P>
<P> return 0;<BR> }</P>
<P>//------------------------------------------------------------------------</P>
<P> </P>
<P>完整的代碼見相應例子文件。例子只是為了演示如何自已定義函數,并調用。運行時它問一句“繼續嗎?”你若輸入大寫或小寫的‘y'字母,就繼續問,否則結束循環。</P>
<P>函數的返回值也可以直接拿來使用。上面代碼中的do...while循環也可以改寫的這樣:</P>
<P> </P>
<P> do</P>
<P> {</P>
<P> cout << "繼續嗎?(Y/N)";</P>
<P> cin >> ch;</P>
<P> }</P>
<P> while(LowerToUpper(ch) == 'Y');</P>
<P> </P>
<P> 功能完全一樣,但看上去更簡潔。請大家進行對比,并理解后面的寫法。</P>
<P> </P>
<P>本例中的“小寫轉換大寫”的函數,雖然我們已經成功實現,但我們并沒有將它的聲明放到某個頭文件,所以,如果在別的代碼文件中,想使用這個函數,還是不方便。確實,我們很有必要為這個函數寫一個頭文件,在講完函數后,我們將去做這件事。</P>
<P>實例二代表了一種函數的使用需求:我們將一些很多代碼都要使用的某個功能,用一個函數實現。這樣,每次需要該功能時,我們只需調用函數即可。這是函數的一個非常重要的功能:代碼重用。通過函數,不僅僅是讓你少敲了很多代碼,而且它讓整個程序易于維護:如果發現一某個功能實現有誤,需要改正或改進,我們現在只需修改實現該功能的函數。如果沒有函數?那將是不可想像的。</P>
<P> </P>
<P>但是,只有那些一直要使用到的代碼,才有必要寫成函數嗎?并不是這樣。有些代碼就算我們可能只用一次,但也很有必</P></TD></TR></TBODY></TABLE></CENTER></BODY></HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -