?? 教學--第十二章 函數(一).htm
字號:
<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>
<H5><A name=12.3.2.2>12.3.2.2</A> 使用函數改寫“統計程序”</H5>
<P><B>實例三:</B>使用函數改寫第十章“<A
href="http://d2school.com/bcyl/bhcpp/newls/ls10.htm#10.2">可連續使用的統計程序</A>”。</P>
<P> </P>
<P>我們先把第十章的例子拷過來(只拷其中的main()函數部分):</P>
<P> </P>
<P>int main(int argc, char* argv[])
<P>{
<P> float sum,score;
<P> int num; //num 用于存儲有幾個成績需要統計。
<P> int i; //i 用于計數
<P>
<P> char c; //用來接收用戶輸入的字母
<P>
<P> do
<P> {
<P><B> </B>//初始化:
<P> sum = 0;
<P> i = 1;
<P>
<P> cout << "====成績統計程序====" <<
endl;<BR>
<P> //用戶需事先輸入成績總數:
<P> cout << "請輸入待統計的成績個數:";
<P> cin >> num;
<P> cout << "總共需要輸入"<< num
<< "個成績(每個成績后請加回車鍵):" << endl;
<P>
<P> while ( i <= num)
<P> {
<P> cout << "請輸入第"
<< i << "個成績:";
<P> cin >>
score;<BR>
sum +=
score;<BR>
i++;<BR>
}<BR><BR>
//輸出統計結果:<BR> cout
<< "參加統計的成績數目:" << num << endl;<BR>
cout << "總分為:" << sum <<
endl;
<P>
<P> //提問是否繼續統計:
<P> cout <<"是否開始新的統計?(Y/N)?";
<P> cin >> c;
<P> }
<P> while( c == 'y' || c == 'Y');
<P>}
<P>//---------------------------------------------------------------------------<BR>
<P>我們將要對這段代碼所作的改進是:將其中完成一次統計功能的代碼,寫入到一個單獨的函數。
<P>
<P>//函數:實現一個學員的成績統計:
<P>//參數:無
<P>//返回:無
<P>void ScoreTotal()
<P>{
<P> float sum,score;
<P> int num; //num 用于存儲有幾個成績需要統計。
<P> int i; //i 用于計數
<P>
<P> sum = 0;
<P> i = 1;
<P>
<P> cout << "====成績統計程序(Ver 3.0)====" << endl;
<P> //用戶需事先輸入成績總數:
<P> cout << "請輸入待統計的成績個數:";
<P> cin >> num;
<P> cout << "總共需要輸入"<< num <<
"個成績(每個成績后請加回車鍵):" << endl;
<P>
<P> while ( i <= num)
<P> {
<P> cout << "請輸入第" << i <<
"個成績:";
<P> cin >> score;
<P> sum += score;
<P> i++;
<P> }
<P>
<P> //輸出統計結果:
<P> cout << "參加統計的成績數目:" << num << endl;
<P> cout << "總分為:" << sum << endl;
<P> }
<P> //---------------------------------------------------------------------------<BR>
<P>我只是將一些代碼從在原來的位置抽出來,然后放到ScoreTotal()函數體內。接下來,請看原來的main()函數內的代碼變成什么:
<P>
<P>//---------------------------------------------------------------------------
<P>int main(int argc, char* argv[])
<P>{
<P> char c;
<P>
<P> do
<P> {
<P> //調用函數實現一次統計:
<P> ScoreTotal();
<P>
<P> //提問是否繼續統計:
<P> cout <<"是否開始新的統計?(Y/N)?";
<P> cin >>
c;<BR> }
<P> while(c == 'Y' || c == 'y');
<P> }
<P>//---------------------------------------------------------------------------
<P>
<P>看,當實現統計一次的功能的代碼交由ScoreTotal()處理之后,這里的代碼就清晰多了。
<P>
<P>函數的另一重要作用:通過將相對獨立的功能代碼寫成獨立的函數,從而使整體程序增加可讀性,同樣有益于代碼維護。這稱為“模塊化”的編程思想。“模塊化”的思想并不與C++后面提倡的“面向對象”的編程思想相抵觸。而函數正是C,C++中實現“模塊化”的基石。
<P>實例三的演變過程也向我們展示了一種編寫程序的風格:當一個函數中的代碼看上去很長時,你就應該去檢查這段代碼,看看中間是否有哪些邏輯是可以獨立成另外一個函數?在本例子中,main()函數中套了兩層循環,但這兩種循環相互間沒有多大邏輯上的聯系:內層用于實現一次完整的統計功能,外層則只負責是否需要繼續下一次的統計。所以,把內層循環實現的功能獨立“摘”出去,這是一個非常好的選擇。
<P>我們閱讀VCL的源代碼時(用Pascal實現),發現盡管VCL是一套龐大的類庫,但其內部實現仍保持了相當好的簡約風格,很少有代碼超過200行的函數。這的確可以作為我們今后編寫軟件的楷模。
<P>本例的完整請見相關例子文件。其中我還把前例的LowerToUpper()函數也加入使用。
<P>
<H5><A name=12.3.2.3>12.3.2.3</A> 求多種平面形狀的面積</H5>
<P><B>實例四:</B>寫一程序,實現求長方形,三角形,圓形,梯形的面積,要求各種形狀分別用一個函數處理。
<P>
<P>程序大致的流程是:
<P>首先提問用戶要求什么形狀態的面積?然后根據用戶的輸入,使用一個switch語句區分處理,分別調用相應的函數。求不同形狀態的面積,需要用戶輸入不同的數據,基于本程序的結構,我們認為將這些操作也封裝到各函數比較合適。
<P>先請看main()函數如何寫:</P><PRE>int main(int argc, char* argv[])
{
char ch;
do
{
cout << "面積函數" <<endl;
cout << "0、退出 "<< endl //<--沒有分號!用一個cout輸出多行,只是為了省事
<< "1、長方形" << endl
<< "2、三角形" << endl
<< "3、圓形" << endl
<< "4、梯形" << endl; //<--有分號
cin >> ch;
if(ch == '0')
break;
switch(ch)
{
case '1' : AreaOfRect(); break; //長方形
case '2' : AreaOfTriangle(); break; //三解形
case '3' : AreaOfRound(); break; //圓形
case '4' : AreaOfTrape(); break; //梯形
default :
cout << "輸入有誤,請在0~4之間選擇。" << endl;
}
}
while(true);
}</PRE>
<P>函數main()的任務很清晰:負責用戶可以連續求面積,這通過一個do...while實現,同時負責讓用戶選擇每次要計算面積的形狀,這通過一個switch實現。而具體的,每一個平面圖形的面積計算,都通過三個自定義的函數來實現。盡管我們還沒有真正實現(編寫)這三個函數,但這并不影響我們對程序整體架構的考慮。
<P>當我們學會如何編寫函數的時候,我們就必須開始有意識地考慮程序架構的問題。如果說變量,表達式等是程序大廈的沙子,水泥;而語句是磚頭鋼筋的話,那么函數將是墻,棟梁。僅僅學會寫函數是不夠的,還需要學習如何把一個大的程序分劃為不同的功能模塊,然后考慮這些模塊之間的關系,最終又是如何組合為完整系統。
<P>實例四的目的在于向我們演示:當你寫一個程序時,有時候你不必去考慮一些小函數的具體實現,相反,你就當
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -