顯示具有 Chap7 標籤的文章。 顯示所有文章
顯示具有 Chap7 標籤的文章。 顯示所有文章

10/28/2006

第七章 資料之輸入與輸出

資料之輸入及輸出同等重要。輸入與輸出均有特定的指令,有些應用於檔案,有些則直接由鍵盤輸入。在輸出的指令中,比較正式使用的為fprintf函數,其型式係沿用C語言,有些設定與該語言相通;比較簡單的型式則如disp指令,主要應用於螢幕之顯示。

輸出指令則以fscanf為主,其參數及格式與fprintf大體相同,而螢幕常用的指令則是input函數。詳細的分類可參考表5.1。

表7.1輸入輸出相關指令















輸出入指令說明
input 提供字串,使使用者輸入資料於一變數中
keyboard將執行權交至鍵盤
fscanf 按照特定的式自某輸出裝置輸出,包括輸出於螢幕上。
fread 讀入二位元資料
fprintf按照特定格式,印出資料
disp(x)輸出矩陣內容或文字內容,但不含變數名稱
menu自訂一個選擇菜單,經選項後決定其值
ginput 利用滑鼠之位置輸入座標值
return 結束返回
pause 暫停執行,按任意鍵繼續
fopen, fclose開啟檔案、關閉檔案
fwrite 寫入二位元資料

7.1 INPUT('message')

input之輸入指令主要應用於鍵盤輸入,然後按enter 確定輸入之內容。這些輸入之內容將設定給左邊的變數。


>>age=input('請問芳齡:')
請問芳齡: 60
age = 60


這個指令執行時,會將訊息打在螢幕上,然後等待使用者輸入任何資料。若沒輸入任何資料,僅按enter鍵,則age將會為一個空矩陣。空矩陣並不等於零,而是資料的另一種型式,可以用isempty()這個函數指令來檢驗。在輸入過程中,有時也必須利用這種技巧與程式使用者作順暢的交談。比如,輸入時常使用預設值,若使用者不輸入即直接按下enter,表示接受預設值,則程式可利用所得之空矩陣作檢驗,並設法餵給預設值。例如:

reply=input('要繼續嗎?y/n [y]','s');
if isempty(reply)
  reply='y'; %若為空矩陣,將其reply設為'y',以利程式進行
end


在input指令中,參數 's',表示輸入之內容當作字串,存於左邊的變數中。若沒有這個選項,則輸入之內容視為數值,此時若輸入文字則會有錯誤的信息。

7.2 MENU函數

menu這個指令為新版的功能。可改善input所無法顯示不同選擇的缺點。利用menu,可以將要選擇的項目逐一列出,並且先給一個標題或提示。經過選擇後,其值將轉存於左邊之變數中,其型式如下:

k=menu('標題', '選擇一','選擇二',…,'選擇N')


例如:

k=menu('請選擇你最喜歡的顏色:','紅色','黃色','藍色','白色','綠色')

















k = 5

這個指令適用於選擇性的問題,而且會自動產生一個小視窗,可以利用滑鼠選擇。選後得到的對應數值就存入k中(本例中選擇綠色,故k值為5),如此再作進一步的運算。

7.3 KEYBOARD & RETURN

keyboard是一個不用參數的指令。當程式執行到這個指令時,會將執行權開放到鍵盤,由鍵盤輸入。因此你可在鍵盤上下另外指令,查看資料、改變參數或檢查執行進度等等。等到在鍵盤上鍵入return指令時,執行權返回程式,在新更改的參數內容下,繼續往下執行。

7.4 DISP(X)

這個指令是最簡單列印資料的用法,其結果在螢幕中顯示。其中X可為矩陣,也可為文字模式,但不能兩者兼具。其顯示的結果不包含變數名稱,只有內容。例如:


>>disp('本期樂透彩中獎號碼為:')
ans=本期樂透彩中獎號碼為:
>>disp(rand(5,4)*10^3)
ans=
582.7917 225.9499 209.0694 567.8287
423.4963 579.8069 379.8184 794.2107
515.5118 760.3650 783.3286 59.1826
333.9515 529.8231 680.8458 602.8691
432.9066 640.5265 461.0951 50.2688


這樣的處理方式有點笨拙,文字顯示與矩陣顯示必須執行兩次,這是因為disp(X)中的X僅能處理一個參數。雖然如此,這個參數仍然可使用向量替換,故妥善的辦法是利用向量將一些數值經過轉換後,組成向量之型式以中括號起來。例如:
>disp(['今天的日期是 ' date]) 
今天的日期是 02-Apr-2006


若要文字與其他數值型變數共用,則必須利用num2str()的函數轉換;將數值轉成字串,然後用中括號括起來,當作一個向量參數處理。例如我的身高178公分,則:

