函式,string類別
2012/11/20 謝碧景(c)編製更新
學習目標
一、函式/函數簡介
一般程式中會將特定功能或經常需重複使用之程式編撰成獨立的小單元,稱為程序,主程式可呼叫此程序,在C++即稱此程序為函式/函數(function),其可傳回或不傳回返回值,而在呼叫函數過程中亦可傳遞參數或不傳遞參數。此外 C++ 還提供內建函數,例如:Math數學函數、亂數函數、char字元函數、轉換函數(字串轉數值函數、數值轉字串函數)等。
函數可分內建(pre-defined)函數與自訂(user-defined)函數。內建函數為編譯器提供的公用函式庫,而自訂函數是依使用者需求自行定義的函數。
函式庫代表函數集合,善用函式庫可簡化程式的開發。可利用標頭檔(副檔名為.h)集合所設計的函數,再使用#include前置處理器於程式前端加入標頭檔(header file)。當程式原始碼編譯為執行檔之前,會先加入標頭檔進行編譯,再編譯程式內容。
可利用cplusplus.com查詢各個函式庫及函式的使用方法 http://www.cplusplus.com/
*註:在其他語言中若無傳回值之程序稱為副程式(subroutine),有傳回值之程序即稱為函數(function)。
二、自訂函數(/函式)
函式/函數(function)會執行指定的動作,可分無回傳值和有回傳值的函數;其依有無參數,又分無參數和有參數的函數。
(一)建立函數
1.有回傳值的自訂函數格式:
回傳值資料型態 函數名稱(型態 參數1,型態 參數2,...) //參數列可略,為接收呼叫函數傳進的值
{
敘述;
return(值 或 運算式); //返回值
}
*註:
return 返回呼叫函數,會傳回返回值,其資料型態必須和回傳值資料型態的宣告相同。
『參數列』接收呼叫函數傳進的值,須宣告與呼叫函數對應『引數』資料型態相同,參數可為常數、變數、陣列等、使用者自定資料型態。
函數建立後不會執行,需在主程式中呼叫,才會執行。流程圖如下:
2.無回傳值且無參數之函數格式:
void 函數名稱() //void 無回傳值,可省略
{
敘述;
}
//主程式
函數名稱(); //呼叫
3.無回傳值但有參數之函數格式:
void 函數名稱(型態 參數1,型態 參數2,...)
{
敘述;
}
函數名稱(引數1,引數2,...);
//呼叫函數
*註:參數列宣告需含參數型態及參數名稱,若多個參數,請以逗號隔開,引數和參數的個數需相同。
(二)呼叫函數
在 main() 函數(即主程式或稱主函數)中呼叫自訂函數,即會執行自訂函數,若函數有傳回值,則以同型態之變數儲存返回值,如下:
回傳值資料型態 變數=函數名稱(引數) //引數(argument)
變數依其有效範圍分為全域變數及區域變數。
(1)全域變數:定義在函式外的變數,其有效範圍是整個檔案。
(2)區域變數:定義在一個函式中的變數,其有效範圍是在該函式內。
◆範例1:以函數設計,輸入攝氏(Celsius)溫度,並轉換華氏(Fahrenheit)溫度輸出。(檔名:func-ex1.cpp)
(三)宣告函數原型
宣告函式在 using namespace std; 之下,main() 之上,函式一旦執行到return,就會立刻回傳。
如果自訂函數定義寫在 using namespace std; 之下,main() 之上,呼叫時不用宣告函數的原型;若自訂函數定義寫在 main() 主程式的下方,則呼叫自訂函數時必須宣告函數的原型,否則會產生編譯錯誤。注意:結束的【;】符號,而參數名稱可省略,一般會將函數的原型宣告放在檔頭宣告之後。
回傳值資料型態 函式名稱(資料型態1 參數1 , 資料型態2 參數2…);
◆範例2:同上範例。(檔名:func-ex2.cpp)
◆範例3:求矩形面積。
方法Ⅰ:自訂函數定義寫在 main() 主程式的下方,則呼叫自訂函數時必須宣告函數的原型。 (檔名:func-ex3-1.cpp)
方法Ⅱ:自訂函數定義寫在 main() 主程式的上方,呼叫時不用宣告函數的原型。 (檔名:func-ex3-2.cpp)
◆範例4:排序演算法
氣泡排序演算法,以函數設計(無回傳值有參數)。(檔名:func-ex4-1.cpp)
執行結果:
選擇排序演算法,以函數設計(無回傳值有參數)。(檔名:func-ex4-2.cpp)
*註:4-16為自訂函數_選擇排序,18-23為自訂函數_輸出陣列元素。
執行結果:
(四)參數
傳值呼叫(call by value)
傳參考呼叫(call by reference)
傳址呼叫( call by address))
(五)遞迴(Recursive)
函數本身呼叫自己的函數即為遞迴,撰寫時函式中必須有結束點(即終止遞迴條件),否則會造成無止境的遞迴錯誤。
◆ 範例5:計算自然數的階層,n!【提示:n!=n*(n-1)*(n-2)*...*2*1 ,例如:7!=7*6*5*4*3*2*1,3!=3*2*1,而0!=1】 (檔名:func-ex5.cpp)
5!=f(5)=5*f(4)=5*4*f(3)=5*4*3*f(2)=5*4*3*2*f(1)=5*4*3*2*1*f(0)=5*4*3*2*1
方法Ⅰ
方法Ⅱ
(六)多載 (overloading)
函數的命名允許使用多個相同的名稱,並透過傳遞參數列或參數的型態來區別不同的方法,稱為『函數多載』。
◆範例6:建立Area()函數,以多載方式分別求正方形和矩形面積。 (檔名:func-ex6.cpp)
執行結果
三、內建函數
C++提供許多功能強大的函式庫,使用內建函式需先使用 #include命令引入對應的『函式庫』,並寫在程式的一開始,即標頭檔,標頭檔內建許多函數。
(一)數學函數
數學函數使用前需先引入 #include <cmath> ,在程式的開頭,該標頭檔內建許多數學函數,可運算三角函數、指數、對數…等。
常用數學函數:
例:數學函數
*註:行3 #include <cmath> 引入函式庫,即可使用數學函數運算。
執行結果
(二) 亂數函數
1.以 srand(time(NULL)) 函數產生亂數種子:
srand()是隨機(random)產生亂數種子(seed)之意,為使亂數種子產生不規則的亂數(即每次不同),會以系統時間為主,以時間函數time()當其種子,time(NULL)會傳回自1970/1/1到程式執行當時所經過的秒數,因此每次取得之值會不同。
2.以 rand() 函數取得亂數:
rand() 會搭配【%】餘數運算子產生某特定範圍的亂數,如下:
產生 m <= r <= n 的亂數,公式如下:
int r = m + rand() % (n-m+1);
// 產生 m <= r <= n 的亂數
取 1-6 的亂數 r=(rand() % 6) +1
取 1-100 的亂數 r=(rand() % 100) +1
取 100-1000 的亂數 r=(rand() % 901) +100
3.使用 time() 函數需引入標頭檔 <ctime>,使用 srand() 和 rand() 函數需引入 <cstdlib>,所以使用亂數程式開頭需引入兩個標頭檔。
#include <ctime >
#include <cstdlib>
◆範例7:骰子遊戲,連續擲8次骰子,輸出其點數 (即 以亂數產生8次1-6 點)。(檔名:func-ex7.cpp)
執行結果
◆範例8:班級32位同學,以亂數產生5 個號碼。 (檔名:func-ex8.cpp)
執行結果
(三) 字串函數
字串函數使用前需先引入 #include <cstring> 或 #include <string.h> ,在程式的開頭,該標頭檔內建許多字串函數。
字串函數是處理字串相關功能。如下:【參閱:C++ Reference→string】
◆範例9:strcpy 及 strlen 函數之應用。【提示:字串函數需引入 #include <cstring>】(檔名:func-ex9.cpp)
執行結果
◆範例10:統計字數:每輸入一行英文句子,即顯示每行之字數,並於輸入完後,統計總字數。(檔名:func-ex10.cpp)
執行結果
(四) 字元函數
(五)轉換函式
四、string 類別應用
C++在內建的標準函式庫中有個 string 類別(class),如同資料型態設定(int、char等),可定義變數;使用前需先引入 #include <string>【參閱:C++ Reference→string】。
讀取字串的方式:
例:
§實作練習
(一) 函數/函式
題1:以函式設計,輸入一個整數,求其絕對值。
題2:以函式設計,輸入一個整數,求其平方根。【參閱數學函式 sqrt(x) 】
題3:以函式設計,求 x 的 n 次方。【參閱數學函式 pow(x,n) 次方函式設計 】
題4:以函式設計,輸入一正整數,並判斷此數是否為質數。
題5:找出所有小於50000之正整數,其值等於其各個位數之階乘和。
例: 4!+0!+5!+8!+5! (以函式設計)
=24+1+120+40320+120
=40585
題6:以函式設計,銀行存款計算方式如下:
N天後的存款=開始存入的錢x(1+RATE/365)^N,其中RATE代表年利率。試寫一程式包含下列兩個功能:
(1)輸入開始的存款經過N天後,輸出存款為何?
(2)輸入N天後的存款,求開始時要存入多少錢?【提示:pow(x,n)函數 ,參閱:數學函式】
題7:以函式設計,A、B二正整數,若所有能整除A的正數之和等於B(包括1,但不包括A本身);反之亦然,則A、B二數稱為"friendly"
例如220及 284,其中能整除220之數有:1+2+4+5+10+11+20+22+44+55+110=284
能整除284的有:1+2+4+71+142=220
設計一程式: 找出所有成"friendly"關係的正整數組,且此正整數組中的兩個數均小 於500。
題8:以函式設計,輸入兩個正整數,並求其最大公因數 gcd及最小公倍數 lcm 【提示:a*b兩數乘積等於gcd*lcm】
【進階題】以函式設計,輸入三正整數,求此三數之最大公因數與最小公倍數【提示:利用gcd(gcd(a,b),c) 求三數之最大公因數】
題9:以函式設計,身分證認證:確認一組身分證號碼是否合法?
(1)英文代號以下表轉換成數字
A=10 台北市 J=18 新竹縣 S=26 高雄縣
B=11 台中市 K=19 苗栗縣 T=27 屏東縣
C=12 基隆市 L=20 台中縣 U=28 花蓮縣
D=13 台南市 M=21 南投縣 V=29 台東縣
E=14 高雄市 N=22 彰化縣 *W=32 金門縣
F=15 台北縣 *O=35 新竹市 X=30 澎湖縣
G=16 宜蘭縣 P=23 雲林縣 Y=31 陽明山
H=17 桃園縣 Q=24 嘉義縣 *Z=33 連江縣
*I=34 嘉義市 R=25 台南縣
(2)英文轉成的數字, 個位數乘9再加上十位數
(3)各數字從右到左依次乘1、2、3、4....8
(4)求出(2),(3)之和
(5)求出(4)除10後之餘數,用10減該餘數,結果就是檢查碼,若餘數為0 則檢查碼就是0
例如: 身分證字號 A123456789
(二)遞迴函式
題10:以遞迴函式設計,求N!【提示:N!=N*(N-1)*(N-2)*...*2*1 】
題11:以遞迴函式設計,輸入一個整數,並反轉此數值輸出。
題12:以遞迴函式設計,求 Fibonacci 費氏數列﹦0,1,1,2,3,5,8,13,… 即 fn=1 當n=1或 n=2, fn=fn-1+fn-2 當n>2