?? 第12章 函數(一).htm
字號:
<P>關閉剛才的工程,CB會問你是否存盤,統統不存(如果你要存,就存到別的什么地方去,不要存在CB默認的目錄下)。然后重新創建一個空白的控制臺工程。在代碼窗口里加入以下兩行黑體代碼:</P>
<P>//---------------------------------------------------------------------------</P>
<P>//包含“數學庫函數”的頭文件,因為sin()函數的聲明在這個頭文件里:</P>
<P><B>#include <math.h></B></P>
<P>#pragma hdrstop</P>
<P>//---------------------------------------------------------------------------</P>
<P>#pragma argsused</P>
<P>int main(int argc, char* argv[])</P>
<P>{</P>
<P><B> double b = sin(3.14159);</B></P>
<P> return 0;</P>
<P>}</P>
<P>//---------------------------------------------------------------------------</P>
<P>并不需要編譯及運行這個程序。因為我們只是想找到sin()函數的聲明。</P>
<P>本來,我們可以通過老辦法來找到sin函數聲明。按Ctrl+回車鍵打開math.h文件,然后通過Ctrl+F打開查找對話框,找到sin函數。不過CB為我們提供了一種更方便的查找函數聲明的方法,有點像我們在網頁點擊鏈接:</P>
<P>請按住Ctrl鍵不放,然后將鼠標移到代碼中的 sin處,注意要準確在移到sin字母身上,發現什么?呵,sin出現了超鏈接效果:</P>
<P><IMG height=40 src="第12章 函數(一).files/ls12.h8.gif" width=196
border=0></P>
<P>點一下,CB將自動打開math.h頭文件,并且跳轉到sin函數的聲明處。</P>
<P>(以上操作的成功依賴于你正確地照我說的,在代碼中加入#include<math.h>這一行,當然你在安裝CB時也必須選擇了安裝源代碼。最后,成功打動后,記得將math.h文件設置為只讀。)</P>
<P><IMG height=166 src="第12章 函數(一).files/ls12.h7.gif" width=443
border=0></P>
<P> </P>
<P>從圖中我們看到,sin函數的參數只有一個:__x,類型要求是double(雙精度浮點數,如果你忘了,復習<A
href="http://www.d2school.com/bcyl/bhcpp/newls/ls04.htm#4.4">第四章</A>)。</P>
<P>所以,當我們調用sin函數來求正弦值時,我們最好應該給它一個double類型的數,如:</P>
<P>double x = 3.1415926 * 2;</P>
<P>double y = sin(x);</P>
<P> </P>
<P>當然, 我們傳給它一個整數:</P>
<P>double y = sin(0);</P>
<P>或者,傳給它一個單精度浮點數:</P>
<P>float x = 3.14;</P>
<P>double y = sin(x);</P>
<P>這些都是可以的。這并不違反“參數類型由函數本身決定,不能由調用者決定”的原則。因為在<A
href="http://www.d2school.com/bcyl/bhcpp/newls/ls07.htm#7.2">第七章第二節講算術類型轉換</A>時,我們知道一個整數,單精度浮點數,都可以隱式地轉換為雙精度浮點數。并且屬于安全的類型轉換,即轉換過程中,數據的精度不會丟失。(反過來。一個double類型轉換為int類型,就是不安全的轉換。比如3.14159轉換為整型,就成了3。)</P>
<P>有些函數并不需要參數,比如,我們用了許多次的控制臺函數:getchar();。這個函數要做的事就是:等待用戶輸入一個字符并回車。前面講數學函數時,舉的隨機數例子。要想讓程序能夠產生真正的隨機數,需要讓程序事先做一些準備。所以我們調用randmize()函數。這個函數也沒有參數。因為我們調它的目的,無非是:喂,告訴你,我一會兒可能要用到隨機數,你做好準備吧。</P>
<H4><A name=12.2.4>12.2.4</A> 如何得到函數的運行結果</H4>
<P>函數總是要實現一定的功能,所以我們也可以認為函數執行起來就像是在做一件事。</P>
<P>做一件事一般會有個結果,當然,只是“一般會有”。有些事情真的會有結果嗎?嗯?看來,這句話勾起某些同學一些舊事,他們陷入了深深的,似乎很痛苦的回憶之中……對此,為師我表示最大的理解,并有一言相送:“并非是一件事情不會有結果,只是,有時候,我們并不需要結果……”。</P>
<P>寫函數的人就是這樣的啊。函數需要什么參數,由寫函數的人決定,函數返回什么結果,也由他們決定。如果他們認定這個函數不需要什么結果,那么這個函數就將寫成返回void類型。void是“無類型”之意,這就相當于這個函數沒有返回結果。</P>
<P>舉修理電視的例子來說,我們認為它至少應該返回一個bool值,即真或假。真表示電視修好了,假表示電視修不好。</P>
<P>bool XiuliDianshi(TDianshi ds);</P>
<P>然后,我們如何得知結果呢?</P>
<P>bool jg = XiuliDianshi(ds);</P>
<P>看,我們也聲明了一個bool變量,然后讓它等于這個函數,這就可以得到函數的返回值。</P>
<P> </P>
<P>來看一個實例,仍然是sin函數。</P>
<P>double x = 3.1415926;</P>
<P>double y = sin(x);</P>
<P>y值將是一個非常接近0的值。</P>
<P> </P>
<P>getchar();是一個不需要參數的函數,但它有返回值。它返回用戶輸入的字符(事實上它返回的是整型)。所以我們可以這樣用:</P>
<P>char c = getchar();</P>
<P>c將得到用戶輸入的字符。</P>
<P>而另一個例子:
randomize()函數,則赤條條地來,赤條條地走,瀟灑得很。根本就不打算返回什么。連到底準備成功了嗎?都不返回--因為它認定自已一定會執行成功。</P>
<P> </P>
<P>還需說明的是,有時函數是有返回值,但我們并不在意。還是getchar();我們不是一直在使用它來“暫時”停止程序,以期能看到DOS窗口上的輸出結果嗎?這時,用戶輸入什么鍵我們都不在意。所以我們總這么寫:</P>
<P>getchar();</P>
<P>就完事,并沒讓誰去等于誰。</P>
<P> </P>
<P>最后一點針對學過PHP,JavaScript,Perl等腳本語言的學員:在C,C++里,一個函數返回值的類型,必須是確定的。不像腳本語言中的函數,可以返回不定類型的結果。</P>
<H4><A name=12.2.5>12.2.5</A> 調用庫函數的實例</H4>
<P><B>實例一:</B>使用庫函數創建或刪除文件夾。</P>
<P>(本例子中刪除的文件夾將無法恢復!請大家操作時小心。)</P>
<P> </P>
<P>在本實例里,我們將“大膽地”在C盤根目錄下創建指定的目錄(文件夾),然后再把它刪除。</P>
<P>使用到兩個函數:</P>
<P>1、mkdir("文件夾名稱")</P>
<P>參數是一個字符串,即指定的文件夾名稱。</P>
<P>返回值比較特殊:整數:0表地成功,-1表示失敗:比如那個文件夾已經存在,或者,你想讓它一次創建多級目錄,如:C:\abc\123,而C:\abc并不存在。</P>
<P>2、_rmdir("文件夾名稱")</P>
<P>參數是一個字符串,即指定的文件夾名稱。</P>
<P>返回同樣是0或-1。刪除一個文件夾比較容易失敗:比如文件夾內還有文件或其它子文件夾,比如該文件夾正好是當前文件夾,另外你也不能刪除一個根目錄,比如你想刪除:"c:\"
!!!(想刪除整個C盤?病毒?)</P>
<P> </P>
<P>兩個函數都在“dir.h”文件里聲明,所以我們需要include它。</P>
<P> </P>
<P>下面是完整的代碼:</P>
<P>//---------------------------------------------------------------------------</P>
<P>#include <dir.h></P>
<P>#include <iostream.h></P>
<P>#pragma hdrstop</P>
<P>//---------------------------------------------------------------------------</P>
<P> </P>
<P>#pragma argsused</P>
<P>int main(int argc, char* argv[])</P>
<P>{</P>
<P> char path[50];</P>
<P> char ch;</P>
<P> </P>
<P> do</P>
<P> {</P>
<P> //讓用戶選擇操作項: </P>
<P> cout << "0、退出本程序" <<
endl;</P>
<P> cout << "1、創建文件夾" <<
endl;</P>
<P> cout << "2、刪除文件夾" <<
endl;</P>
<P> cout << "請選擇:";</P>
<P> cin >> ch;</P>
<P> </P>
<P> //如果輸入字符'0',則結束循環以退出:</P>
<P> //請注意break在這里的用法:</P>
<P> if(ch == '0')</P>
<P> {</P>
<P> break;</P>
<P> }</P>
<P> </P>
<P> //如果輸入的既不是1,也不是2,要求重新輸入,</P>
<P> //請注意continue在這里的用法:</P>
<P> if(ch != '1' && ch != '2')</P>
<P> {</P>
<P> cout <<
"輸入有誤,請重新選擇!" << endl;</P>
<P> continue;</P>
<P> }</P>
<P> </P>
<P> //不管是創建還是刪除,總得要用戶輸入文件夾名稱:</P>
<P> cout << "請輸入文件夾的絕對路徑:" ;</P>
<P> cin >> path;</P>
<P> </P>
<P> //先定義一個bool變量,用來判斷操作是否成功:</P>
<P> bool ok;</P>
<P> //現在需要區分用戶想做什么了:</P>
<P> if(ch == '1') //創建文件夾:</P>
<P> {</P>
<P> ok = (0 ==
mkdir(path)); //若mkdir返回結果等于0,表示操作成功</P>
<P> }</P>
<P> else //否則就是要刪除了!</P>
<P> {</P>
<P> ok = (0 ==
_rmdir(path)); //同樣,_rmdir也是返回0時表示成功</P>
<P> }</P>
<P> </P>
<P> //給出結論:</P>
<P> if(ok)</P>
<P> {</P>
<P> cout
<< "恭喜!操作成功。" << endl;</P>
<P> }</P>
<P> else</P>
<P> {</P>
<P>
cout <<"抱歉,操作失敗,請檢查您的輸入。" << endl;</P>
<P> }</P>
<P> }</P>
<P> while(true);</P>
<P> </P>
<P> return 0;</P>
<P>}</P>
<P>//---------------------------------------------------------------------------</P>
<P> </P>
<P>代碼里頭有一個do...while循環,一個continue,和break;另有幾個if...else,這些相信你可以邊運行程序,邊看明白其間的邏輯。惟一陌生的是最開頭的一句:</P>
<P>char path[50];</P>
<P>這里涉及到了“數組”的知識。針對本例,你可以這樣理解:</P>
<P>char ch; </P>
<P>這一行我們能看懂,定義了一個字符類型的變量,ch。ch變量的空間是1個字節,能存儲一個字符,因此你可以用它存儲諸如:'A','2','H'等,但現在我們要輸入的是:"c:\abcd"這么一句話,所以變量ch無法勝任。C,C++提供了數組,我們可以通過定義數組來存儲同一類型的多個數據。如:</P>
<P>char path[50];</P>
<P>本行定義了path這個數組,它可以存儲50 個 char類型的數據。</P>
<P>注意,path只能存儲最多50個字符。所以在運行本例時,不要輸入太長的文件夾名稱。</P>
<P>另外,Windows對新建文件夾的名稱有一些特殊的要求,所以如果文件夾名稱含了一些非法字符,操作將失敗。</P>
<P>以下是我運行的一個結果:<BR></P>
<P><IMG height=220 src="第12章 函數(一).files/ls12.h8.jpg" width=416
border=0></P>
<P> </P>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -