570 likes | 774 Views
第七章 M 文件和面向对象编程. 内容:. 脚本; 函数; 函数句柄的创建和使用; 程序调试和剖析; 数据结构(类、对象); 重载和继承; 面向对象编程. 7.1 入门. 通过M脚本文件,画出下列分段函数所表示的曲面。. a=2;b=2; clf; x=-a:0.2:a;y=-b:0.2:b; for i=1:length(y) for j=1:length(x) if x(j)+y(i)>1 z(i,j)=0.5457*exp(-0.75*y(i)^2-3.75*x(j)^2-1.5*x(j));
E N D
第七章 M 文件和面向对象编程 内容: • 脚本; • 函数; • 函数句柄的创建和使用; • 程序调试和剖析; • 数据结构(类、对象); • 重载和继承; • 面向对象编程
7.1 入门 通过M脚本文件,画出下列分段函数所表示的曲面。
a=2;b=2; clf; x=-a:0.2:a;y=-b:0.2:b; for i=1:length(y) for j=1:length(x) if x(j)+y(i)>1 z(i,j)=0.5457*exp(-0.75*y(i)^2-3.75*x(j)^2-1.5*x(j)); elseif x(j)+y(i)<=-1 z(i,j)=0.5457*exp(-0.75*y(i)^2-3.75*x(j)^2+1.5*x(j)); else z(i,j)=0.7575*exp(-y(i)^2-6*x(j)^2); end end end axis([-a,a,-b,b,min(min(z)),max(max(z))]); colormap(flipud(winter));surf(x,y,z);
7.2 MATLAB 控制流 7.2.1 for循环结构 语法形式: for x=array (commands) end for i=1:10; x(i)=i; end;
7.2.2 while循环结构 语法形式: while expression (commands) end i=1; while i<10; x(i)=i; i=i+1; end;
a = 0; fa = -Inf; b = 3; fb = Inf; while b-a > eps*b x = (a+b)/2; fx = x^3-2*x-5; if sign(fx) == sign(fa) a = x; fa = fx; else b = x; fb = fx; end end x
7.2.3 if-else-end分支 (1)if 表达式 执行语句 end 功能:如果表达式的值为真,就执行语句,否则执行end后面的语句。
(2) if 表达式 执行语句1 else 执行语句2 end 功能:如果表达式的值为真,就执行语句1,否则执行语句2。
(3)if 表达式1 • 执行语句1 • elseif 表达式2 • 执行语句2 • else • 语句n • end • 功能:如果表达式1的值为真,就执行语句1,然后跳出if执行语句;否则判断表达式2,如果表达式2的值为真,就执行语句2,然后跳出if执行语句.否则依此类推,一直进行下去。如果所有的表达式的值都为假,就执行end后面的语句。
7.2.4 switch-case 结构 Switch语句的形式为: switch 表达式 case 常量表达式1 语句块1 case 常量表达式2 语句块2 case {常量表达式n,常量表达式n+1,…} 语句块n otherwise 语句块n+1 end
功能: switch语句后面的表达式可以为任何类型;每个case后面的常量表达式可以是多个,也可以是不同类型;与if语句不同的是,各个case 和otherwise 语句出现的先后顺序不会影响程序运行的结果。
例: 编一个转换成绩等级的函数文件,其中成绩等级转换标准为考试成绩分数在[90,100]分显示优秀;在[80,90)分显示良好;在[60,80)分显示及格;在[0,60)分显示不及格。
function result=ff(x) n=fix(x/10); switch n case {9,10} disp('优秀') case 8 disp('良好') case {6,7} disp('及格') otherwise disp('不及格') end
7.2.5 try-catch结构 语法结构 try (commands1) catch (commands2) end 说明: • 只有当matlab在执行组命令1时出现了错误后,组命令2才会被执行 • 可调用lasterr函数查询出错原因 • 当执行组命令2时又出错,matlab将终止该结构
例 对(3× 3) 魔方阵的行进行援引,当“行下标”超出魔 方阵的最大行数时,将改向对最后一行的援引,并显 示“出错”警告。 clear,N=4;A=magic(3); try A_N=A(N,:) catch A_end=A(end,:) end lasterr
7.2.6 控制程序流的其它常用指令 • 1 return指令 通常,当被调函数执行完后,matlab会自动地把控制转至主调函数或者指令窗。如果在被调函数中插入了return指令,可以强制matlab结束执行该函数并把控制转出。
2 input和keyboard指令 (1)input input指令将matlab的“控制权”暂时交给用户。此后, 用户通过键盘键入数值、字符串或者表达式,并经“回 车”把键入内容输入工作空间,同时把“控制权”交还给 matlab。
格式: v=input(‘message’) 将用户键入的内容赋给变量v v=input(‘message’,’s’)将用户键入的内容作为字符串赋给变量v 说明: • 指令中‘message’是将显示在屏幕上的字符串,是必不可少的 • 对于第一种调用格式,用户可以输入数值、字符串、元胞数组等各种形式的数据。 • 对于第二种调用格式,不管键入什么,总以字符串形式赋给变量v。
(2)keyboard指令 当程序遇到keyboard时,matlab将“控制权”交给键盘,用户可以从键盘输入各种合法的matlab指令,只有当用户使用return指令结束输入后,“控制权”才交还给程序。 (3)pause指令 pause 暂停执行文件,等待用户按任意键继续。 pause(n) 在继续执行之前,暂停n秒 (4)break指令 break指令可以导致包含有该指令的while、for等指令终止。
(5)error和warning指令 常用的警示指令: • error('message') 显示出错信息message,终止程序。 • errortrap 错误发生后,程序继续执行与否的双位开关。 • lasterr 显示matlab自动判断的最新出错原因并终止程序。 • warning(‘message’) 显示警告信息message,程序继续运行。 • lastwarn 显示matlab自动给出的最新警告,程序继续运行。
7.3 脚本文件和函数文件 7.3.1 M脚本文件 M脚本文件特点: • 它只是一串按用户意图排列而成的matlab指令集合。 • 脚本文件运行后,所产生的所有变量都驻留在matlab基本工作空间中。
7.3.2 M函数文件 与脚本文件不同,函数文件犹如一个“黑箱”,它的特点: • 从形式上看,与脚本文件不同,函数文件的第一行总是以“function”引导的函数申明行。 • matlab允许使用比“标称数目”较少的输入输出参数,实现对函数的调用。 • 从运行上看,中间变量都存在在临时工作空间。 • 在matlab整个运行期间,可以产生任意多个临时函数空间。 • 假如在函数文件中,发生对某脚本文件的调用,那么该脚本文件运行产生的所有变量都存放于函数空间之中,而不是存放在基本空间。
7.3.3 局部变量和全局变量 (1)局部(local)变量 存在于函数空间内部的中间变量,产生于该函数的运行过程中,其影响范围仅限于该函数本身。 (2)全局(Global)变量 通过global指令,matlab允许几个不同的函数空间以及基本工作空间共享同一个变量,这种被共享的变量称为全局变量。
说明: • 没采用global定义的函数或基本工作空间,将无权享用全局变量。 • 除非与全局变量联系的所有工作空间都被删除,否则全局变量依然存在。 • 对全局变量的定义必须在该变量被使用之前进行。建议把全局变量的定义放在函数体的首行位置。 • 建议选用大写字符命名全局变量 • 不提倡使用全局变量。
7.3.4 M文件的一般结构 演示: (A)编写一个画任意半径任意色彩线型的圆。 (B)完整函数文件的基本结构。 (C)函数文件各基本组成部分的作用。 (参看lesson7-1)
M 函数文件的结构如下: • 函数申明行 • H1行(The first help text line) • 在线帮助文本(help text)区 • 编写和修改记录 • 函数体
7.3.5 P码文件 1、语法分析过程和伪代码 一个M文件首次被调用时,matlab将首先对该M文件进行语法分析,并把生成的相应内部伪代码文件存放在内存中。 Matlab的分析器总是把M文件连同被它调用的所有函数M文件一起变成P码文件 形式: 文件名相同,扩展名是”.p”
2、P码文件的预生成 P码文件可以被预先生成 pcode FunName 在当前目录上生成FunName.p pcode FunName -inplace 在FunName.m所在目录上生成FunName.p P码文件的优点: • 运行速度快; • 程序保密性好;
3、内存中P码文件的列表和清除 inmem 罗列出内存中所有P码文件名 clear FunName 清除内存中的FunName.pP码文件 clear functions 清除内存中的所有P码文件
7.3.6 Matlab 的搜索过程 假设Matlab在一个文件中碰到指令cow时,它将按以下步骤进行检索。 (1)检查cow是否一个变量名;如果不是,执行下一步。 (2)检查cow是不是内建函数(Built-in Function);假如不是,执行下一步。 (3)检查cow是不是cow所在的M文件中的一个子函数;假如不是,再往下执行。 (4)检查cow是不是cow所在的M文件中的一个私有函数;假如不是,在往下执行。 (5)检查cow是不是当前目录上的文件;假如不是,再往下执行。 (6)检查搜索路径上是否有cow存在。
7.4 变量的检测传递和限权使用函数 7.4.1 输入输出宗量检测指令 nargin 在函数体内,用于获取实际输入参数 nargout 在函数体内,用于获取实际输出参数 nargin(‘fun’) 获取‘fun’指定函数的标称输入参数个数 nargout(‘fun’) 获取’fun’指定函数的标称输出参数个数 inputname(n)在函数体内使用,给出第n个输入参数的 实际调用变量名
7.4.2“变长度”输入输出参数 varargin “变长度”输入参数列表 varargout “变长度”输出参数列表 例 编写程序,画两个同心圆环,其中一个半径由独立输入参数定义,另一个由变长度输入参数的第一个参数定义,可以用任何指定的色彩,线型绘制;(lesson7_2)
有输出情况 r1=1;r2=3; [x1,y1,x2,y2,s1,s2]=lesson7_2(r1); [x1,y1,x2,y2]=lesson7_2(r1,r2); [x1,y1,x2,y2,s1,s2]=lesson7_2(r1,r2); 无输出情况 r1=1;r2=0.6; subplot(1,3,1),lesson7_2(r1,r2); subplot(1,3,2),lesson7_2(r1,r2,'Marker','o') subplot(1,3,3); lesson7_2(r1,r2,'LineWidth',5,'Color',[1 0.4 0])
7.4.3 跨空间变量传递 1、跨空间计算串表达式的值 evalin(‘workspace’,’expression’) 跨空间计算表达式值 evalin(‘workspace’,’expression1’,’expression2’) 跨空间计算替代串表达式值
clear,a=30;t=(0:a)/a*2*pi;sss={'base','caller','self'}; for k=1:3 y0=lesson7_3(8,sss{k}); subplot(1,3,k) plot(real(y0),imag(y0),'r','LineWidth',3),axis square image end 例 编写绘制正多边形或圆的程序。(lesson7_3)
2、跨空间赋值 assignin(‘workspace’,’VN’,x) 跨空间向VN变量赋值 [lesson7_4.m] function y= lesson7_4(x) y=sqrt(x);t=x^2; assignin('base','yy',t)
7.4.4 子函数和私用函数 1、子函数 matlab允许1个M函数文件包含多个函数的代码。其中,第一个出现的称为主函数,该文件中其他的函数则称为子函数。 保存时所用函数文件名与主函数定义名相同。 外部程序只能对主函数进行调用。
子函数性质: • 每个子函数的第一行是其自己的函数申明行 • 在M函数文件内,主函数的位置不可改变,但子函数的排列次序可以任意改变 • 子函数只能被处于同一文件的主函数或其他子函数调用 • 在M函数文件中,任何指令通过“名字”对函数进行调用时,子函数的优先级仅次于内装函数 • 同一文件的主函数、子函数的工作空间都是彼此独立的。
2、私有函数 所谓私用函数,是指位于private目录上的M文件函数,性质: • 私用函数的构造与普通M函数完全相同 • 私用函数只能被private直接父目录上的M文件所调用,而不能被其他目录上的任何M文件或matlab指令窗中的命令所调用 • M文件中,任何指令通过“名字”对函数进行调用时,私用函数的优先级虽低于内装函数和子函数,但高于其他任何目录上的函数。
7.5 串演算函数 为了提高计算的灵活性,matlab提供一种利用字符串进行计算的能力。 7.5.1 eval y=eval(‘CEM’) 执行CEM指定的计算; y=eval(‘CEM1’,’CEM2’) 先执行CEM1指定的计算,如果出错,就执行CEM2 [y1,y2,…]=eval(‘CEM’) 执行CEM代表的函数文件调用,并输出计算结果。
说明 • eval指令的输入参数必须是字符串 • 构成字符串的CEM,可以是matlab任何合法的指 令、表达式、语句或M文件名 • 第3种格式种的CEM只能是M函数文件名。 例 计算“表达式”串,产生向量值。 clear,t=pi;cem='[t/2,t*2,sin(t)]';y=eval(cem)
例 计算“语句”串,创建变量。 clear,t=pi;eval('theta=t/2,y=sin(theta)');who 例 计算“替代”串。 A=ones(2,1);B=ones(1,3);c=eval('B*A','A*B'); errmessage=lasterr 例 计算“合成”串。 CEM={'cos','sin','tan'}; for k=1:3 theta=pi*k/12;y(1,k)=eval([CEM{1},'(',num2str(theta),')']); end
7.5.2 feval [y1,y2,…]=feval(‘FN’,arg1,arg2,…) 用参量arg1,arg2等执行FN函数指定的计算。 说明: • ‘FN’只能是函数名。 • 在既可以使用eval,又可以使用feval的情况下,feval运行效率更高。
feval 和eval 运行区别:feval 的FN 绝对不能是表达式 x=pi/4;Ve=eval('1+sin(x)') Vf=feval('1+sin(x)',x) feval 和eval 调用区别:feval 的FN 只接受函数名。 randn('seed',1);A=rand(2,2); [ue,de,ve]=eval('svd(A)'); disp('Results by eval');disp([ue,de,ve]);disp(blanks(1)) [uf,df,vf]=feval('svd',A); disp('Results by feval');disp([uf,df,vf])
7.5.3 内联函数 1、 内联函数的创建 inline(‘CE’) 把串表达式转化为输入参数自动生成的内联函数; inline(‘CE’,arg1,arg2,…) 把串表达式转化为arg1,arg2等指定输入参数的内联函 数; inline(‘CE’,n) 把串表达式转化为x,P1,P2,…Pn等指定输入参数的内联 函数
2、涉及内联函数性质的指令 class(inline_fun) 给出内联函数类型 char(inline_fun) 给出内联函数计算公式; argnames(inline_fun) 给出内联函数的输入参数 vectorize(inline_fun) 使用内联函数适用”数组运算”规则。
3 、内联函数创建和应用示例内联函数的第一种创建格式适于“数组运算”。clear,F1=inline('sin(rho)/rho');f1=F1(2);FF1=vectorize(F1);xx=[0.5,1,1.5,2];ff1=FF1(xx);第一种内联函数创建格式的缺陷;含向量的多宗量输入的赋值。G1=inline('a*exp(x(1))*cos(x(2))'),G1(2,[-1,pi/3]);G2=inline('a*exp(x(1))*cos(x(2))','a','x'),G2(2,[-1,pi/3])
产生向量输入、向量输出的内联函数; Y2=inline('[x(1)^2;3*x(1)*sin(x(2))]') argnames(Y2) x=[4,pi/6]; y2=Y2(x) 最简练格式创建内联函数;内联函数可被feval 指令调 用 Z2=inline('P1*x*sin(x^2+P2)',2) z2=Z2(2,2,3) fz2=feval(Z2,2,2,3)
7.6 面向对象编程 1、类和对象 matlab内装类
2、新类应包含的基本内容 (1)创建类目录 (2)选定待建类的数据结构 (3)对象构造函数 (4)显示函数 (5)与其他类之间的转换函数 (6)其他重载函数和重载运算 (参见queue类)