>>height=178;
>>disp(['我現在的身高是 ' num2str(height) '公分。'])
我現在的身高是 178公分。


雖然經過這樣處理比較麻煩,但在程式寫作時,只要稍加用心也可以克服一些困難。這種處理方式同樣可以應用在input指令之文字串中,以提供更彈性的資訊給回答者。

7.6 列印函數FPRINTF

其格式如下:

count=fprintf(fid, format,A,…)


這是一個很通用的輸出指令,其輸出之格式依照指定的format,後面是所要輸出之參數名稱。其中fid代表輸出的裝置,fid=1代表標準裝置,或為螢幕,所以可以印在指令窗內。若要輸出至某一個檔案,則必須先將該檔案打開,即open指令打開一個檔,然後訂一個共通的代號fid。

列印格式則由format制定。format係由一系列包括C語言轉換碼之文字。其轉換控制包括符號、對齊、有效位數、欄寬及其他輸出之控制格式。此字串可包括特定字母,可代表非文字之控制標如新行及定位等。

這些轉換格式均以%符號開頭,並可能包括下列之項目:

  •  正負旗標
  •  欄寬及位數
  •  上下標
  •  轉換文字

上述的項目中,轉換文字必須存在,其餘視情況作選擇。












正負旗標位於輸出數字之前,可用+,-,0作為控制數字符號之用,若使用負號(-),則表示採用左邊對齊,正號(+)代表要印出該數字之正負號,若用零(0)置於前,表示其前面滿0。其例如%-10.5d、%+10.5d、%010.5d等等。

欄位寬度及有效位數則由數值表示,小數點前之數字代表總位數,如%6f,表示要列印六位數;若小數點後面有數字,表示該數之小數位數,如%6.3f表示有三位數小數,但總欄寬(包括小數點)為六位數。

格式標則在標明印出數值之性質,常用的如d代表十進位,e代表指數表示法,相關資訊如表5.2:

表7.2 格式標代碼表














格式標代碼 說明
%c單一文字
%d十進位(有正負符號)
%e 指數格式(如小寫1.414e+01)
%E 指數格式(如大寫1.414E+01)
%f 固定位數
%g 較%f或%e更為簡潔的型式,使用小寫e
%G 同%g但使用大寫E
%i 十進位(有正負符號)
%o 八進位(無正負符號)
%s 一串文字
%u 十進位(無正負符號)
%x 十六進位(使用小寫文字a-f)
%X 十六進位(使用大寫文字A-F)


在format格式中,也常使用控制標以印出控制的動作,這些包括換行、換頁等等,其項目如表5.3:

表7.3 控制標代碼表









控制標說明
\b倒退一格
\f進一頁
\n跳一新行
\r回行
\t水平跳格
\\反斜線符號
\''單括號
%%百分比%


下面為產生一串正弦值,然後將其存於一個名叫sinx.txt之文字檔案內。在新開一個檔時,通常要先用fopen開啟,等利用fprintf存完後,再用fclose令其關閉。才算存檔完成。

x=0:pi/10:pi; % %將pi分成十等分,置於x中
y=sin(x); %計算sin(x)值,置於y
% 打開一個名叫sinx.txt的文字檔,將其代碼設為fid,'w'代表要寫入
fid=fopen('sinx.txt','w');
%列印資料x,y於檔案中,格式x為%6.4f;y為%10.8f
fprintf(fid,'%6.4f %10.8f\n',x,y);
fclose(fid); %關閉檔案

type sinx.txt %將存檔內容印出

0.0000 0.31415927
0.6283 0.94247780
1.2566 1.57079633
1.8850 2.19911486
2.5133 2.82743339
3.1416 0.00000000
0.3090 0.58778525
0.8090 0.95105652
1.0000 0.95105652
0.8090 0.58778525
0.3090 0.00000000


在format格式中,亦可包括其他文字,使印出的報告容易閱讀。比如說:

>>height=178;
>>fprintf(1, '我的身高有 %4.0f cm,也就相當於 %4.2f ft.', height, height/30.48);
我的身高有 178 cm,也就相當於 5.84 ft.


這樣的文字讀起來也比較人性化一些。在此,fprintf括號內第一個參數1表示印在螢幕中,而中間即為格式之內容。其中除文字本身外,遇到%時表示是輸出變數的格式,而每遇到一個%的型式就需要有一個變數對應。故第一個%4.0f 對應變數height,第二個%4.2f對應height/30.48。

由於格式format 中,已經用掉撇號'、反斜線\及百分比號%,因此若要在文字中出現這些文字時,必須寫上兩次。例如:


