M文件和函数句柄

Download Report

Transcript M文件和函数句柄

第六章 M文件和函数句柄
—— matlab语言称为第四代
编程语言,程序简洁、可读性
很强而且调试十分容易。
进行程序设计的m文件是
matlab重要组成部分。
本章内容
§1
matlab控制流
§2
脚本文件和函数文件
§3
函数类别
§4
函数句柄
6.1 MATLAB控制流
(1) 顺序结构 —— 依次顺序执行程序的各条语句
(2) 分支结构——根据一定条件来执行各条语句。
 if — else — end条件控制语句有3种形式
单分支 、双分支、多分支
 switch — case — otherwise — end结构
仅执行满足条件的分支
(3) 循环结构 —— 被重复执行的一组语句。
循环语句主要有:
 for — end
 while — end
6.1 MATLAB控制流
6.1.1 if — else — end条件控制
分支控制有3种形式
 单分支
if 表达式
执行语句
end
 双分支
if 表达式
语句1
else
语句2
end
多分支
if 表达式1
语句1
elseif 表达式2
语句2
elseif 表达式3
语句3
·
·
·
else
语句n
end
• 在条件表达式中,通常用
关系操作符:
>, < ,<=, >=, = =, ~=
逻辑操作符:
&,| , ~
逻辑函数:isequal —— 若是相等则为真
isempty ——若是空矩阵则为真
isstr —— 若是字符串则为真
例6.1-1:编写m函数,
对于任意一组输入x值,
计算函数值
x
(x<-1)
y = x3 (-1≤x<1)
e-x+1 (x≥1)
function y=abc(x)
% function calculate of y
n=length(x);
for k=1:n
if x(k)<-1
y(k)=x(k);
elseif x(k)>=1
y(k)=exp(1-x(k));
else
y(k)=x(k)^3;
end
end
x=[-2,-1.2,-0.4,0.8,1,6]
y=abc (x)
x =
-2.0000 -1.2000 -0.4000
y =
-2.0000 -1.2000 -0.0640
0.8000
1.0000
6.0000
0.5120
1.0000
0.0067
6.1.2 switch-case 控制结构
switch-case语法结构:
switch expr
case value1
(commands 1)
case value2
……
case vlauek
(commands k)
otherwise
(commands)
end
●当遇到switch结构时, matlab将表达式的值依次和各个case指
令后面的检测值进行比较.如果比较结果为假,则取下一个检测值再
比较,一旦比较结果为真, matlab将执行相应的一组命令,然后跳出
该结构。如果所有的比较结果都为假,即表达式和所有的检测值都
不等, matlab将执行otherwise后面的一组命令.可见该结构保证
至少有一组命令会得到执行。
●switch指令后面的表达式为一个标量或者一个字符串。对于标
量形式的表达式,比较这样进行:表达式==检测值i.对于字符串,将调
用函数strcmp来实现比较。
●case指令后面的检测值不仅可以是一个标量值或字符串,还可
以是一个单元数组。如果一个检测值是一个单元数组,matlab将
把表达式的值和该单元数组中的所有元素进行比较,如果单元数
组中某个元素和表达式的值相等,就认为此次比较结果为真。
●当matlab检测到某个检测值和表达式相等时,将执行相应的一
组命令,执行完毕,自动跳出swith结构,无需使用break指令。
例6.1-2:根据学生百分制分数进行等级成绩划分.
for i=1:10
a{i}=89+i; b{i}=79+i; c{i}=69+i; d{i}=59+i;
end
%用胞元数组
c=[d,c];
A=cell(2,5);
A(1,:)={'Jack','Marry','Peter','Rose','Tom'};
A(2,:)={72,83,56,94,100}; %用胞元数组
for k=1:5
switch A{2,k}
case 100,
A{3,k}= '满分';
case a,
A{3,k}= '优秀';
case b,
A{3,k}= '良好';
case c,
A{3,k}= '及格';
otherwise, A{3,k}= '不及格';
end 'Jack' 'Marry' 'Peter' 'Rose' 'Tom'
end
[ 72]
[ 83]
[ 56]
[ 94] [ 100]
A
'及格‘
'良好'
'不及格'
'优秀‘
'满分'
6.1.3 for循环和while循环
for循环结构语法为:
for i = 表达式 (表达式为一个向量)
可执行语句
end
例6.1-3:用for循环生成Hilbert方阵 ( a(i, j )  1 /(i  j  1) )
循环法:
向量法:
K=5;
A=zeros(K,K);%预配置内存空间 N=5;
for m=1:K
n=repmat(1:N,N,1);
for n=1:K
m=n';
A(m,n)=1/(m+n-1);
end
format rat
end
A3=1./(n+m-1)
format rat
A
while — end 循环结构语法为:
while 表达式
循环体语句
end
表达式一般是由逻辑运算和关系运算以及一
般运算组成的,以判断循环的进行和停止;只
要表达式的值非0,继续循环;直到表达式值为
0,循环停止。可借助break指令退出循环。
N
例6.1-4:计算
S 
n 1
1
n
k
, 其中N  arg min{
k 1
1
N
k
  }.为给定精度
