版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第4章M腳本與M函數(shù)4.1使用M文件編程4.2M函數(shù)4.3函數(shù)的調用與函數(shù)句柄4.4函數(shù)編程的實例 4.1使用M文件編程
4.1.1M文件的結構
1.函數(shù)M文件一個函數(shù)M文件與腳本文件類似,它們都是一個擴展名為“.m”的文本文件。同腳本M文件一樣,函數(shù)M文件不進入命令窗口,而是由文本編輯器所創(chuàng)建的外部文本文件。函數(shù)M文件不是獨立執(zhí)行的文件,它接受輸入參數(shù)、提供輸出參數(shù),只能被程序調用。一個函數(shù)M文件通常包含以下部分:
函數(shù)定義語句;
H1幫助行;
幫助文本;
函數(shù)體或者腳本文件語句;
注釋語句。為了易于理解,可以在書寫代碼時添加注釋語句。這些注釋語句在編譯程序時會被忽略,因此不會影響編譯速度和程序運行速度,但是能夠增加程序的可讀性。
一個完整的函數(shù)M文件的結構如下:
functionf=fact(n) 函數(shù)定義語句
%Computeafactorialvalue. H1行
%FACT(N)returnsthefactorialofN, 幫助文本
%usuallydenotedbyN!
%Putsimply,FACT(N)isPROD(1:N). 注釋語句
f=prod(1:n); 函數(shù)體
函數(shù)定義語句只在函數(shù)文件中存在,定義函數(shù)名稱、輸入/輸出參數(shù)的數(shù)量和順序,腳本文件中沒有該語句。
2.腳本M文件
腳本文件也叫命令文件,是獨立執(zhí)行的文件,它不接受輸入參數(shù),不返回任何值,而是代碼的結合,該方法允許用戶將一系列MATLAB命令輸入到一個簡單的腳本“.m”文件中,只要在MATLAB命令窗口中執(zhí)行該文件,則會依次執(zhí)行該文件中的命令。
腳本M文件中包含一族由MATLAB語言所支持的語句,它類似于DOS下的批處理文件,它的執(zhí)行方式很簡單,用戶只需在MATLAB的提示符“>>”下鍵入該M文件的文件名,這樣MATLAB就會自動執(zhí)行該M文件中的各條語句,并將結果直接返回到MATLAB的工作空間。在使用腳本文件時需要注意一點:如果當前工作區(qū)中存在與該腳本同名的變量,則當輸入該文件名時,系統(tǒng)將其作為變量名執(zhí)行。
MATLAB中有一個專門用于尋找“.m”文件的路徑搜索器?!?m”文件是以目錄和文件夾的方式分布于文件系統(tǒng)中的,一部分“.m”文件的目錄是MATLAB的子目錄,由于MATLAB的一切操作都是在它的搜索路徑,包括當前路徑中進行的,因此如果調用的函數(shù)在搜索路徑之外,MATLAB就會認為此函數(shù)不存在。
3.塊注釋
在MATLAB?5以前的版本中,注釋是逐行進行的,采用百分號(%)進行標記。逐行注釋不利于用戶增加和修改注釋內容。在MATLAB?5及以后的版本中,用戶可以使用“%{”和“%}”符號進行塊注釋,“%{”和“%}”分別代表注釋塊的起始和結束。
4.代碼單元
一個代碼單元指用戶在M文件中指定的一段代碼,以一個代碼單元符號:兩個百分號加空格,即“%%”為開始標志,到另一個代碼單元符號結束。如果不存在代碼單元符號,則直到該文件結束。用戶可以通過MATLAB編輯器中的cell菜單創(chuàng)建和管理代碼單元。
需要注意的是,代碼單元只能在MATLAB編輯器窗口中創(chuàng)建和使用,而在MATLAB命令窗口中是無效的。當在命令窗口中運行M文件時,將執(zhí)行文件中的全部語句。4.1.2M文件的建立、運行與命名規(guī)則
M文件的語法類似于一般高級語言,是一種程序化的編程語言,但是與傳統(tǒng)的高級語言相比,M文件又有其特點。它只是一個簡單的ASCII碼型文本文件,因此,它的語法比一般的高級語言要簡單,程序也容易調試,并具有很好的交互性。
1.M文件的建立與運行
M文件的建立與運行都可以在M文本編輯器中進行。在MATLAB主窗口中,單擊菜單命令“File?|?New?|?Script”或“Function”即可打開M文本編輯器,如圖4-1所示。
輸入完程序命令代碼后,按照M文件的命名規(guī)則對文件進行命名并保存。
單擊菜單命令“Debug?|?Run”或“F5”即可運行腳本程序。M函數(shù)程序的運行需要由其他程序調用。圖4-1M文本編輯器
2.M文件的命名規(guī)則
M文件的命名規(guī)則如下:
(1)文件名命名要用英文字符,第一個字符必須是字母而不能是數(shù)字,其中間不能有非法字符。
(2)文件名不要取為MATLAB的固有函數(shù),盡量不要是簡單的英文單詞,最好是由大小寫英文、數(shù)字、下劃線等組合而成的。原因是簡單的單詞命名容易與內部函數(shù)名同名,結果會出現(xiàn)一些莫名其妙的錯誤。
(3)文件存儲路徑一定要為英文。
(4)文件名不能為兩個單詞,如randomwalk,應該寫成random_walk,即中間不能有空格等非法字符。4.1.3程序的調試
在開發(fā)函數(shù)或M文件過程中,會不可避免地出現(xiàn)錯誤,即運行故障。MATLAB提供了很多函數(shù)和方法,來幫助調試函數(shù)或腳本程序。
在MATLAB的M文本編輯器窗口中,單擊菜單命令“Debug|SaveFileandRun”,即可運行M文本編輯器中的內容。
在MATLAB表達式中,有兩類錯誤:語法錯誤和運行錯誤。在運行過程中,可能存在一些語法或其他錯誤而自動終止執(zhí)行,而需要進行類似于修正錯誤或更改參數(shù)的調試。
當MATLAB計算一個表達式的值或一個函數(shù)被編譯到內存時會發(fā)現(xiàn)語法錯誤。一旦發(fā)現(xiàn)語法錯誤,MATLAB立即標志這些錯誤,并提供有關所遇到的錯誤類型,以及M文件中發(fā)生錯誤處的行數(shù)。給定這些反饋信息后,就很容易糾正這些錯誤。而另一方面,即使MATLAB標志了運行錯誤,但找出錯誤一般比較困難。當發(fā)現(xiàn)運行錯誤時,MATLAB把控制權返回給命令窗口和MATLAB的工作空間,失去了對發(fā)生錯誤的函數(shù)空間的訪問權,因此用戶不能詢問函數(shù)工作空間中的內容排除問題。
MATLAB程序的調試一般使用兩種方法:直接調試法和利用調試工具。
1.直接調試法
MATLAB語言具有強大的運算能力,指令系統(tǒng)簡單,因此程序通常非常簡潔。對于簡單的程序可以采用直接調試的方法。
在程序調試時,程序運行中變量的值為一個重要的線索。由于在函數(shù)調用時只返回最后的輸出參數(shù),而不返回中間變量,因此,可以選擇下面的方法查看程序運行中的變量值。
(1)通過分析后,將可能出錯的語句后面的分號(;)刪除,將結果顯示在命令窗口中,與預期值進行比較。
(2)利用函數(shù)disp()顯示中間變量的值。
(3)在程序中的適當位置添加keyboard指令。程序運行至此時將暫停,在命令窗口中顯示k>>提示符,用戶可以查看工作區(qū)中的變量,可以改變變量的值。輸入return指定返回程序,繼續(xù)運行。
(4)在調試一個單獨的函數(shù)時,可以將函數(shù)改寫為腳本文件,此時可以直接對輸入參數(shù)賦值,然后以腳本方式運行該M文件,這樣可以保存中間變量,在運行完成后,可以查看中間變量的值,對結果進行分析,查找錯誤所在。
2.利用調試工具
可采用的調試工具有命令行調試程序和調試器界面調試程序。
文本編輯器中的Debug菜單提供了全部的調試選項,另外,MATLAB主窗口中的Debug菜單提供了一些調試命令,方便調試時在命令窗口中查看運行狀態(tài)。調試選項及其功能如表4-1所示。表4-1調?試?菜?單?項
Set/ClearBreakpoint:設置或清除斷點??梢赃x擇該選項對當前行進行操作,或者通過快捷鍵F12,或者直接點擊該行左側的“-”。設置斷點時該處顯示為紅點。再次進行相同的操作則刪除該斷點。
一旦這些斷點被設置,程序將會運行到第一個斷點并在那里停止。在調試的過程中,會有一個綠色的箭頭出現(xiàn)在當前行。
一旦到達某個斷點,程序員可以通過在命令窗口中鍵入變量名的方法檢查或修改在工作區(qū)內的任一變量。當程序員對程序的這一點感到滿意時,可以通過重復按F10鍵一行一行地進行調試,也可以按F5鍵運行到下一個斷點。它總是能檢測程序中的每一個斷點中的任何一個變量的值。
Set/ModifyConditionalBreakpoint…:該選項用于設置或修改條件斷點。條件斷點為一種特殊的斷點,當滿足指定的條件時則程序執(zhí)行至此即停止,條件不滿足時則程序繼續(xù)進行。其設置界面如圖4-2所示,在輸入框中輸入斷點條件則將當前行設置為條件斷點。圖4-2設置或修改條件斷點對話框
Enable/DisableBreakpoint:該選項用于開啟或關閉當前行的斷點,如果當前行不存在斷點,則設置當前行為斷點;如果當前行是斷點,則改變該斷點的狀態(tài)。在調試時,被關閉的斷點將會被忽略。
在程序調試中,變量的值是查找錯誤的重要線索,在MATLAB中有三種查看變量值的方法:
(1)在編輯器中將鼠標放置在待查看的變量處停留,則在此處顯示該變量的值;
(2)在工作區(qū)瀏覽器中查看該變量的值;
(3)在命令窗口中輸入該變量的變量名,則顯示該變量的值。調試器的另外一個重要特性是可在“Debug”菜單的“StopifErrors/Warnings”項目中找到錯誤。如果程序中發(fā)生了一個錯誤,這個錯誤導致了電腦死機或產生了錯誤信息,程序員可以打開這些選項,并執(zhí)行這個程序。這個程序將會運行到錯誤或警告的斷點并停在那兒,它允許程序員檢查變量的每一個值,并幫助找出出錯的原因。若一個錯誤被發(fā)現(xiàn),程序員能用編輯器來更正這個MALTAB程序,并把更新的版本存到磁盤上,在調試沒結束之前,它必須重復以上的動作。這個步驟將會重復下去直到這個程序沒有錯誤出現(xiàn)。4.1.4程序錯誤的檢測和處理
在MATLAB的命令表達式中可能存在兩種類型的錯誤,即語法錯誤和運行錯誤。
語法錯誤。語法錯誤發(fā)生在M文件程序代碼的生成過程中,一般是由于編程人員的錯誤操作引起的,常見的如變量或函數(shù)名拼寫錯誤、引號或括號以及標點符號缺少或應用不當,也可能是由函數(shù)參數(shù)輸入類型有誤或是矩陣運算階數(shù)不符等所引起的。
運行錯誤。運行錯誤一般指在程序運行過程中,出現(xiàn)溢出或是死循環(huán)等異?,F(xiàn)象。
1.錯誤的檢測
在編程過程中,無論程序的編寫多么謹慎,在不同的環(huán)境下運行時都有可能產生意外的錯誤。因此,有必要在程序中添加錯誤檢測語句,保證程序在所有的條件下都能夠正常運行。
1)錯誤檢測
與C語言類似,MATLAB中的try-catch語句可用于錯誤檢測。如果程序中的一些語句可能會產生非預計的結果,可以將這些語句放在try-catch塊中。try-catch語句可以檢測所有錯誤,并且分別進行處理。格式如下:
try
表達式1
catch
表達式2
end
一個try-catch塊分為兩部分。第一部分以try開始,第二部分以catch開始,整個塊以end結束。程序首先正常執(zhí)行第一部分,如果有錯誤發(fā)生,則停止執(zhí)行該部分的其他語句,轉而執(zhí)行catch中的語句。catch部分對錯誤進行處理,可以顯示錯誤提示、執(zhí)行默認語句等。在try-catch語句中,可以嵌套其他的try-catch語句,其格式如下:
try
表達式1 %執(zhí)行表達式1
catch
try
表達式2 %嘗試從錯誤中恢復
catch
disp'Operationfailed' %處理錯誤
end
end
2)發(fā)出錯誤報告
在MATALB中,error()函數(shù)可以報告錯誤并且中斷程序運行。用戶可以通過指定error()函數(shù)參數(shù)的方式指定將要發(fā)出的錯誤信息。MATALB提供了一系列錯誤識別和處理函數(shù),如表4-2所示。
3)識別錯誤發(fā)生的原因
當錯誤發(fā)生時,用戶需要知道錯誤發(fā)生的位置及錯誤原因,以便能夠正確處理錯誤。lasterror()函數(shù)可以返回最后發(fā)生的錯誤的相關信息,輔助用戶識別錯誤。
lasterror()函數(shù)的返回結果為一個結構體,該結構體包含三個域,分別為message、identifier、stack。message為字符串,其內容為最近發(fā)生的錯誤的相關文本信息;identifier也是一個字符串,其內容為錯誤消息的類別標志;stack為一結構體,其內容為該錯誤的堆棧中的相關信息。stack包含三個域,分別為file、name和line,表示文件名、函數(shù)名和錯誤發(fā)生的行數(shù)。
4)錯誤重現(xiàn)
在一些情況下,需要重現(xiàn)已經拋出過的錯誤,以便于對錯誤進行分析,函數(shù)rethrow()可以重新拋出指定的錯誤。
該函數(shù)的格式為rethrow(err),其中,輸入參數(shù)err用于指定需要重現(xiàn)的錯誤,err必須為MATLAB結構體,包含message、identifier、stack中至少一個域,這三個域的類型與lasterror返回結果相同。
該語句執(zhí)行后程序運行中斷,將控制權轉給鍵盤或catch語句的上一層模塊。
rethrow()函數(shù)通常與try-catch語句一起使用,如:
try
表達式1
catch
do_cleanup
rethrow(lasterror)
end
2.標志符的應用
1)消息標志符的格式
消息標志符為一個字符串,指定錯誤或警告消息的類別(component)及詳細信息(mnemonic)。通常為“類別:詳細信息”的格式。如:
MATLAB:divideByZero
Simulink:actionNotTaken
TechCorp:notFoundInPath
兩個部分都需要滿足如下的規(guī)則:
(1)不能包含空格;
(2)第一個字符必須為字母;
(3)后面的字符可以為數(shù)字或下劃線。類別部分指定錯誤或警告可能發(fā)生的大體位置,通常為某一產品的名字或者工具箱的名字,如MATLAB或者Control。MATLAB支持使用多層次的類別名稱。
詳細信息用于指定消息的具體內容,如除數(shù)為0等。
以下例子為一個完整的標志符:
error('MATLAB:ambiguousSyntax','Syntax%scouldbeambiguous.\n',inputstr)。
2)消息標志符的應用
消息標志符通常與lasterror()函數(shù)一起應用,使得lasterror()函數(shù)和lasterr()函數(shù)能夠識別錯誤的原因。lasterror()函數(shù)和lasterr()函數(shù)返回消息標志符,用戶可以通過其類別信息和詳細信息分別獲取錯誤的總體類別及具體信息。
使用消息標志符的第一步為確定目的信息并為其指定標志符。消息標志符通過error()函數(shù)指定,格式如下:
error('msg_id','errormsg')
error('msg_id','formatted_errormsg',arg1,arg2,...)
其中的消息標志符可以省略。如果lasterror()函數(shù)不使用該信息,上面的語句可以簡寫為
error('errormsg')
3.錯誤處理
對于執(zhí)行出現(xiàn)的錯誤,可以根據(jù)提示的錯誤類型,有針對性地改正,然后繼續(xù)編譯、運行。如果程序較大,可以像C語言一樣設置斷點、單步執(zhí)行等。MATALB提供了一系列程序斷點的設置函數(shù),如表4-3所示。
4.警告處理
警告用于提示用戶在程序運行中出現(xiàn)異常情況。與錯誤不同的是,警告并不中斷程序的運行,而是顯示警告內容并繼續(xù)執(zhí)行。警告通過函數(shù)warning()發(fā)出,格式與error()函數(shù)相同,如:
warning('Inputmustbeastring')
warning('formatted_warningmsg',arg1,arg2,...)
warning('Ambiguousparametername,"%s".',param)
另外,與錯誤相同,警告也可以使用消息標志符,用以顯示該警告信息的類別及具體信息。
5.函數(shù)M文件中的錯誤處理
函數(shù)M文件中的一般錯誤處理與腳本文件一樣,但對于函數(shù)M文件中出現(xiàn)的簡單問題,使用下面的一種或幾種方法可以方便求解。
(1)將函數(shù)中輸出關鍵值的行的分號(;)去掉,這樣,這些運算的中間結果將在命令窗口中予以顯示,用戶可以據(jù)此來檢查中間結果的正確性。
(2)在函數(shù)中添加一些語句,用來顯示用戶認為很重要的變量的值。
(3)使用keyboard命令中斷程序,該命令實現(xiàn)函數(shù)工作區(qū)間和命令窗口工作區(qū)間的交互,從而獲得用戶所需要的信息,使用該命令后,程序將處于調試狀態(tài),此時命令窗口的提示符由“>>”變?yōu)椤癒>>”,用戶可以進行相應的操作。
(4)在函數(shù)頭前加“%”就將函數(shù)式M文件變?yōu)槟_本式M文件,而腳本式M文件運行時,其工作區(qū)間就是MATLAB的工作區(qū)間,這樣在出現(xiàn)錯誤的時候就可以查詢這個工作區(qū)間。
當M文件大,遞歸調用或者多次嵌套(即調用其他M文件函數(shù),被調用M文件函數(shù)又調用其他M文件函數(shù),等等)時,用MATLAB的調試函數(shù)會更方便。與上述所列方法相反,這些調試函數(shù)不要求將有問題的M文件進行編輯。表3-6所給出的這些函數(shù)類似于其他高級編程語言中所提供的函數(shù)。4.1.5程序的分析與優(yōu)化
在MATLAB中,使用profile()函數(shù)以及計時函數(shù)tic()和toc()來分析程序中各個部分的耗時情況,從而幫助用戶找出程序中需要改進的地方。其中profile()在計算相對耗時以及查找文件執(zhí)行過程中瓶頸問題時更為有效,而tic()和toc()函數(shù)在計算絕對耗時時更為有效。
1.通過tic()、toc()函數(shù)進行程序運行分析
如果只需要了解程序的運行時間,或者比較一段程序在不同應用條件下的運行速度,可以通過計時器來進行。計時器包含tic()和toc()兩個函數(shù)。tic()用于開始計時器,toc()用于關閉計時器,并計算程序運行的總時間。如:
tic
所需計時的程序代碼--
toc
對于小程序,如果其運行時間非常短,可以通過將其多次運行,計算總體時間的方法進行,如:
tic
fork=1:100
所需計時的程序代碼--
end
toc因為MATLAB是一種解釋性語言,所以有時程序的執(zhí)行速度不是很理想。一個目的的實現(xiàn),往往可以有多種程序結構或算法,或使用不同的函數(shù)。而不同的方法,其速度是千差萬別的,例如求解定積分的數(shù)值解法在MATLAB中就提供了quad()和quadl()兩個函數(shù),其中后一個算法在精度、速度上都明顯高于前一種方法。所以說,在科學計算領域是存在“多快好省”的途徑的。因此可以通過程序的優(yōu)化,使編程、運行效率提高。
2.循環(huán)運算的優(yōu)化
循環(huán)運算是MATLAB中的最大弱點。在程序設計中,循環(huán)語句及循環(huán)體經常被認為是MATLAB編程的瓶頸問題,應當盡量避免使用循環(huán)運算。如果必須使用循環(huán)運算,可通過以下兩種方法進行改進,以提高其效率。
(1)程序的向量化操作,使循環(huán)向量化:當使用for循環(huán)和while循環(huán)來增加數(shù)據(jù)結構的大小時,將影響系統(tǒng)和內存的使用。提高效率的可行辦法是進行預定義。
用戶可以通過將M文件向量化來優(yōu)化M文件。所謂向量化,就是使用向量和矩陣運算來代替For循環(huán)和While循環(huán)。采取向量化的方法比常規(guī)循環(huán)運算效率可提高一倍多。
(2)在必須使用多重循環(huán)的情況下,如果兩個循環(huán)執(zhí)行的次數(shù)不同,則建議在循環(huán)的外環(huán)執(zhí)行循環(huán)次數(shù)少的,內環(huán)執(zhí)行循環(huán)次數(shù)多的,這樣也可以顯著提高速度。
3.大型矩陣(數(shù)組)預先定維、預分配內存
雖然矩陣的尺寸不必預先定義,但給大型矩陣動態(tài)定維是個很耗費時間的事。如果在定義大矩陣時,首先用MATLAB函數(shù),如zeros()或ones()對之預先進行定維、預分配內存,然后再進行賦值處理,這樣會顯著減少所需的時間,大大提高效率。
4.優(yōu)化程序結構
優(yōu)化程序結構需要考慮以下因素:
(1)優(yōu)先考慮內在函數(shù)。由于MATLAB的內在函數(shù)是由更底層的C語言編程構造的,其執(zhí)行速度顯然快于使用循環(huán)的矩陣運算,因此矩陣運算應該盡量采用MATLAB的內在函數(shù)。
(2)采用有效的算法。在實際應用中,解決同樣的數(shù)學問題經常有各種各樣的算法。如果一個方法不能滿足要求,可以嘗試其他的方法。
(3)避免在運行MATLAB時運行其他大型后臺程序。
(4)對向量賦值時盡量避免改變變量的類型或數(shù)組大小。
(5)盡量對實數(shù)進行操作,避免復數(shù)的操作。
(6)合理使用邏輯運算符。
(7)避免重載MATLAB的內置函數(shù)和操作符。
(8)通常情況下,函數(shù)的運行效率高于腳本文件。
(9)?load()和save()函數(shù)效率高于文件輸入/輸出函數(shù)。
5.應用Mex技術
應用Mex技術,以Mex文件的格式編寫循環(huán)語句。在一個大型的MATLAB程序中,雖然采用了很多措施,但執(zhí)行速度仍然很慢,比如說耗時的循環(huán)是不可避免的,這樣就應該考慮用其他語言,如C或Fortran語言。按照Mex技術要求的格式編寫相應部分的程序,然后通過編譯連接,形成在MATLAB可以直接調用的動態(tài)連接庫(DLL)文件,這樣可以顯著地加快運算速度。 4.2M函數(shù)
函數(shù)是MATLAB強有力的工具,在求解一些大的問題時,會經常使用到一些已經定義的數(shù)學函數(shù)、系統(tǒng)函數(shù)、其他函數(shù)或有用的命令序列等。MATLAB中提供了兩種函數(shù)表示的方法:
利用M文件將函數(shù)定義為MALTAB函數(shù)。MATLAB提供了一個創(chuàng)建用戶自定義函數(shù)的結構,并以M文件的文本形式存儲在計算機上。
匿名函數(shù)方法。通過符號“@”直接創(chuàng)建函數(shù)。4.2.1函數(shù)M文件
函數(shù)M文件與腳本文件M文件在通信方面是不同的。函數(shù)是一個黑箱,使用函數(shù)時,可以看見的就是輸入數(shù)據(jù)和輸出數(shù)據(jù)。函數(shù)與MATLAB工作空間之間的通信,只通過傳遞給它的變量和通過它所創(chuàng)建的輸出變量。在函數(shù)內中間變量不出現(xiàn)在MATLAB工作空間,或與MATLAB工作空間不交互。
MATLAB頭一次執(zhí)行一個函數(shù)M文件時,它打開相應的文本文件并將命令編輯成存儲器的內部表示,以加速執(zhí)行在以后所有的調用。如果函數(shù)包含了對其他函數(shù)M文件的引用,它們也同樣被編譯到存儲器。而普通的腳本M文件不被編譯,即使它們是從函數(shù)M文件內調用,也是如此。打開腳本M文件,調用一次就逐行進行注釋。
函數(shù)M文件提供了一個簡單的擴展MATLAB功能的方法。事實上,MATLAB本身的許多標準函數(shù)就是函數(shù)M文件。4.2.2函數(shù)M文件的結構、規(guī)則和屬性
一個函數(shù)M文件通常包含五個部分:函數(shù)定義語句、H1幫助行、幫助文本、函數(shù)體或者腳本文件語句和注釋語句。函數(shù)M文件必須遵循以下特定的規(guī)則。除此之外,它們還有許多的重要屬性。
1.函數(shù)定義
函數(shù)定義必須遵循以下特定的規(guī)則:
(1)一個函數(shù)M文件的第一行使用function把M文件定義為一個函數(shù),并指定它的名字。
(2)函數(shù)名和文件名必須相同,但沒有?.m擴展名。例如,函數(shù)fliplr()存儲在名為fliplr.m文件中。它也定義了它的輸入和輸出變量。
2.輸入、輸出參量
函數(shù)可以有零個或更多個輸入參量,也可以有零個或更多個輸出參量。
函數(shù)可以按少于函數(shù)M文件中所規(guī)定的輸入和輸出變量進行調用,但不能用多于函數(shù)M文件中所規(guī)定的輸入和輸出變量數(shù)目。如果輸入和輸出變量數(shù)目多于函數(shù)M文件中function語句一開始所規(guī)定的數(shù)目,則調用時自動返回一個錯誤。
當函數(shù)有一個以上輸出變量時,輸出變量包含在括號內。
例如:[V,D]=eig(A)。
3.幫助行
正文的第一行是幫助行,稱為H1行,H1行是緊隨函數(shù)定義語句后面的一行注釋語句,是由lookfor命令所搜索的行,lookfor()函數(shù)只檢索和顯示H1行。
H1行后面連續(xù)的注釋行是幫助文本,當在命令窗口中通過help命令查詢該函數(shù)的說明信息時,則在窗口中顯示這些內容。
M文件的其余部分包含了MATLAB創(chuàng)建輸出變量的命令。
4.函數(shù)體
函數(shù)體為M文件的主要部分,是函數(shù)的執(zhí)行代碼。
除上面的H1行和幫助文本外,為了易于理解,可以在書寫代碼時添加注釋語句。這些注釋語句在編譯程序時會被忽略,因此不會影響編譯速度和程序運行速度,但是能夠增加程序的可讀性。
5.函數(shù)的工作空間
(1)函數(shù)有它們自己的專用工作空間,與MATLAB的工作空間是分開的。函數(shù)內變量與MATLAB工作空間之間唯一的聯(lián)系是函數(shù)的輸入和輸出變量。如果函數(shù)任一輸入變量值發(fā)生變化,其變化僅在函數(shù)內出現(xiàn),不影響MATLAB工作空間的變量。函數(shù)內所創(chuàng)建的變量只駐留在函數(shù)的工作空間,而且只在函數(shù)執(zhí)行期間臨時存在,以后就消失。因此,從一個調用到下一個調用,在函數(shù)工作空間變量存儲信息是不可能的。
(2)如果一個預定的變量(如pi)在MATLAB工作空間被重新定義,它不會延伸到函數(shù)的工作空間。逆向有同樣的屬性,即函數(shù)內的重新定義變量不會延伸到MATLAB的工作空間中。
(3)當調用一個函數(shù)時,輸入變量不會拷貝到函數(shù)的工作空間,但它們的值在函數(shù)內可讀。然而,只要改變輸入變量內的任何值,數(shù)組就可拷貝到函數(shù)工作空間。進而,按缺省,如果輸出變量與輸入變量相同,例如,如果函數(shù)是x=fun(x,y,z)中的x,那么就將它拷貝到函數(shù)的工作空間。因此,為了節(jié)約存儲和增加速度,最好是從大數(shù)組中抽取元素,然后對它們作修正,而不是使整個數(shù)組拷貝到函數(shù)的工作空間。4.2.3函數(shù)變量
MATLAB的變量有輸入變量、輸出變量和函數(shù)內使用的變量之分,還可分為局部變量、全局變量、永久變量。
輸入變量相當于函數(shù)的入口數(shù)據(jù),也是一個函數(shù)操作的主要對象,從某種意義上來說,函數(shù)的功能就是對輸入變量進行一定的操作,從而實現(xiàn)一定的功能。函數(shù)的輸入變量為局部變量,函數(shù)對輸入變量的一切操作和修改如果不依靠輸出變量的話,將不會影響工作區(qū)間中該變量的值。
1.局部變量
在M函數(shù)文件中,所有變量默認為局部變量。因此,在一個函數(shù)文件中的變量與MATLAB工作區(qū)中的同名變量是完全不同的變量,它們存在內存的不同位置。
每個函數(shù)都有自己的局部變量,這些變量存儲在該函數(shù)獨立的工作區(qū)中,與其他函數(shù)的變量及主工作區(qū)中的變量分開存儲。當函數(shù)調用結束時,這些變量隨之刪除,不保存在內存中。并且,除了函數(shù)返回值,該函數(shù)不改變工作區(qū)中其他變量的值。
腳本文件沒有獨立的工作區(qū),當通過命令窗口調用腳本文件時,腳本文件分享主工作區(qū),當函數(shù)調用腳本文件時,腳本文件分享主調函數(shù)的工作區(qū)。需要注意的是,如果腳本中改變了工作區(qū)中變量的值,則在腳本文件調用結束后,該變量的值發(fā)生改變。局部變量是在函數(shù)內部使用的變量,其影響范圍只能在本函數(shù)內,每個函數(shù)在運行時,都占有獨立的函數(shù)工作空間,此工作空間和MATLAB的工作空間是相互獨立的,局部變量僅存在于函數(shù)的工作空間內。當函數(shù)執(zhí)行完畢之后,該變量即自行消失。
2.全局變量
在MATLAB中,函數(shù)內部定義的變量都是局部變量,它們不被加載到工作區(qū)間中。有時,用戶需要使用全局變量,這時要使用global()函數(shù)來進行定義。
局部變量只在一個工作區(qū)內有效,無論是函數(shù)工作區(qū)還是MATLAB主工作區(qū)。與局部變量不同,全局變量可以在定義該變量的全部工作區(qū)中有效。當在一個工作區(qū)內改變該變量的值時,該變量在其他工作區(qū)中的變量同時改變。
任何函數(shù)要使用全局變量,必須首先聲明,即使是在命令窗口也不例外。如果一個M文件中包含的子函數(shù)需要訪問全局變量,則需在子函數(shù)中聲明該變量,如果需要在命令行中訪問該變量,則需在命令行中聲明該變量。聲明格式:
global變量名1變量名2
3.永久變量
除局部變量和全局變量外,MATLAB中還有一種變量類型為永久變量。除了通過全局變量共享數(shù)據(jù)外,函數(shù)式M文件還可以通過persistent聲明一個變量,來對函數(shù)中重復使用和遞歸調用的變量的訪問進行限制,該變量就是永久變量。
(1)永久變量的特點如下:
①永久變量與全局變量類似,但是只能在M文件內部定義,它的范圍被限制在聲明這些變量的函數(shù)內部,不允許在其他的函數(shù)中對它們進行改變。
②只有該變量從屬的函數(shù)能夠訪問該變量。
③當函數(shù)運行結束時,該變量的值保留在內存中。只要M文件還在MATLAB的內存中,永久變量就存在。因此當該函數(shù)再次被調用時,可以再次利用這些變量。
(2)永久變量的定義方法:
persistent變量名1變量名2
使用格式形如persistent(XYZ)。4.2.4函數(shù)的分類
函數(shù)可分為以下幾類:主函數(shù)、子函數(shù)、匿名函數(shù)、嵌套式函數(shù)、局部函數(shù)(私有函數(shù))及重載函數(shù)。
1.主函數(shù)
通常在M文件中的第一次調用的函數(shù)就叫主函數(shù),主函數(shù)中可以包含任意數(shù)量的子函數(shù),它們可以作為主程序的子程序。主函數(shù)可以被該文件之外的其他函數(shù)調用,而子函數(shù)只能被該文件內的函數(shù)調用。一般來說,在命令窗口或是其他的M文件只能調用主函數(shù),主函數(shù)的調用就是直接調用存儲該函數(shù)的M文件的文件名。
2.子函數(shù)
一個M文件中可以包括多個函數(shù),除主函數(shù)之外的其他函數(shù)稱為子函數(shù)。子函數(shù)只能被主函數(shù)或該文件內的其他子函數(shù)調用。每個子函數(shù)以函數(shù)定義語句開頭,直至下一個函數(shù)的定義或文件的結尾。
當函數(shù)中調用函數(shù)時,系統(tǒng)判斷其函數(shù)類型的順序為:首先判斷是否為子函數(shù),然后判斷是否為私有函數(shù),最后判斷其是否為當前目錄下的M文件函數(shù)或者系統(tǒng)內置函數(shù)。由于子函數(shù)具有最高的優(yōu)先級別,因此在定義子函數(shù)時,可以采用已有的其他外部函數(shù)的名稱。
3.局部函數(shù)
MATLAB中把放置在“private”目錄下的函數(shù)稱為局部函數(shù)(私有函數(shù)),局部函數(shù)是MATLAB中的另一類函數(shù),這些函數(shù)只有private目錄的父目錄中的函數(shù)才可以調用,其他目錄下的函數(shù)不能調用。
例如,當前文件夾為matlabmath,matlabmath中包含子文件夾private,則private中的函數(shù)只能被matlabmath根目錄下的函數(shù)及這些函數(shù)調用的M文件調用。私有函數(shù)只能被其父文件夾中的函數(shù)調用,因此,用戶可以開發(fā)自己的函數(shù)庫,函數(shù)的名稱可以與系統(tǒng)標準M函數(shù)庫名稱相同,而不必擔心在函數(shù)調用時發(fā)生沖突,因為MATLAB首先查找私有函數(shù),再查找標準函數(shù)。
局部函數(shù)與子函數(shù)所不同的是,局部函數(shù)可以被其父目錄下的所有函數(shù)所調用,而子函數(shù)則只能被其所在的M文件的主函數(shù)所調用。所以,局部函數(shù)在可用的范圍上大于子函數(shù);在函數(shù)編輯的結構上,局部函數(shù)與一般的函數(shù)文件的編輯相同,而子函數(shù)只能在主函數(shù)文件中編輯。
4.嵌套式函數(shù)
在MATLAB中,一個函數(shù)內部可以定義一個或多個其他的函數(shù),這種在內部定義的函數(shù)稱做嵌套式函數(shù)。在嵌套式函數(shù)的內部也可以定義嵌套式函數(shù)。
需要注意的是,當一個M文件中存在嵌套函數(shù)時,該文件內的所有函數(shù)無論是主函數(shù)還是嵌套函數(shù)都必須以end結尾。
1)嵌套函數(shù)的書寫
定義嵌套函數(shù)時,只要在一個函數(shù)內部直接定義嵌套函數(shù)即可。
每個函數(shù)中可以平行嵌套多個函數(shù)。
嵌套函數(shù)還可以包含多層嵌套函數(shù)。例4-2-1嵌套函數(shù)的結構。
解程序如下:
functionx=A(p1,p2)
...
functiony=B(p3)
...
end
...
end
2)嵌套函數(shù)的調用
一個嵌套函數(shù)可以被下列函數(shù)調用:
該嵌套函數(shù)的上一層函數(shù)。
同一母函數(shù)下的同級嵌套函數(shù)。
被任一低級別的函數(shù)調用。
5.重載函數(shù)
重載函數(shù)是為已經存在的函數(shù)創(chuàng)建的一種附加應用,這些已經存在的函數(shù)被設計成專門執(zhí)行某種類的句柄,當調用函數(shù)傳遞參數(shù)時,MATLAB搜尋函數(shù)句柄執(zhí)行函數(shù)代碼。
每個重載的MATLAB函數(shù)都有一個類文件在MATLAB路徑下,類保存在以@打頭、類名命名的子文件夾中:@類名。例如,若用戶想使plot()函數(shù)的表達方法滿足自己的需要,則需要重載MATLAB的plot()函數(shù)。為此,若需要生成一個類(例如:polynom),則需建立一個子文件夾@polynom,并在該文件夾中保存類polynom和自己的文件plot.m,然后重載polynom類指定的plot()函數(shù)。
函數(shù)重載為程序編寫和用戶調用都提供了很大的方便。函數(shù)重載允許多個函數(shù)使用相同的函數(shù)名、不同的輸入參數(shù)類型。在函數(shù)調用時,系統(tǒng)根據(jù)輸入參數(shù)的情況自動選擇相應的函數(shù)執(zhí)行。4.2.5內聯(lián)函數(shù)與匿名函數(shù)
內聯(lián)函數(shù)是用戶用來自定義函數(shù)的一種形式,一般用于定義一些比較簡單的數(shù)學函數(shù)。用命令inline來定義,因此叫內聯(lián)函數(shù)。
1.內聯(lián)函數(shù)
使用inline()函數(shù)可以構建一個內聯(lián)對象。調用方法如下:
(1)fun=inline(expr):使用MATLAB字符串表達式expr構建一個內聯(lián)函數(shù)對象。內聯(lián)函數(shù)的輸入參數(shù)是通過搜索expr,找到一個除i、j以外的孤立小寫字母來自動確定的。如果沒有找到這樣的字符,就用x,如果字符x不是唯一的,就使用最靠近的x。如果找到了兩個字符,則選擇在字母表中靠后面的一個字符。
(2)?fun=inline(expr,arg1,arg2,...):使用表達式expr構建一個內聯(lián)函數(shù)對象。輸入參數(shù)由串“arg1,arg2,....”指定。
例如:f(x,y)=sin(x2+y2)可寫成f=inline('sin(x.^2+y.^2)','x','y')。
(3)?fun=inline(expr,n):n是一個標量,輸入參數(shù)是“x,P1,P2,...”。
MATLAB7.x后的版本中推薦用戶使用匿名函數(shù)取代內聯(lián)函數(shù),匿名函數(shù)可以實現(xiàn)內聯(lián)函數(shù)的幾乎全部功能,而速度和方便性卻比后者高很多。
2.匿名函數(shù)
匿名函數(shù)提供了一種創(chuàng)建簡單程序的方法,使用它的用戶可以不必每次都編寫M文件。用戶可以在MATLAB的命令窗口或是其他任意M文件和腳本文件中使用匿名函數(shù)。
匿名函數(shù)的格式如下:
fhandle=@(arglist)expr
其中,fhandle是為該函數(shù)創(chuàng)建的函數(shù)句柄;@符號用于創(chuàng)建函數(shù)句柄;arglist為用逗號分隔的參數(shù)列表;expr為函數(shù)主體,是MATLAB表達式。
例如,f(x,y)=sin(x2+y2)可寫成f=(x,y)@sin(x.^2+y.^2)??捎媚涿瘮?shù)直接創(chuàng)建函數(shù),例如:
>>fh=@(x)1./((x-0.3).^2+0.01)+1./((x-0.9).^2+0.04)-6;
例4-2-2
有一個自定義函數(shù)myfun.m,具體如下:
functiony=myfun(x)
y=1./(x.^3-2*x-5);
解運行下列命令可用匿名函數(shù)求出積分結果:
>>Q=quad(@myfun,0,2)
Q=-0.4605
也可以直接運行匿名函數(shù)求出積分結果:
>>F=@(x)1./(x.^3-2*x-5);
>>Q=quad(F,0,2)
Q=-0.4605
4.3函數(shù)的調用與函數(shù)句柄
4.3.1函數(shù)參數(shù)與函數(shù)的調用
當調用函數(shù)時,主調函數(shù)通過函數(shù)參數(shù)的形式向被調函數(shù)傳遞數(shù)據(jù),被調函數(shù)通過函數(shù)返回值的形式向主調函數(shù)返回數(shù)據(jù)。當調用一個函數(shù)時,需遵循下列規(guī)則。
1.輸入和輸出參量的數(shù)目
(1)當調用一個函數(shù)時,所用的輸入和輸出參量的數(shù)目,在其內部是定義好了的。函數(shù)工作空間變量nargin包含輸入參量個數(shù);函數(shù)工作空間變量nargout包含輸出參量個數(shù)。事實上,這些變量常用來設置缺省輸入變量,并決定用戶所希望的輸出變量。例如,MATLAB的函數(shù)linspace():
functiony=linspace(d1,d2,n)
%LINSPACELinearlyspacedvector.
%LINSPACE(X1,X2)generatesarowvectorof100linearly
%equallyspacedpointsbetweenX1andX2.
%
%LINSPACE(X1,X2,N)generatesNpointsbetweenX1andX2.
%ForN<2,LINSPACEreturnsX2.
%
%SeealsoLOGSPACE,
%Copyright1984-2002TheMathWorks,Inc.
%$Revision:5.12$$Date:2002/02/0513:47:28$
ifnargin==2
n=100;
end
y=[d1+(0:n-2)*(d2-d1)/(floor(n)-1)d2];
這里,如果用戶只用兩個輸入參量調用linspace(),例如linspace(0,10),表示linspace產生100個數(shù)據(jù)點。相反,如果輸入參量的個數(shù)是3,例如,linspace(0,10,50),那么第三個參量決定數(shù)據(jù)點的個數(shù)。
(2)可用一個或兩個輸出參量調用函數(shù)。例如函數(shù)size(),盡管這個函數(shù)不是一個函數(shù)M文件,而是一個內置函數(shù)。size()函數(shù)的幫助文本說明了它的輸出參量的選擇。
IZE
Matrixdimensions.
D=SIZE(X),forM-by-NmatrixX,returnsthetwo-element
rowvectorD=[M,N]
%containingthenumberofrowsandcolumns
inthematrix.
[M,N]=SIZE(X)%returnsthenumberofrowsandcolumns
inseparateoutputvariables.
(3)如果函數(shù)僅用一個輸出參量調用,就返回一個二元素的行,它包含行數(shù)和列數(shù)。相反,如果出現(xiàn)兩個輸出參量,size分別返回行和列。在函數(shù)M文件里,變量nargout可用來檢驗輸出參量的個數(shù),并按要求修正輸出變量的創(chuàng)建。
(4)當一個函數(shù)說明一個或多個輸出變量,但沒有要求輸出時,就簡單地不給輸出變量賦任何值。MATLAB的函數(shù)toc()闡明了這個屬性。
functiont=toc
%
TOC
Readthestopwatchtimer.
%
TOC,byitself,printstheelapsedtimesinceTICwasused.
%
t=TOC;savestheelapsedtimeint,insteadofprintingitout.
%
%
SeealsoTIC,ETIME,CLOCK,CPUTIME.
%
Copyright(c)1984-94byTheMathWorks,Inc.
%
TOCusesETIMEandthevalueofCLOCKsavedbyTIC.
globalTICTOC
ifnargout<1
elapsed_time=etime(clock,TICTOC)
else
t=etime(clock,TICTOC);
end如果用戶用不以輸出參量調用toc(),例如,>>toc,那么就不指定輸出變量t的值,函數(shù)在命令窗口顯示函數(shù)工作空間變量elapsed_time,但在MATLAB工作空間里不創(chuàng)建變量。相反,如果toc是以>>out=toc調用,則按變量out將消逝的時間返回到命令窗口。
(5)當一個函數(shù)的輸入參量的個數(shù)超出了規(guī)定的范圍,MATLAB的nargchk()函數(shù)提供了統(tǒng)一的響應。函數(shù)nargchk()可定義為
function
msg=nargchk(low,high,number)
%
NARGCHK
Checknumberofinputarguments.
%
Returnerrormessageifnotbetweenlowandhigh.
%
Ifitis,returnemptymatrix.
%
Copyright(c)1984-94byTheMathWorks,Inc.
msg=[
];
if(number<low)
msg='Notenoughinputarguments.';
elseif(number
>
high)
msg='Toomanyinputarguments.';
end下列的文件片段表明了在一個函數(shù)M文件內的典型用法,即
error(nargchk(nargin,2,5))
如上所述,如果nargin的值小于2,函數(shù)error()能像前面描述的那樣進行處理,nargchk()返回字符串?'沒有足夠的輸入參量。'。如果nargin的值大于5,函數(shù)error()執(zhí)行處理,nargchk()返回字符串?'太多輸入參量。'。如果nargin是在2和5之間,函數(shù)error()簡單地將控制傳遞給下一個語句,nargchk()返回一個空字符串。也就是說,當nargin的輸入參量為空時,error()函數(shù)什么也不做。
2.確定的函數(shù)參數(shù)數(shù)目
在MATLAB中,輸入/輸出參數(shù)是以單元數(shù)組的形式進行傳輸?shù)模狠斎雲?shù)以單元數(shù)組的形式傳遞給函數(shù),單元數(shù)組的每個元素為相應的參數(shù)。同樣,輸出參數(shù)也是以單元數(shù)組的形式組織的。如此的參數(shù)組織形式便于函數(shù)接受任意數(shù)目的參數(shù)。
MATLAB可以有任意數(shù)量的輸入和輸出變量,這些輸入和輸出參數(shù)的特性和規(guī)則
如下:
函數(shù)式M文件可以沒有輸入和輸出變量。
函數(shù)可以用比M文件中的函數(shù)定義行所規(guī)定的輸入/輸出變量更少的變量進行調用,但是調用變量不能比規(guī)定的輸入/輸出變量多。
在一次調用中所用到的輸入和輸出變量的個數(shù)可以通過分別調用函數(shù)nargin()和nargout()來確定。
函數(shù)nargin()和nargout()分別用于確定函數(shù)的輸入、輸出參數(shù)個數(shù)。在函數(shù)體內部用nargin(nargout)?確定用戶提供的輸入(輸出)參數(shù)個數(shù)。在函數(shù)體外部用nargin(nargout)?確定一個給定的函數(shù)的輸入(輸出)參數(shù)個數(shù),如果函數(shù)的參數(shù)的數(shù)目是可變的,則返回一個負值。語法如下:
(1)?nargin()、nargout():返回指定的輸入、輸出參數(shù)個數(shù)。
(2)?nargin(fun)、nargout(fun):返回由函數(shù)fun確定的輸入、輸出參數(shù)個數(shù)。fun可以是函數(shù)名或函數(shù)句柄名。如果函數(shù)的輸入、輸出參數(shù)的數(shù)目是可變的,則nargin()、nargout()返回一個負值。在函數(shù)體內部用nargin(nargout)?確定了輸入/輸出參數(shù)后,可以用條件語句確定需要執(zhí)行的操作。
在調用該函數(shù)時可以輸入任意數(shù)目的參數(shù),參數(shù)可以為二元數(shù)組或者表示線型的字符串,該函數(shù)將用指定的線型繪制輸入數(shù)據(jù)的圖像。指定線型的字符串可以在任意位置輸入,并且可以輸入多個。但需要注意的是,只有最后一個字符串起作用。
在上面的程序中,將所有輸入參數(shù)作為一個單元數(shù)組,利用花括號和圓括號對數(shù)組元素進行訪問,實現(xiàn)輸入參數(shù)的調用。例4-3-1
顯示一個函數(shù)myplot()的接口代碼,它接受一個數(shù)目可選的輸入和輸出參數(shù)。
function[x0,y0]=myplot(x,y,npts,angle,subdiv)
%MYPLOTPlotafunction.
%MYPLOT(x,y,npts,angle,subdiv)
%Thefirsttwoinputargumentsare
%required;theotherthreehavedefaultvalues.
...
ifnargin<5,subdiv=20;end
ifnargin<4,angle=10;end
ifnargin<3,npts=25;end
...
ifnargout==0
plot(x,y)
else
x0=x;
y0=y;
end注意:由于nargin()和nargout()是函數(shù)而不是變量,因此用戶不能用諸如nargin=nargin+
pi之類的語句對它們進行重新賦值。
nargin()和nargout()是函數(shù),當在函數(shù)中調用這兩個函數(shù)時,其值為該函數(shù)的輸入或輸出參數(shù),而不需要進行聲明。如上面的例子中,在函數(shù)A中調用nargin(B(nargin,y*rand(4)))表示函數(shù)A的輸入參數(shù)個數(shù),在函數(shù)C中調用nargin表示函數(shù)C的輸入參數(shù)個數(shù)。
3.參數(shù)數(shù)目可變的函數(shù)
函數(shù)nargin()和函數(shù)nargout()允許函數(shù)接收或返回任意數(shù)目的參數(shù)。在嵌套函數(shù)中也可以使用可變參數(shù)。但需要注意的是,varargin、varargout和nargin、nargout的意義可能有所不同。
varargin和varargout為變量,與MATLAB其他變量的作用范圍相同。由于嵌套函數(shù)與主函數(shù)使用相同的工作區(qū),因此varargin和varargout既可以表示嵌套函數(shù)的輸入輸出參數(shù),也可以是主函數(shù)的輸入/輸出函數(shù),具體值取決于程序中的變量聲明:
如果嵌套函數(shù)在函數(shù)聲明中包含varargin或者varargout,則在該函數(shù)內部調用這兩個變量時,變量內容為該函數(shù)的輸入輸出參數(shù);
如果嵌套函數(shù)聲明中沒有包含varargin或者varargout,而在該函數(shù)的上層函數(shù)聲明中包含varargin或者varargout,則當在該嵌套函數(shù)內部調用這兩個變量時,變量內容為上層函數(shù)的輸入輸出參數(shù)。
(1)?varargin:代表一個可變長度的輸入列表。語法如下:
functiony=bar(varargin)
接受一個可變數(shù)量的參數(shù)到函數(shù)bar.m.。
該varargin語句僅用于函數(shù)內部包含可選的輸入參數(shù)傳遞給函數(shù)。該varargin參數(shù)必須被聲明為函數(shù)的最后一個輸入參數(shù),所有的輸入參數(shù)都從該點開始。在聲明中,varargin必須小寫。
例4-3-2
編寫一個函數(shù),顯示所需要的和可選的參數(shù),并將其傳遞給該函數(shù)。
解程序如下:
functionvartest(argA,argB,varargin)
optargin=size(varargin,2);
stdargin=nargin-optargin;
fprintf('Numberofinputs=%d\n',nargin)
fprintf('Inputsfromindividualarguments(%d):\n',...
stdargin)
ifstdargin>=1
fprintf('%d\n',argA)
end
ifstdargin==2
fprintf('%d\n',argB)
end
fprintf('Inputspackagedinvarargin(%d):\n',optargin)
fork=1:size(varargin,2)
fprintf('%d\n',varargin{k})
end在MATLAB命令窗口調用該函數(shù),可觀察到提取出從varargin單元數(shù)組指定的參數(shù)。
>>vartest(10,20,30,40,50,60,70)
Numberofinputs=7
Inputsfromindividualarguments(2):
10
20
Inputspackagedinvarargin(5):
30
40
50
60
70例4-3-3
編寫以下函數(shù)。
解程序如下:
functionmyplot(x,varargin)
plot(x,varargin{:})
在MATLAB命令窗口調用該函數(shù),所有的輸入都從第二個輸入變量varargin開始,myplot使用逗號分隔列表的語法varargin{:}傳送可選的參數(shù)來繪制圖形。
>>myplot(sin(0:.01:10),'color',[.5.7.3],'linestyle','.')
varargin結果是一個1?×?4元素的單元數(shù)組,包含?'color'、[.5
.7
.3]、'linestyle'?和?'.'。繪制出的正弦曲線圖形如圖4-3所示。圖4-3繪制出的正弦曲線圖形
(2)?varargout:代表一個可變長度的輸出列表。語法如下:
functionvarargout=foo(n)
從函數(shù)foo.m.返回一個可變數(shù)量的參數(shù)表。varargout僅用于函數(shù)內部包含可選的、由函數(shù)返回的輸出參數(shù)。varargout參數(shù)必須被聲明為函數(shù)的最后一個輸出參數(shù),所有輸出從該點開始,在聲明中,varargout必須小寫。
4.變量
(1)全局變量可以被其他函數(shù)或工作空間共享。如果所調用函數(shù)的變量被說明是全局性的,該函數(shù)可以被其他函數(shù)共享,還可以被MATLAB工作空間共享,并且可以遞歸調用全局變量本身。如果要說明該變量是全局的,在一個函數(shù)內部或在MATLAB工作空間中訪問一個變量,必須在函數(shù)內和每一個所希望訪問的工作空間中。
全局變量使用的例子可以在MATLAB函數(shù)tic和toc中看到,它們結合在一起共同工作。例如在一個“跑表”程序中,函數(shù)tic和toc代碼如下:
functiontic
%
TIC
Startastopwatchtimer.
%
Thesequenceofcommands
%
TIC
%
anystuff
%
TOC
%
printsthetimerequiredforthestuff.
%
%
SeealsoTOC,CLOCK,ETIME,CPUTIME.
%
Copyright(c)1984-94byTheMathWorks,Inc.
%
TICsimplystoresCLOCKinaglobalvariable.
globalTICTOC
TICTOC=clock;
functiont=toc
%
TOC
Readthestopwatchtimer.
%
TOC,byitself,printstheelapsedtimesinceTICwasused.
%
t=TOC;savestheelapsedtimeint,insteadofprintingitout.
%
%
SeealsoTIC,ETIME,CLOCK,CPUTIME.
%
Copyright(c)1984-94byTheMathWorks,Inc.
%
TOCusesETIMEandthevalueofCLOCKsavedbyTIC.
globalTICTOC
ifnargout<1
elapsed_time=etime(clock,TICTOC)
else
t=etime(clock,TICTOC);
end在函數(shù)tic()中,變量TICTOC說明為全局的,因此它的值由調用函數(shù)clock()來設定。以后在函數(shù)toc()中,變量TICTOC也說明為全局的,讓toc()訪問存儲在TICTOC中的值。利用這個值,toc()計算自執(zhí)行函數(shù)tic()以來消失的時間。值得注意的是,變量TICTOC存在于tic()和toc()的工作空間,而不在MATLAB的工作空間。
(2)實際編程中,無論什么時候應盡量避免使用全局變量。如果要使用全局變量,建議全局變量名要長,它應包含所有要使用該全局變量的函數(shù)名的大寫字母,并選擇以首次出現(xiàn)的M文件的名字開頭。例如上面的M函數(shù)文件tic()首次出現(xiàn),全局變量聲明為:globalTICTOC。如果遵循這些建議,則可把全局變量之間不必要的相互作用減至最小。例如,如果在另一函數(shù)或MATLAB工作空間說明TICTOC為全局的,那么它的值在該函數(shù)或MATLAB工作空間內可被改變,由于變量TICTOC只可以存在于tic()和toc()的工作空間,而不在MATLAB工作空間和其他函數(shù)中。TICTOC的值由于被其他函數(shù)或MATLAB工作空間改變,而使得函數(shù)toc()得到不同的、可能是無意義的結果。
5.調用腳本M文件
從函數(shù)M文件內可以調用腳本文件。在這種情況下,腳本文件查看函數(shù)工作空間,不查看MATLAB工作空間。從函數(shù)M文件內調用的腳本文件不必用調用函數(shù)編譯到內存。函數(shù)每調用一次,它們就被打開和解釋一次。因此,從函數(shù)M文件內調用腳本文件減慢了函數(shù)的執(zhí)行。
6.遞歸調用
函數(shù)可以遞歸調用,即函數(shù)M文件能調用它們本身。例如以下函數(shù)ichina():
functionichina(n)
%ichinaRecursiveFunctionCallExample
%Copyright(c)2010byLGL
ifnargin==0,n=20;end
ifn>1
disp('中國是一個歷史悠久的文明國家。')
ichina(n-1)
else
disp('我是中國人!')
end
調用這個函數(shù)產生以下結果:
>>ichina(3)
中國是一個歷史悠久的文明國家。
中國是一個歷史悠久的文明國家。
我是中國人!遞歸調用函數(shù)在許多應用場合是有用的。在編制要遞歸調用的函數(shù)時,必須確保會終止,否則MATLAB會陷入死循環(huán)。最后,在一個遞歸函數(shù)內,如果變量說明是全局的,則該全局變量對以后所有函數(shù)調用是可用的。在這個意義下,全局變量變成靜態(tài)的,并在函數(shù)調用之間不會消失。
7.函數(shù)終點
當函數(shù)M文件到達M文件終點,或者碰到返回命令return時,就結束執(zhí)行和返回。
return命令提供了一種結束一個函數(shù)的簡單方法,而不必到達文件的終點。
MATLAB的函數(shù)error()在命令窗口顯示一個字符串,放棄函數(shù)執(zhí)行,把控制權返回給鍵盤。這個函數(shù)對提示函數(shù)使用不當很有用,如在以下文件片段中:
iflength(val)>1
error('
VALmustbeascalar.
')
end
這里,如果變量val不是一個標量,error顯示消息字符串,則把控制權返回給命令窗口和鍵盤。4.3.2函數(shù)句柄
在很多情況下,用戶需要將一個函數(shù)的標識作為參數(shù)傳遞給另一個函數(shù),MATLAB支持用字符串代表函數(shù),例如sin代表正弦函數(shù),也可以使用內聯(lián)函數(shù)(inlinefunction)來傳遞。由于匿名函數(shù)的引入,因此使用函數(shù)句柄。
當需要調用MALTAB函數(shù)時,需要通過符號“@”獲取函數(shù)句柄,利用函數(shù)句柄實現(xiàn)對函數(shù)的操作。函數(shù)句柄提供了一種間接訪問函數(shù)的手段,使用函數(shù)句柄具有以下優(yōu)勢:
用戶可以很方便地調用其他函數(shù);
提供函數(shù)調用過程中的可靠性;
減少程序設計中的冗余;
同時可以在使用函數(shù)的過程中保存函數(shù)相關的信息,尤其是關于函數(shù)執(zhí)行的信息。
利用函數(shù)句柄可以實現(xiàn)對函數(shù)的間接操作,既可以通過將函數(shù)句柄傳遞給其他函數(shù)實現(xiàn)對函數(shù)的操作,也可以將函數(shù)句柄保存在變量中,留待以后調用操作。函數(shù)句柄是一個強有力的工具,當有一個函數(shù)句柄被創(chuàng)建時,它將記錄函數(shù)的詳細信息,因此當一個句柄調用該函數(shù)時,MATLAB立即執(zhí)行,不需要進行文件搜索。尤其是反復調用一個函數(shù)時,可以節(jié)省大量的搜索時間,提高執(zhí)行效率。
函數(shù)句柄的另一個重要特性是用來標識子函數(shù)、私有函數(shù)和嵌套函數(shù)。使這些“隱蔽”的函數(shù)“顯現(xiàn)”出來。
1.函數(shù)句柄的創(chuàng)建
函數(shù)句柄的創(chuàng)建比較簡單,是通過@符號創(chuàng)建的,其格式為
fhandle=@functionname。
其中,fhandle為所創(chuàng)建的函數(shù)句柄,functionname為所創(chuàng)建的函數(shù)。
例如:trigFun=@sin;
可以使用單元數(shù)組保存函數(shù)句柄,如trighandle={@sin,@cos,@tan};使用時只需引用該函數(shù)所在單元。
2.函數(shù)句柄的調用
通過函數(shù)句柄實現(xiàn)對函數(shù)的間接調用,其調用格式與直接調用函數(shù)的格式相同。
例如,在命令窗口中調用程序:
>>trigFun(pi/2)
ans=
1
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 幼兒園安保人員職責合同
- 大數(shù)據(jù)模板施工合同
- 公共交通電力施工合同樣本
- 旅游度假村建筑合同
- 漁業(yè)公司銷售總監(jiān)招聘協(xié)議
- 員工培訓合同范本設計模板
- 風力發(fā)電硅芯管鋪設協(xié)議
- 餐飲中心消防樓梯安裝協(xié)議
- 污水處理廠建設項目合同成本臺賬
- 控股股東表決權委托合同三篇
- 金融隨機分析2課后答案
- 大學美育知到章節(jié)答案智慧樹2023年延邊大學
- 數(shù)控銑床工作臺三維運動伺服進給系統(tǒng)設計-課程設計
- 全國碩士研究生入學統(tǒng)一考試《思想政治理論》試題答題卡模板
- 外貿函電-報盤及外貿函電模板大全
- 施工總平面布置圖及說明及施工現(xiàn)場平面布置圖
- 商鋪交接清單
- 攤鋪機使用說明rp953e-903e操作手冊
- 編寫童話故事三年級400字
- 呼吸科拍背排痰流程圖
- PEP英語四年級上冊Unit 4 My home 教學反思
評論
0/150
提交評論