6第6章 M文件与程序设计.docx
《6第6章 M文件与程序设计.docx》由会员分享,可在线阅读,更多相关《6第6章 M文件与程序设计.docx(22页珍藏版)》请在冰豆网上搜索。
6第6章M文件与程序设计
第6章M文件与程序设计
复杂问题的解算需要借助MATLAB程序进行。
这种程序的扩展名为m——故称为M文件。
M文件分为(M)脚本文件和(M)函数文件。
本章介绍编写MATLAB程序时常用的控制结构、函数文件的构造、主函数、子函数及述函数句柄的创建、观察和调用。
.1MATLAB控制流
语法
说明
if表达式
语句体1
elseif
语句体2
else
语句体3
end
1.若表达式返回数组,则仅当所有元素都不为零时为真;若数组为空,则为假。
2.elseif和else可选,其中可有多个elseif。
switch表达式
case表达式1
语句体1
case{式2,式3…}
语句体2
otherwise
语句体3
end
1.仅执行第一个满足条件的语句体。
2.case后可用花括号把多个表达式以“或”逻辑连接起来。
3.可有多个case语句。
4.otherwise可选。
forx=表达式
语句体
end
1.执行确定次数的循环。
2.表达式为矩阵时,x把矩阵按列拉长为向量取值。
while表达式
语句体
end
若表达式为真时,循环执行语句体。
.1.1if-else-end控制结构
if-else-end指令为程序流提供了一种分支控制。
表6.1-1if-else-end分支结构的使用方式
单分支
双分支
多分支
ifexpr
(commands)
end
ifexpr
(commands1)
else
(commands2)
end
ifexpr1
(commands)
elseifexpr2
(commands)
…….
else
(commandsk)
end
当expr给出“逻辑1”时,(commands)指令组才被执行。
当expr给出“逻辑1”时,(commands1)指令组被执行;否则,(commands2)被执行。
expr1,expr2,…中,首先给出“逻辑1”的那个分支的指令组被执行;否则,(commandsk)被执行。
该使用方法常被switch-case所取代。
【例6.1-1】已知函数
,编写能对任意一组输入x值求相应y值的程序。
(1)编写函数文件程序:
functiony=exm060101(x)
%y=exm060101(x)Functioncalculateofexample6.1-1
n=length(x);
fork=1:
n
ifx(k)<-1
y(k)=x(k);
elseifx(k)>=1
y(k)=exp(1-x(k));
else
y(k)=x(k)^3;
end
end
(2)保存在搜索路径上
(3)调用函数文件
x=[-2,-1.2,-0.4,0.8,1,6]
y=exm060101(x)
.1.2switch-case控制结构
表6.1-2switch-case控制结构的使用方式
指令格式
含义
switchexpr
casevalue_1
(commands1)
casevalue_2
(commands2)
casevalue_k
(commandsk)
otherwise
(commands)
end
●expr为根据此前给定变量进行计算的表达式
●value_1是给定的数值、字符串标量(或单元数组)
●若expr结果与value_1(或其中的单元元素)相等,则执行。
●value_k是给定的数值、字符串标量(或单元数组)
●若expr结果与value_k(或其中的单元元素)相等,则执行。
●该情况是以上的“并”的“补”
●若所有case都不发生,则执行该组命令。
【例6.1-2】已知学生的名字和百分制分数。
要求根据学生的百分制分数,分别采用“满分”、“优秀”、“良好”、“及格”和“不及格”等表示学生的学习成绩。
clear;
fork=1:
10
a(k)={89+k};b(k)={79+k};c(k)={69+k};d(k)={59+k};
end;
c=[d,c];
%
A=cell(3,5);
A(1,:
)={'Jack','Marry','Peter','Rose','Tom'};
A(2,:
)={72,83,56,94,100};
%
fork=1:
5
switchA{2,k}
case100
r='满分';
casea
r='优秀';
caseb
r='良好';
casec
r='及格';
otherwise
r='不及格';
end
A(3,k)={r};
end
A
.1.3for循环和while循环
表6.1-3循环结构的使用方式
for循环
while循环
forix=array
(commands)
end
whileexpression
(commands)
end
【例6.1-3】创建Hilbert矩阵。
(1)Hilbert矩阵
。
(2)
K=5;
A=zeros(K,K);
form=1:
K
forn=1:
K
A(m,n)=1/(m+n-1);
end
end
formatrat
A
%formatshortg
A=
Columns1through4
11/21/31/4
1/21/31/41/5
1/31/41/51/6
1/41/51/61/7
1/51/61/71/8
Column5
1/5
1/6
1/7
1/8
1/9
(3)
clear
tic
K=1000;
form=1:
K
forn=1:
K
A1(m,n)=1/(m+n-1);
end
end
t1=toc
tic
K=1000;
A2=zeros(K,K);
form=1:
K
forn=1:
K
A2(m,n)=1/(m+n-1)
end
end
t2=toc
(4)
tic
N=1000;
n=repmat(1:
N,N,1);
m=n';
A3=1./(n+m-1);
t3=toc
clear
tic
N=5;
n=repmat(1:
N,N,1);
m=n';
A3=1./(n+m-1);
t3=toc
formatrat
A3
A3=
10.50.333330.250.2
0.50.333330.250.20.16667
0.333330.250.20.166670.14286
0.250.20.166670.142860.125
0.20.166670.142860.1250.11111
t3=
0.66052
A3=
Columns1through4
11/21/31/4
1/21/31/41/5
1/31/41/51/6
1/41/51/61/7
1/51/61/71/8
Column5
1/5
1/6
1/7
1/8
1/9
【例6.1-5】创建n阶魔方矩阵,限定条件是n为能被4整除的偶数。
%exm060105.m生成一类魔方矩阵,该魔方矩阵的阶n为能被4整除的偶数。
%A为魔方矩阵
%n魔方矩阵的阶数
clear
clc
while1n=input('请输入一个能被4整除的正整数!
n=');
ifmod(n,4)==0break
end
end
G=logical(eye(4,4)+rot90(eye(4,4)));
m=n/4;
K=repmat(G,m,m);
N=n^2;
A=reshape(1:
N,n,n);
A(K)=N-A(K)+1
验证所生成的魔方阵正确与否的程序:
s0=round(n*(n*n+1)/2);
disp([int2str(n),'阶魔方矩阵的标称和是',int2str(s0)])
Ns0=round(2*(n+1));
B=A';
SC=sum(A);
SR=sum(B);
Sd=sum(diag(A));
Sdi=sum(diag(B));
LS=[SC,SR,Sd,Sdi]==s0;
NS=round(sum(LS));
ifNS==Ns0
disp('经验证,A是魔方矩阵。
')
else
disp('经验证,A不是魔方矩阵。
')
end
.1.4控制程序流的其它常用指令
表6.1-4控制程序流的其它常用指令
指令格式
使用说明
v=input('message')
v=input('message','s')
该指令执行时,“控制权”交给键盘;待输入结束,按下Enter键,“控制权”交还MATLAB。
message是提示用的字符串。
keyboard
遇到keyboard时,将“控制权”交给键盘,用户可以从键盘输入各种MATLAB指令。
break
break指令,或导致包含该指令的while、for循环终止,或在if-end,switch-case,try–catch中导致中断。
参见例6.1-5。
continue
跳过位于它之后的循环体中其他指令,而执行循环的下一个迭代..见例6.1-5。
pause
pause(n)
第一种格式使程序暂停执行,等待用户按任意键继续;
第二种格式使程序暂停n秒后,再继续执行。
return
结束return指令所在函数的执行,而把控制转至主调函数或者指令窗。
否则,只有待整个被调函数执行完后,才会转出。
try
语句体1
catch
语句体2
end
1.语句体1总被执行,若没有错误则跳出try/catch块。
2.若语句体1执行过程中发生错误,则执行语句体2。
3.可以嵌套使用。
利用try-catch模块,MATLAB编译系统发现的错误将被用户捕获,用户可以控制MATLAB怎样对发生的错误进行处理。
error('e1:
"%s"bad',svar)
显示错误信息并退出程序。
warning
显示警告信息但不退出程序。
dbstopifallerror
如遇错误/警告,则停止执行并进入调试状态
.2脚本文件和函数文件
注意:
用户自己创建的M文件的文件名要避免与MATLAB的内建函数和工具箱中的函数重名,以免发生内置函数被替换的情况。
.2.1M脚本文件
对于一些比较简单的问题,从指令窗中直接输入指令进行计算是十分轻松简单的事。
但随指令数的增加,或随控制流复杂度的增加,或重复计算要求的提出,直接从指令窗进行计算就显得烦琐。
而此时脚本文件最为适宜。
“脚本”本身反映这样一个事实:
MATLAB只是按文件所写的指令执行。
脚本文件的特点是:
●它只是一串按用户意图排列而成的MATLAB指令集合。
●脚本文件运行后,产生的所有变量都驻留在MATLAB基本工作空间中。
只要用户不使用clear指令加以清除,这些变量将一直保存在基本工作空间(Baseworkspace)中。
基本空间随MATLAB的启动而产生;只有当关闭MATLAB时,该基本空间才被删除。
.2.2M函数文件
函数文件犹如一个“黑箱”。
从外界只看到:
传给它的输入量和送出来的计算结果。
而内部运作是藏而不见的。
函数文件的特点是:
(1)从形式上看,与脚本文件不同,函数文件的第一行总是以"function"引导的“函数申明行”。
该行还罗列出函数与外界的联系的全部“标称”输入输出宗量。
但对“输入输出宗量”的标称数目并没有限制,即可以完全没有输入输出宗量,也可以是任意数目。
(2)MATLAB允许使用比“标称数目”较少的输入输出宗量,实现对函数的调用。
在一次调用中所用到的输入和输出变量的个数可以通过分别调用函数nargin和nargout来确定。
因为nargin和nargout是函数而不是变量,所以用户不能用诸如nargin=nargin+pi之类的语句对它们进行重新赋值。
(3)从运行上看,与脚本文件运行不同,每当函数文件运行,MATLAB就会专门为它开辟一个临时工作空间,称之谓函数工作空间(Functionworkspace)。
所有中间变量都存放在函数工作空间中。
当执行完文件最后一条指令或遇到return时,就结束该函数文件的运行,同时该临时函数空间及其所有的中间变量就立即被清除。
(4)函数空间随具体M函数文件的被调用而产生,随调用结束而删除。
函数空间是相对基本空间独立的、临时的。
在MATLAB整个运行期间,可以产生任意多个临时函数空间。
(5)假如在函数文件中,发生对某脚本文件的调用,那么该脚本文件运行产生的所有变量都存放于该函数空间之中,而不是存放在基本空间。
.2.3局部变量和全局变量
(1)局部(Local)变量
存在于函数空间内部的中间变量,产生于该函数的运行过程中,其影响范围也仅限于该函数本身。
正由于这种空间、时间上的局部性,中间变量被称为局部变量。
(2)全局(Global)变量
通过global指令,MATLAB也允许几个不同的函数空间以及基本工作空间共享同一个变量。
这种被共享的变量称为全局变量。
每个希望共享全局变量的函数或MATLAB基本工作空间,必须逐个用global对具体变量加以专门定义。
没采用global定义的函数或基本工作空间,将无权享用全局变量。
如果某个函数的运作使全局变量的内容发生了变化,那么其他函数空间以及基本工作空间中的同名变量也就随之变化。
’
除非与全局变量联系的所有工作空间都被删除,否则全局变量依然存在。
[说明]
●对全局变量的定义必须在该变量被使用之前进行。
建议把全局变量的定义放在函数体的首行位置。
●虽然MATLAB对全局变量的名字没有任何特别的限制,但是为了提高M文件的可读性,建议选用大写字符命名全局变量。
●全局变量损害函数的封装性,因此不提倡使用全局变量。
.2.4M文件的一般结构(看PPT课件)
基本组成部分
函数示例
函数头,定义函数名和输入输出参数(仅用于函数文件)
functionf=fact(n)
help帮助:
指M文件最前面连续的注释行,注意空行前也要有注释符。
命令helpfact可显示这些信息;H1行指M文件的第一行注释,用于lookfor快速查找。
H1行
%FACTFactorial.
%
%FACT(N)returnsN!
%FACT(N)isequaltoPROD(1:
N).
%
%Examples
%f=fact(5)
%
%SeealsoPROD
这个不带%的空行表示help帮助结束
普通注释
%Author:
WH
%$Version:
1.0$$Date:
2003.6$
语句体
检查输入输出参数,仅用于函数文件(也可以没有)
ifnargin~=1||~isnumeric(n)||...
~all(size(n)==[11])
error('Inputmustbeainteger.')
end
功能语句
f=prod(1:
n);
从结构上看,脚本文件只是比函数文件少一个“函数申明行”。
典型M函数文件的结构如下:
(1)函数申明行:
位于函数文件的首行,以function开头,函数名以及函数的输入输出宗量都在这一行定义。
(2)H1行:
它是紧随函数申明行之后以%开头的第一注释行。
H1行包含:
大写体的函数文件名;运用关键词简要描述的函数功能。
该H1行供lookfor关键词查询和help在线帮助使用。
(3)在线帮助文本(Helptext)区:
H1行及其之后的连续以%开头的所有注释行构成整个在线帮助文本。
它通常包括:
函数输入输出宗量的含义,调用格式说明。
(4)编写和修改记录:
与在线帮助文本区相隔一个“空”行,也以%开头,标志编写及修改该M文件的作者和日期、版本记录。
它用于软件档案管理。
(5)函数体(Functionbody):
为清晰起见,它与前面的注释以“空”行相隔。
这部分内容由实现该M函数文件功能的MATLAB指令组成。
它接收输入宗量,进行程序流控制,得到输出宗量。
若仅从运算角度看,惟有“函数申明行”和“函数体”两部分是构成M函数文件所必不可少的。
【例6.2-1】编写一个M函数文件。
它具有以下功能:
(A)根据指定的半径,画出蓝色圆周线;(B)可以通过输入字符串,改变圆周线的颜色、线型;(C)如果需要输出圆面积,则绘出圆。
(1)M函数文件
function[S,L]=exm060201(N,R,str)
%exm060201.mTheareaandperimeterofaregularpolygon(正多边形的面积和周长)
%NThenumberofsides
%RThecircumradius
%strAlinespecificationtodeterminelinetype/color
%STheareaoftheregularpolygon
%LTheperimeteroftheregularpolygon
%exm060201用蓝实线画半径为1的圆
%exm060201(N)用蓝实线画外接半径为1的正N边形
%exm060201(N,R)用蓝实线画外接半径为R的正N边形
%exm060201(N,R,str)用str指定的线画外接半径为R的正N边形
%S=exm060201(...)给出多边形面积S,并画相应正多边形填色图
%[S,L]=exm060201(...)给出多边形面积S和周长L,并画相应正多边形填色图
switchnargin
case0
N=100;R=1;str='-b';
case1
R=1;str='-b';
case2
str='-b';
case3;
otherwise
error('输入量太多。
');
end;
t=0:
2*pi/N:
2*pi;
x=R*sin(t);y=R*cos(t);
ifnargout==0
plot(x,y,str);
elseifnargout>2
error('输出量太多。
');
else
S=N*R*R*sin(2*pi/N)/2;
L=2*N*R*sin(pi/N);
fill(x,y,str)
end
axisequalsquare
boxon
shg
(2)调用指令
[S,L]=exm060201(6,2,'-g')
.3MATLAB的函数类别
在MATLAB中,函数又被细分为:
主函数;子函数;嵌套函数;私用函数;匿名函数等。
本节只对主函数、子函数及匿名函数进行阐述。
.3.1主函数(Primaryfunction)
.3.2子函数(Subfunction)
【例6.3-1】编写一个内含子函数的M函数绘图文件。
(1)M函数文件
functionHr=exm060301(flag)
%exm060301.mDemoforhandlesofprimaryfunctionsandsubfunctions
%flag可以取字符串'line'或'circle'。
%Hr子函数cirline的句柄
t=(0:
50)/50*2*pi;
x=sin(t);
y=cos(t);
Hr=@cirline;
feval(Hr,flag,x,y,t)
%-------------subfunction---------------------------
functioncirline(wd,x,y,t)
%cirline(wd,x,y,t)是位于exm060301.m函数体内的子函数
%wd接受字符串'line'或'circle'
%t画线用的独立参变量
%x由t产生的横坐标变量
%y由t产生的纵坐标变量
switchwd
case'line'
plot(t,x,'b',t,y,'r','LineWidth',2)
case'circle'
plot(x,y,'-g','LineWidth',8),
axissquareoff
otherwise
error('输入宗量只能取''line''或''circle''!
')
end
shg
(2)在命令窗调用该函数的命令
HH=exm060301('circle')
(3)直接利用创建的子函数句柄调用该主函数的子函数
t=0:
2*pi/5:
2*pi;x=cos(t);y=sin(t);
%为绘制正五边形准备数据
HH('circle',x,y,t)%利用句柄绘图
.3.3***(根据学时选讲)匿名函数(Anonymousfunction)
匿名函数提供了一种创建简单程序的方法,使用它用户可以不必每次都编写M文件。
用户可以在MATLAB的命令窗口或是其他任意M文件和脚本文件中使用匿名函数。
(1)创建匿名函数的一般方法:
FH=@(arglist)expr
(2)匿名函数的调用格式
FH(arglist)直接调用格式
feval(FH,arglist)间接调用格式
匿名函数算例:
【例4.1-6】求
。
symsxy
s=vpa(int(int(x^y,x,0,1),y,1,2))
s=
.40546510810816438197801311546432
formatlong
s_n=dblquad(@(x,y)x.^y,0,1,1,2)