k 1
function [S,N]=exm060104(epsilon)
k=0;s=0;d=inf;S=0;
while d>epsilon
k=k+1;
符号法验证结果:
s=s+k; %sum(1:k)
N=141;
SN=vpa(symsum(1/symsum(k,1,n),n,1,N))
d=1/s;
%N项(141项)和
S=S+d;
SN=1.9859154929577464788732394366197
end
syms k n N
N=k;
调用:
SINF=limit(symsum(1/symsum(k,1,n),n,1,N),N,inf)
SINF=2
>>[S,N]=exm060104(0.0001)
S = 1.9859, N = 141
【例6.1-5】创建n阶魔方矩阵,限定条件是n为能被4整除
的偶数。
(1)所谓魔方矩阵(Magic matrix),是指那矩阵由1
到n2的正整数按照一定规则排列而成,并且每列、每行、
每条对角线元素的和都等于n(n2+1)/2 。就生成规则而
言,魔方矩阵可分成三类:一,n为奇数;二,n为不
能被4整除的偶数;三,n为能被4整除的偶数。
clear;clc;
while 1
n=input('请输入一个能被4整除的正整数! n = ');
if mod(n,4)==0
break
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));
if NS==Ns0
disp('经验证,A是魔方矩阵。')
else
disp('经验证,A不是魔方矩阵。')
end
12 阶魔方矩阵的标称和是
经验证,A是魔方矩阵。
870
6.1.3 控制程序流的其他常用指令见表6.1-4
input
keyboard
break
continue
pause(n)
return
控制程序程序流的其他常用指令
 1) v=input('msg')
v=input('msg', 's' )
 该指令执行时,控制权交给键盘,待输入结束,按Enter键,
控制权交换matlab, msg是提示用的字符串,告诉用户
输入什么.
 第一种格式用于键入数值,字符串等数据,最后v是一个
数值(包括数组)或者一个字符串.
 第二种格式,不管键入什么,总以字符串形式赋给变量v。
2) keyboard
从M文件中激活键盘,遇到该命令时,将控制权交
给键盘,用户可以从键盘输入各种matlab指令,
仅当用户输入return指令后,控制权才交还给程
序。与input指令的区别是:该指令允许输入任
意多个matlab指令, 而input只能输入赋给变量
的值。该指令在调试M文件时非常有用。
3) continue
跳过位于其后的循环中的其他指令,执行循环的下一个迭代
例 更改数组中的值
a=ones(1,12);count=0;s=0;
for k=1:12
if rem(k,3)==0
continue
break
else
s=s+k;
end
count = count + 1;
end
count = 8
4) break
终止while,for循环,也可以在if-end, switch-case, try-catch
中导致中断
5) pause, pause(n)
第一种格式使程序暂停执行,等待用户按任意键继续,第二种格
式使程序暂停n秒后,再继续执行
6) return
结束return指令所在函数的执行,把控制转至主调函数或指令
窗.否则,只有整个被调函数执行完毕才转出
6.2 脚本文件 和函数文件
 m文件的语法类似于c语言,但又有其自身特点。它
只是一个简单的ASCII码文本文件,执行程序时逐行
解释运行程序。


m文件有两类独立的m文件 — 称脚本文件
可调用m文件 — 称函数文件
6.2.1 脚本文件
 脚本文件 — 简单的m文件
 脚本文件实际上是一串指令的集合,与在命令窗口
逐行执行文件中的所有指令,其结果是一样的。没
有输入输出参数。
 运行产生的所有变量驻留在基本工作空间。
6.2.2 M函数文件— 需要输入变量,返回输出变量
函数m文件的格式:
function 返回变量=函数名(输入变量)
%注释说明语句段
程序语句段
特定规则:
1. 函数m文件第一行必须以单词function作为引导词,
必须遵循如下形式:
function <因变量>=<函数名>(<自变量>)
2. m文件的文件名最好是<函数名> .m。
3. 程序中的变量均为局部变量,不保存在工作空间中。
其变量只在函数运行期间有效。
6.2.3 局部变量和全局变量
• 局部(local)变量
– 它存在于函数空间内部的中间变量,产生于该函数
的运行过程中,其影响范围也仅限于该函数本身。
• 全局(global)变量
– 通过global指令定义变量,Matlab也允许几个不同
的函数空间以及基本工作空间共享同一个变量。这
种被共享的变量称为全局变量。每个希望共享全局
变量的函数或Matlab基本工作空间,必须逐个用
global对具体变量加以专门定义。没有采用global定
义的函数或基本工作空间,将无权享用全局变量。
关于全局变量的说明
 如果某个函数的运作使全局变量的内容发生了变化,
那么其他函数空间以及基本工作空间中的同名变量
也就随之变化。
 除非与全局变量联系的所有工作空间都被删除,否
则全局变量依然存在。
 对全局变量的定义必须在该变量被使用之前进行。
建议把全局变量的定义放在函数体的首行位置。
 虽然Matlab对全局变量的名字没有任何特别的限制,
但是为了提高 M文件的可读性,建议选用大写字符
命名全局变量。
 由于全局变量损害函数的封装性,因此不提倡使用
全局变量。
6.2.4 函数文件一般结构: 举例vdp1,ode45
1.函数申明行 :位于函数文件的首行,以关键字
function开头,函数名以及函数的输入输出参量都在
这一行定义。函数名和文件名必须相同。
2.H1行:紧随函数申明行之后以 %开头的第一行注释
行,包括大写体的函数文件名;运用关键词要描述
的函数功能。
3.在线帮助文件文本 :H1行及其之后的连续 %开头的
所有注释行构成整个在线帮助文本。它通常包括:
函数输入输出参量的含义,调用格式说明。
6.2.4 函数文件一般结构
4.编写和修改记录:与在线帮助文本区相隔一个“空”
行,也以%开头。标志编写及修改该文件的作者、日
期和版本记录。它用于软件档案管理。
5.函数体:这部分内容由实现该 M函数文件功能的
Matlab指令组成。它接收输入参量,进行程序流控制,
得到输出参量。
例6.2-1:根据指定边数N、半径、线型色彩,绘出圆周
线(正多边形)或填色圆 (正多边形) 。
function [S,L]=exm060201(N,R,str)
switch nargin
调用:
case 0, N=100;R=1;str='-b';
[S,L]=exm060201(6,2,'-g')
case 1, R=1;str='-b';
case 2, str='-b';
case 3 ;
otherwise, error('输入量太多');
end;
t=0:2*pi/N:2*pi;
x=R*sin(t);y=R*cos(t);
if nargout==0,plot(x,y,str)
elseif nargout>2,error('输出量太多');
else
S=N*R*R*sin(2*pi/N) /2;
L=2*N*R*sin(pi/N);
fill(x,y,str)
end
axis equal square,box on,shg
%将该函数M文件存于matlab搜索路径上
1
0.5
0
-0.5
-1
-1
-0.5
0
0.5
1
例6.1-2存为M函数文件, 百分成绩转换为五级制成绩。
function grade=score2grade(score);
% TRANS 将学生分数 score 转换为五级制成绩grade
% 级别,90-100, A; 80-89, B; 70-79,C; 60-69,D; others, E;
for i=1:10
a{i}=89+i; b{i}=79+i; c{i}=69+i; d{i}=59+i;
end
for k=1:length(score)
switch score(k)
case 100, grade{k}= ‘A';
case a, grade{k}= ' A ';
case b, grade{k}= ‘B';
case c, grade{k}= ‘C';
case d, grade{k}= ‘D';
otherwise, grade{k}= ‘E';
end
end
6.3 MATLAB 的函数类别
(1)主函数:由第一个function引出的函数
(2)子函数:由非第一个function引出的,寄生在主函数体内
的函数
各函数间通过输入输出宗量或全局变量传递
(3)匿名函数:不以文件形式驻留在文件夹中
创建:FH=@(arglis)expr
直接调用:FH(arglis)
用函数句柄演算函数间接调用:feval(FH,arglis)
例:匿名函数的调用
y=@(x)(x.^2+x-20)
feval(y,2) 或 y(2)
6.3 MATLAB 的函数类别
6.3.1 主函数
• 通常每个 M 文件中的第一个函数为主函数,
主函数可以被该文件之外的其他函数调用,而
子函数只能被该文件内的函数调用。主函数的
调用通过存储该函数的 M 文件的文件名调用。
我们在前面几节中编写的实验程序,大多为主
函数。因此,这里不再过多介绍。
6.3.2 子函数
 一个 M 文件中可以包括多个函数,除主函数之外的
其他函数称为子函数。子函数只能被主函数或该文
件内的其他子函数调用。每个子函数以函数定义语
句开头,直至下一个函数的定义或文件的结尾。
 当函数中调用函数时,系统判断其函数类型的顺序
为:首先判断是否为子函数,然后判断是否为私有
函数,最后判断其是否为当前目录下的 M 文件函数
或者系统内置函数。由于子函数具有最高的优先级
别,因此,在定义子函数时,可以采用已有的其他
外部函数的名称。
子函数
– 每个子函数的第一行是其自己的函数申明行;
– 主函数的位置不可改变,但子函数的排列次序可以
任意改变;
– 子函数只能被处于同一文件的主函数或其他子函数
调用;
– 在M函数文件中,任何指令通过“名字”对函数进
行调用时,子函数的优先级仅次于内装函数。
– 同一文件的主函数、子函数的工作空间都是彼此独
立的。各函数间的信息,或通过输入输出宗量传递,
或通过全局变量传递,或通过跨空间指令传递。
– help,lookfor等帮助指令都不提供关于子函数的任
何帮助信息。
第四章习题六用主、子函数实现
function y0_5=main( )
tspan=[0, 0.5];
y0=[1;0];
[tt,yy]=ode45(@DyDt,tspan,y0);
y0_5=yy(end,1);
function ydot=DyDt (t,y)
mu=3;
ydot=[y(2);mu*y(2)-2*y(1)+1];
在命令行输入y0_5=main,即可得到结果
例6.3-1: 编写一个内含子函数的函数M文件
function Hr=exm060301(flag)
%------prime function----------t=(0:50)/50*2*pi;
x=sin(t);y=cos(t);
Hr=@cirline;
feval(Hr,flag,x,y,t)
%------subfunction----------function cirline(wd,x,y,t)
switch wd
case 'line'
plot(t,x,'b',t,y,'r');
case 'circle'
plot(x,y,'-g')
otherwise
error('输入宗量错!')
end
axis square
%主调函数
exm060301('line')
HH=exm060301('circle')
%绘图并返回子函数句柄
t=(0:2*pi/5:2*pi);
x=cos(t);
y=sin(t);
HH('circle',x,y,t)
%通过子函数句柄直接调用子函数
6.3.3 匿名函数
 匿名函数提供了一种创建简单程序的方法,使用它用户
可以不必每次都编写 M 文件。用户可以在 MATLAB
的命令窗口或是其他任意 M 文件和脚本文件中使用匿
名函数。
 匿名函数的创建格式为:
FH = @(arglist) expr
其中 FH 是为该函数创建的函数句柄;@ 符号用于创建
函数句柄;arglist 为用逗号分隔的参数列表;expr 为函
数主体,为 MATLAB 表达式。
 匿名函数的调用格式为:
FH (arglist)
%直接调用
feval(FH, arglist) %间接调用
嵌套函数
• 一个函数内部可以定义其他的函数,这
种内部的函数称作嵌套函数。
• 1.嵌套函数的书写
• 定义嵌套函数时,只要在一个函数内部
直接定义嵌套函数即可。需要注意的是
当一个 M文件中存在嵌套函数时,该文
件内的所有函数必须以 end 结尾。
私用函数
 私用函数的构造与普通 M函数完全相同;
 私用函数只能被 private目录的直接父目录上的 M函