>>fprintf(1,'My mother''s book is not 100%% complete yet.\n')
My mother's book is not 100% complete yet.


最後的\n表示跳到下一行列印。
相對於輸出之fprint指令,讀入資料可以利用fscan指令,其應用請待下回分解。

7.7 fscanf讀取資料

正式之讀取資料函數如下之格式:

A=fscanf(fid,format)

[A, count]=fscanf(fid,format,size)

這個指令可以自fid所標示的檔案中將其資料依format的格式取出,並置於矩陣A中。fid的定義與前述之fprintf指令相同。另一種型式則增加count與size兩參數。count表示已完成的資料筆數。而size則是決定讀入之資料量,可用[m,n]表示,表示讀入之資料可填滿m x n的矩陣。其中n 可用inf取代,代表EOF(End of File)。

此處格式format%符號大體上與fprintf相同,其中%e,%f,%g均代表具有浮點之數據。以%12hd為例,12為數值之總位數,d代表使用整數,其前面所置的文字表示整數的型式,h代表短整數,l代表長整數,而lg則代表雙精度浮點值。這些文字代碼可參考fprintf指令,其功能相似。


fid=fopen('sinx.txt');
A=fscanf(fid,'%g %g',[2 inf]); %最後項為size,表示讀入二列資料,直到檔案底
fclose(fid);

A=A'
A =
0 0.3142
0.6283 0.9425
1.2566 1.5708
1.8850 2.1991
2.5133 2.8274
3.1416 0
0.3090 0.5878
0.8090 0.9511
1.0000 0.9511
0.8090 0.5878
0.3090 0

7.8 存取excell檔案資料

許多資料多以微軟的速算表excell儲存,故如何自速算表中取得資料相當重要。為此,MATLAB有如下之指令可以自速算表中擷取資料:


[N, T, rawdata] = xlsread('filename', sheet, 'range')


其中filename為檔案名稱,包括路徑及副檔名.xls;sheet為速算表之序號或名稱,若為名稱則必須使用字串型式,如'sheet1'是。range則為所要指定的範圍,如'A1:C3',必須為範圍的型式,大小寫均可。若不指定範圍,即表示輸入整個速算表。若sheet=-1,則有特別功能,亦即可以直接在速算表指定其範圍即可,但此時必須將速算表同時開啟才行。在輸出參數方面,N為數值陣列,T為字串陣列,而rawdata則為細胞陣列,包括所有資料。

下面舉一個例子。設一速算表之內容如下:






















>> [N,A,rawdata]=xlsread('demo7.xls')
N =
12 NaN 60
14 NaN 105
16 NaN 56
18 NaN 48
20 NaN 50
A =
'頁數' '姓名' '年齡' '說明'
'' '馮丁樹' '' '本書的作者'
'' '張三豐' '' '太極拳祖爺'
'' '曹雪芹' '' '紅樓夢作者'
'' '高山青' '' '一首常唱的歌'
'' '文天祥' '' '作了正氣歌'
rawdata =
'頁數' '姓名' '年齡' '說明'
[ 12] '馮丁樹' [ 60] '本書的作者'
[ 14] '張三豐' [ 105] '太極拳祖爺'
[ 16] '曹雪芹' [ 56] '紅樓夢作者'
[ 18] '高山青' [ 48] '一首常唱的歌'
[ 20] '文天祥' [ 50] '作了正氣歌'


其中,N為數值矩陣,A為字串矩陣,而rawdata則為全部之資料,亦即細胞矩陣。


輸出至檔案之格式與參數也類似讀入之型式,其指令格式如下:

[status, message] = xlswrite('filename', M, sheet, 'range')

除上述之定義外,其中M為待輸出之矩陣,輸出檔案名稱可包含路徑。左邊有兩項資訊,若輸出成功,則status=1否則為0,message則會傳出錯誤的信息。其中有兩項,一為錯誤資訊的內容,另一為identifier,或為識別項。通常在寫入excell檔時,若原檔已有內容,則在進行存檔後會有如下之警告信息:

Warning: Added specified worksheet.

若不想這類信息一再出現,可以打入如下指令:

>>warning off MATLAB:xlswrite:AddSheet

如此,警告信息不會再出現,而後面MATLAB:xlswrite:AddSheet即為識別項idengifier。


例如:


>> books = {'書名', '價格(元)'; '模貝設計' 298; '模貝設計' 298; '基本電學' 580; '哈利波特' 660}
books =
'書名' '價格(元)'
'模貝設計' [ 298]
'模貝設計' [ 298]
'基本電學' [ 580]
'哈利波特' [ 660]

>> status=xlswrite('demo8.xls',books,'demo')
status = 1 %表示存檔成功


在excell之檔案內容如下: