Octave 中有許多用來輸出錯誤與警告訊息的函數,在使用者自行定義的函數中若是碰到異常的狀況,可以使用這裡介紹的函數來輸出錯誤或警告訊息。
由於 Octave 中大部份的函數都有使用這些錯誤與警告函數,因此了解這些函數的運作有助於使用者處理 Octave 所產生的錯誤與警告。
錯誤處理(Handling Errors)
錯誤(errors)是指程式發生無法繼續執行或繼續執行已經無意義的情況,例如呼叫函數時輸入的參數太少的情況,在這種情況下函數應該要輸出錯誤訊息,以通知使用者缺少的輸入參數。
產生錯誤(Raising Errors)
最常見的錯誤就是當函數的輸入參數不符合的情況,下面的函數 f()
會在沒有輸入參數的情況以 error()
函數產生錯誤:
function f (arg1) if (nargin == 0) error("not enough input arguments"); endif endfunction
當 error()
函數被呼叫後,會產生指定的錯誤訊息,並停止執行目前的程式,回到命令列,有就是說在 error() 函數之後的程式碼將不會被執行。
error (template, ...) error (id, template, ...)
error()
函數會依照指定的格式將錯誤訊息輸出至標準錯誤(stderr),其格式的指定方式與 printf()
函數相同,而在輸出時會自動在每一行的開頭加上 "error: "
。呼叫 error()
函數也會一並設置 Octave 內部的錯誤狀態,因此 Octave 會直接回到最上層的命令列,不會再執行任何的程式碼,這在取消執行函數或指令稿的時候很有用。
若 error()
函數所指定的錯誤訊息沒有以換行字元結尾,Octave 會自動輸出所有呼叫函數的 traceback,例如:
function f () g (); end function g () h (); end function h () nargin == 1 || error ("nargin != 1"); end
執行 f()
函數時所輸出的 traceback 訊息可以協助使用者很快的找出錯誤的發生點:
f()
輸出的 traceback 訊息為
error: nargin != 1 error: called from: error: h at line 1, column 27 error: g at line 1, column 15 error: f at line 1, column 15
若 error()
函數所指定的錯誤訊息是以換行字元結尾,則 Octave 只會輸出指定的錯誤訊息,不會輸出 traceback,例如將上面的 h()
函數改為:
function h () nargin == 1 || error ("nargin != 1\n"); end
則執行 f()
:
f()
輸出的訊息變為:
error: nargin != 1
由於處理函數輸入參數錯誤的情況很常見,因此 Octave 中提供了一個 print_usage()
函數專門用來處理這樣的狀況,當 print_usage()
函數被呼叫時,它會讀取呼叫它的函數的開頭註解,並輸出詳細的錯誤訊息:若函數說明是 Texinfo 的格式,則會輸出其中 @deftypefn
所定義的函數原型(prototype);若函數的說明不是 Texinfo 格式,則輸出的錯誤訊息會包含所有的函數說明。例如:
## -*- texinfo -*- ## @deftypefn {Function File} f (@var{arg1}) ## Function help text goes here... ## @end deftypefn function f (arg1) if (nargin == 0) print_usage (); endif endfunction
若執行 f()
函數沒有輸入參數時,則會輸出錯誤訊息:
f()
輸出的錯誤訊息為
error: Invalid call to f. Correct usage is: -- Function File: f (ARG1) Additional help for built-in functions and operators is available in the on-line version of the manual. Use the command `doc ' to search the manual index. Help and information about Octave is also available on the WWW at http://www.octave.org and via the help@octave.org mailing list.
print_usage () print_usage (name)
print_usage()
函數可以輸出參數 name
所指定的函數的使用說明,若省略 name
參數則會輸出目前函數的使用說明。
usage (msg)
usage(msg)
函數會將 msg
中訊息的每一行開頭加上 "usage: "
後輸出,並設置 Octave 內部的錯誤狀態,跳過之後所有的程式碼回到最上層的命令列,這個函數亦可用於中斷執行中的函數。當呼叫 usage()
函數後,Octave 也會輸出函數呼叫的 traceback。
當函數以不正確的參數呼叫時,可以使用 usage()
函數輸出適當的錯誤訊息,例如大部分的 Octave 內建函數的開頭都會使用類似這樣的程式碼來檢查輸入的參數個數:
if (nargin != 2) usage ("foo (a, b)"); endif
這樣當使用者所輸入的參數有問題時,可以輸出適當的訊息指引使用者如何使用此函數。
beep ()
beep()
函數可以讓喇叭產生一個嗶聲(beep)。
val = beep_on_error () old_val = beep_on_error (new_val)
beep_on_error()
函數可以查詢或設定是否要在錯誤訊息輸出前產生一個嗶聲。
獲取錯誤(Catching Errors)
當錯誤發生時,可以使用 try
敘述來處理錯誤(請參考 try
敘述),例如下面的範例會計算在迴圈中發生幾次錯誤:
number_of_errors = 0; for n = 1:100 try # ... catch number_of_errors++; end_try_catch endfor
上面這個範例中對於所有的錯誤都使用同一種處理方式,但有時候會需要針對不同的錯誤做不同的處理,此時可以使用 lasterror()
函數來判斷錯誤的類型,此函數會傳回包含最後一次錯誤資訊的資料結構,例如上面的範例可以修改為計算乘法運算子出現錯誤的次數:
number_of_errors = 0; for n = 1:100 try # ... catch msg = lasterror.message; if (strfind (msg, "operator *")) number_of_errors++; endif end_try_catch endfor
err = lasterror (err) lasterror ('reset')
lasterror()
函數可以設定或傳回包含最後一次的錯誤資訊的資料結構,此資料結構的欄位如下:
message
:錯誤訊息。identifier
:錯誤的辨識碼。stack
:包含錯誤發生位置的資料結構,當此資訊無法取得時,會是一個空的資料結構。以下是資料結構的欄位:file
:錯誤發生處的檔案名稱。name
:錯誤發生處的函數名稱。line
:錯誤發生處的行數。column:錯誤發生處的字元數。
這個 err
資料結構也可以當作 lasterror()
函數的傳入參數,以設定最後一次的錯誤資訊,此傳入的資料結構唯一的限制就是必須為純量的資料結構,而此傳入的資料結構中若是其欄位名稱符合上面所列的這些欄位,則會將其值設為傳入資料結構中欄位中對應的值,其餘的值維持預設值。
若 lasterror()
的傳入參數為 'reset'
,則會將所有的值設為預設值。
[msg, msgid] = lasterr (msg, msgid)
lasterr()
函數可以查詢或設定最後一次的錯誤訊息與錯誤的辨識碼,若呼叫時沒有任何輸入參數,則會傳回最後一次的錯誤訊息,若設定 msg
參數,則會將最後一次的錯誤訊息設定為 msg
,若再加上 msgid
參數則會再設定錯誤的辨識碼。
當錯誤被 catch
敘述處理之後,亦可以重新丟出錯誤,當錯誤被處理之後還是需要終止程式執行的情況,就可以使用重新丟出錯誤的方式處理。
要重新丟出錯誤可以使用 rethrow()
函數,上一個範例可以改成:若是乘法運算子出現錯誤,則計算其次數,否則就終止程式的執行:
number_of_errors = 0; for n = 1:100 try # ... catch msg = lasterror.message; if (strfind (msg, "operator *")) number_of_errors++; else rethrow (lasterror); endif end_try_catch endfor
rethrow (err)
rethrow(err)
函數會將 err
錯誤重新丟出,err
是一個至少包含 message
與 identifier
欄位的資料結構,另外亦可包含 stack
欄位(欄位的說明請參考上面 lasterror()
函數的說明),一般來說 err
可以由 lasterror()
函數取得。
err = errno () err = errno (val) err = errno (name)
errno()
函數可以傳回系統變數 errno
目前的值,若傳入一個數值參數 val
則會將系統變數 errno
設定為 val
;若傳入一個字串參數 name
則會傳回此名稱所對應的錯誤代碼,若找不到則傳回 -1
,例如:
errno("EIO")
輸出為
ans = 5
errno_list ()
errno_list()
函數會傳回一個資料結構,其中包含系統變數 errno
所有可能的錯誤代碼。
繼續閱讀: 12