数文件所调用。它不能被其他目录上的任何M函数、
M脚本文件或 Matlab指令窗中的命令所调用,也不能
被直接父目录上的 M脚本文件调用。
 M文件中,任何指令通过“名字”对函数进行调用时,
私用函数的优先级虽低于内装函数和子函数,但高于
其他任何目录上的函数
 help, lookfor等指令都不能提供关于私用函数的任何帮
助信息。
串演算函数
• 一种是串演算函数eval,它具有对字符串
表达式进行计算的能力;
• 另一种是“函数句柄演算函数”feval,
它具有对函数句柄进行操作的能力。
y=eval('CEM')
执行CEM指定的计算
[y1,y2,…]=eval('CEM') 执行CEM代表的函数文件,并输出结果
• eval指令的输入参量必须是字符串;
• 构成字符串CEM,可以是Matlab任何合法
的指令、表达式、语句或M文件名;
• 第二种格式中的CEM只能是(包含输入参
量在内的)M函数文件名;
6.4 函数句柄
6.4.1 函数句柄的创建和观察
 函数句柄是matlab的一种数据类型,携带着“相应
函数创建句柄时的路径、视野(Scope)、函数名及重
载方法”。
优点:
 使函数调用像变量一样灵活方便
 拓宽子函数包括局部函数的使用范围
 提高函数调用的可靠性和软件的重用性
 减少程序设计中的冗余
 提高重复执行的效率
6.4.1 函数句柄的创建和观察
 函数句柄的定义有两种:(1)在提示符 @ 后添加
相应函数的函数名;(2)利用转换函数str2func。
f_h=@plot %与f_h=str2func('plot')等价
则: f_h =
@plot
函数句柄内涵的观察通过functions实现
functions(f_h)
ans =
function: 'plot'
type: 'simple‘
file: 'MATLAB built-in function‘
6.4.2函数句柄的基本用法
如果一个函数的调用格式为:
[argout1,argout2,…argoutn]=FunName(argin1,argin2,…,arginn)
假设该函数的句柄为,那么通过函数句柄实现函数运算的
调用格式为:
(1) 直接调用格式
[argout1,argout2,…,argoutn]=hfun(argin1,argin2,..,arginn)
(2) 间接调用格式
[argout1,argout2,…,argoutn]=feval(hfun,argin1,argin2,..,arginn)
6.4.2 函数句柄的调用
(1) 直接调用
例: f_h1=@peaks %f_h1=str2func(‘peaks’)
f_h1(50)
(2) 间接调用: feval(函数句柄,参数列表)
例: f_h=@plot %f_h=str2func(‘plot’)
feval(f_h,0:10,0:10)
例6.2-1:根据指定不同的半径、色彩、线型,绘出圆周线或圆。
调用:
function [S,L]=exm060201(N,R,str)
switch nargin
[S,L]=exm060201(8,2,'-g')
case 0, N=100;R=1;str='-b';
[S,L]=exm060201(7,3)
case 1, R=1;str='-b';
[S,L]=exm060201(5)
case 2, str='-b';
[S,L]=exm060201
case 3 ;
exm060201(8,2,'-g')
otherwise, error('输入量太多');
end;
t=0:2*pi/N:2*pi;
函数句柄调用:
x=R*sin(t);y=R*cos(t);
H=@exm060201
if nargout==0,plot(x,y,str)
elseif nargout>2,error('输出量太多'); [S,L]=H(7,3)
else
改变路径为d:\再调用:
S=N*R*R*sin(2*pi/N/2);
[S,L]=H(5,2)
L=2*N*R*sin(pi/N);
exm060201(8,2,‘-g’)
fill(x,y,str)
end
axis equal square,box on,shg
%将该函数M文件存于c:\
域名
function
说
明
句柄所代表的函数名
simple
type
无重载的内建函数,M,P函数文件或
无法判断类型的函数
函
数 subfunction 子函数
类 private
私用函数
型 constructor matlab类的对象构造函数
overloaded 有重载的函数
非重载数据类型所对应的源代码及路径,若有内建
函数,总列在此栏
methods 仅当函数类型为重载时,返回结构才有该域
file
小
结
• matlab的程序结构: 顺序、分支、循环结
构
• 程序M文件,函数M文件,函数文件一般结构
• 函数类别,主、子函数,匿名函数
• 函数句柄: @plot, str2func(‘plot’)
习题5 (Page226)
1,4,5,7 题