第五讲 Matlab的程序设计 —— Matlab语言称为第四代编程语言,程序简洁、可读性很强而且调试十分容易, 是Matlab重要组成部分。要充分体现和发挥Matlab的能力,必 须掌握Matlab程序设计
包括以下内容: M文件的功能和特点 M文件的形式 数据结构和全局变量 程序结构 程序流控制 字符与字符串 函数调用及变量传递 M文件的调试
一、m文件的功能和特点 用户如想灵活应用Matlab去解决实际问题,充分调用Matlab的科学技术资源,就需要编辑m文件 包含Matlab语言代码的文件称为m文件,其扩展名为.m。 编辑m文件可使用各种文本编辑器。
二、Matlab的工作方式 指令行操作方式 通常Matlab以指令驱动模式工作,即在Matlab 窗口下当用户输入单行指令时,Matlab 立即处理这条指令,并显示结果,这就是Matlab命令行方式。 命令行操作时,Matlab窗口只允许一次执行一行上的一个或几个语句。
在Matlab窗口输入数据和命令进行计算时,当处理复杂问题和大量数据时是不方便的。因此应编辑m文件。 命令行方式程序可读性差,而且不能存储,对于复杂的问题,应编写成能存储的程序文件。
m文件的编程工作方式 将Matlab语句构成的程序存储成以m为扩展名的文件,然后再执行该程序文件,这种工作模式称为程序文件模式。 程序文件不能在指令窗口下建立,因为指令窗口只允许一次执行一行上的一个或几个语句。
三、 m文件的形式 m文件的语法类似于c语言,但又有其自身特点。它只是一个简单的ASCII码文本文件,执行程序时逐行解释运行程序,Matlab是解释性的编程语言。 m文件有两类 独立的m文件 — 称命令文件 可调用m文件 — 称函数文件 (1). 命令文件 — 简单的m文件 命令文件实际上是一串指令的集合,与在命令窗口逐行执行文件中的所有指令,其结果是一样的。没有输入输出参数。
%一个用以绘制花瓣(flower petal)图案的命令文件 theta=-pi:0.01:pi; rho(1,:)=2*sin(5*theta).^2; rho(2,:)=cos(10*theta).^3; rho(3,:)=sin(theta).^2; rho(4,:)=5*cos(3.5*theta).^3; for i=1:4 polar(theta,rho(i,:)); pause end
说明: 符号%引导的是注释行,不予执行. 不需要end作为M文件的结束标志. 若把untitle.m存放在自己的工作目录中,那么在运行untitle.m之前,就使自己的工作目录处于Matlab的搜索路径上。 文件运行后,存放在内存的变量可以通过whos指令看到,也可在workspace中看到。
(2) Matlab内置函数文件 Matlab自定义的函数文件称内置函数文件. 调用内置函数的方法:使用函数名并给出相应的入口、出口参数即可。 例如:sin.m函数——用type sin查不到。 调用格式:y=sin(2*x) 实际应用中: x=0:2*pi/180:2*pi; y=sin(2*x) plot(x,y)
又如 sqrt(x) —— 求x的平方根 abs(x)—— 求x的绝对值 det(a)—— 求行列式的值 等等。 Matlab拥有大量的内置数学函数,供我们在数值运算和符号运算中调用。
(3) 函数m文件— 需要输入变量,返回输出变量 Matlab用户可以根据需要编辑自己的m文件,它们可以像库函数一样方便的调用,从而极大地扩展了 对于某一类特殊问题,如创建了许多m函数文件,则可形成新的工具箱。 这种用Matlab语言创建定义新的Matlab函数的功能,正体现了Matlab语言强大的扩展功能。
函数m文件的格式: function 返回变量=函数名(输入变量) 注释说明语句段 程序语句段 特定规则: 函数m文件第一行必须以单词function作为引导词,必须遵循如下形式: function <因变量>=<函数名>(<自变量>) m文件的文件名必须是<函数名> .m。 程序中的变量均为局部变量,不保存在工作空间中。其变量只在函数运行期间有效。当函数文件执行完后,这些内部变量将被清除。
例2:计算向量元素的平均值 (1)建立函数文件,内容如下: function y=everage(x) %向量元素的平均值 %语法:average(x),其中x为输入向量 %当输入非向量时,给出错误信息 [m,n]=size(x); if(~((m==1)|(n==1))|(m==1&n==1)) error('input must be a vector'); end y=sum(x)/length(x);
(2)将文件average.m存盘,该文件定义了名为average的新函数。 (3)在指令窗中运行以下指令,可以求得1到100的平均值 >> everage(1:100) ans = 50.5000
说明 第一行指令的作用:指明该文件是函数文件;定义函数名、输入参数和输出参数。 变量x对函数文件everage.m来说是局部的,当该函数被调用结束后,变量x不再存在,这可以用who验证。 在m文件前面连续几行带符号%的注释行有两个作用:一是起注释作用;二是起help指令联机查询用。如:help everage
(4). 系统文件——s函数 用于描述系统运动的专用函数,是特殊的 m 文件。 s 函数有3类: 由simulink结构图自动创建 可用c语言程序设计mex文件直 接定义 用函数m文件编写 s函数一旦创建,即可在框图中使用,也可在文件中调用。
[sys, x0]=sfunction( t, x, u, flag) S函数与函数m文件类似,只是输入、输出变量是限定的。 用户定义的系统 当前输入值 状态初值 系统状态 当前时刻 标志量 当前状态值
三、数据结构和全局变量 数组(array) 数值型(numeric) 字符型 (char) 结构型 (struct) 单元型 (cell) 整型(storage) (int8,uint8,int16,uint16,int32,uint32) 双精度型 (double) 图:Matlab的数据结构
数值变量的类型可以用file菜单中preference子菜单中的general命令或format指令控制。 isstr可用以检测变量是否为字符型,返回值为1,则是字符型;0则不是. 对于其他变量可以用class(V)来得到其变量的类型。
在Matlab中全局变量用global定义,全局变量可以被所有定义该变量为全局变量的函数使用。全局变量的的作用域是整个Matlab的工作区,即全程有效,所以的函数都可以对他进行存取和修改。 如:global X Y Z,则将X,Y,Z定义为全局变量。 在程序设计中,全局变量可以带来一些数据传递的方便,但是也破坏了函数对变量的封装,降低了程序的可读性和可靠性。 函数文件的内部变量是局部的,与其他函数文件及Matlab内存相互隔离。
下面为一个使用全局变量的例子。 函数文件weight_add.m: function all=weight_add(x,y) %两个不同权系数的变量相加 global ALPHA BETA all=ALPHA*x+BETA*y; 命令文件: ALPHA=1; BETA=2; all=weight_add(1,1) 结果:all=3
运算符 逻辑操作符 关系操作符 功能说明 < 小于 >= 大于等于 <= 小于等于 = = 等于 > 大于 ~= 不等于 逻辑操作符 逻辑操作符 功能说明 & 与 | 或 ~ 非
例:表示不连续信号 x=linspace(0,5,100);%0到5中间产生100个数据点 y=cos(x); z=(y>=0).*y;%将cos函数的负数置为零 z=z+0.3*(y<0);%将cos函数的负数值增加0.3 z=(x<=4).*z;%将x超过4时z的值置为零 plot(x,z) xlabel('x');ylabel('z=f(x)');title('一个不连续信号');
四、Matlab的程序结构 (1).顺序结构 —— 依次顺序执行程序的各条语句
(2).循环结构 —— 被重复执行的一组语句,循环是计算机解决问题的主要手段。Matlab提供了两种循环方式:for-end 循环和while-end循环。 语法为: for i = 表达式 (表达式为一个向量) 可执行语句 end
例:利用for循环求1!+2!+3!+ +5!的值 sum=0; for i=1:5 pdr=1; for k=1:i pdr=pdr*k; end sum=sum+pdr; sum = 153
while循环将循环体中的语句循环执行不定次数。 语法为:while 表达式 循环体语句 end 表达式一般是由逻辑运算和关系运算以及一般运算组成的,以判断循环的进行和停止;只要表达式的值 非0,继续循环;直到表达式值为0,循环停止。
例:用while循环求1~100间整数的和 sum=0; i=1; while i<=100 sum=sum+i; i=i+1; end sum sum = 5050
(3). 分支结构——根据一定条件来执行的各条语句。 if — else — end语句有3种形式 if 表达式 执行语句 end if 表达式 ——— 是 语句1 else ———— 否 语句2
这种结构实现了一种多路选择,比较复杂。可替代一般高级语言中的switch-case-end语句 if 表达式1 ——— 多分支 语句1 elseif 表达式2 语句2 elseif 表达式3 语句3 · else 语句n end 这种结构实现了一种多路选择,比较复杂。可替代一般高级语言中的switch-case-end语句
关系操作符 >, < ,<=, >=, = =, ~= 等 逻辑操作符 &,| , ~等 在条件表达式中,通常都是由 关系操作符 >, < ,<=, >=, = =, ~= 等 逻辑操作符 &,| , ~等 逻辑函数:isequal —— 若是相等则为真 isempty ——若是空矩阵则为真 isstr —— 若是字符串则为真
例:折扣问题 apples=10; cost=apples*2.5; if apples>5 cost=0.8*cost; end; cost
例:编写m函数,计算函数值 x (x<1) 2x-1 (1<x<10) 3x-11 (x>=10) function value=calculate(x) if x<1 value=x; elseif x<10 value=2*x-1; else value=3*x-11; end
五、Matlab程序流的控制 echo 指令— 用来控制m文件在执行过程中是否 显示 echo on — 打开所有命令文件的显示方式 Matlab的控制语句同c语言有相似之处, 但没有c 语言复杂、灵活和多变。因而语法比较简单,容易掌握。 echo 指令— 用来控制m文件在执行过程中是否 显示 echo on — 打开所有命令文件的显示方式 echo off — 关闭所有命令文件的显示方式 echo — 在以上两者间切换
echo file on — 打开file函数文件的显示方式 echo file off — 关闭file函数文件的显示方式 echo对于命令文件函数文件有所不同,命令文件用法简单,echo对所有命令起作用;函数文件用法较复杂,具体请help查询。 echo file on — 打开file函数文件的显示方式 echo file off — 关闭file函数文件的显示方式 echo file — 切换file函数文件的显示方式 echo on all — 打开所有函数文件的显示方式 echo off all —关闭所有函数文件的显示方式
input —— 提示用户从键盘输入数值、字符串、表达式。 例:n=input('How many apples= ') How many apples= 5 n = 5 pause —— 暂停,等待用户响应 可令m文件执行暂停,并在继续执行前按任一个键 。
keyboard —— 与input类似,功能更强 keyboard 调用键盘与调用m文件一样,当keyboard在m文件中出现时,它停止文件的执行并控制键盘,用于修改程序。 break —— 中断 break 中断for, while循环语句的执行,在嵌套循环结构中, break进从最里层循环推出。 menu —— 产生一个用户可选择输入的菜单 格式:k=menu( ‘标题’,‘菜单1’,‘菜单2’ …)
六、字符与字符串 在Matlab中关于字符串有以下几点规则: 在Matlab中所有字符串都用单引号界定后输入或赋值。 如:s='hello',的运行结果是 s = hello 字符串的每个字符(空格也是字符)都是响应矩阵的一个元素。如上s是一个1×5的矩阵。可用size查得。 字符以ASCII码存储,用abs 指令可看到字符的ASCII值。 abs(s) ans = 104 101 108 108 111
可用setstr实现ASCII码值向字符的转换。 字符串变量也可以用方括号变成更大的“串” 如:s=[s,‘ world’],得到, s =hello world 用eval和feval函数将字符变量转换为宏功能。 eval(t)和feval(t)就是运行包含在t 中的内容。
例: n=5; t='1/(i+j-1)'; a=zeros(n); for i=1:n for j=1:n a(i,j)=eval(t); end a
例: fun=['sin';'cos';'log']; k=input('choose function number:'); x=input('enter value:'); feval(fun(k,:),x)
七、函数调用及变量传递 一个程序可以由若干个函数组成,并通过函数调用来实现控制转移和相互之间的数据传递。 (1)函数调用 在Matlab中函数调用的常用形式是: [输出参数1,输出参数2,…]=函数名(输入参数1,输入参数2,…) 注意:函数调用时各参数出现的顺序,应该与函数定义时的顺序一样,否则出错
例:给定两个实数a、b,一个正整数n,给出k=1,…,n时的所有 和 (1)建立一个函数文件pow.m function [out1,out2]=pow(a,b,n) out1=(a+b)^n; out2=(a-b)^n; (2)建立调用上述函数文件的命令文件example.m a=input('please input a=:'); b=input('please input b=:'); for k=1:10 [add_pow(k),sub_pow(k)]=pow(a,b,k); end
例:利用递归调用形式计算n的阶乘。 (1)编写递归调用函数文件factor.m function f=factor(n) if n==1 f=1; return; else f=n*factor(n-1); end (2)运行函数文件 factor(4)
(2)参数的传递 Matlab在函数调用上有一个与众不同的地方:函数所传递的参数具有可调性,凭借这种特性,一个函数可以完成多种功能。 传递参数数目的可调性来源于如下2个永久变量。 nargin 函数体内的nargin 给出调用该函数时的输入参数数目。 nargout 函数体内的nargout 给出调用该函数时的输出参数数目。
function [x0,y0] = myplot(fname,lims,npts,angl,subdiv) % MYPLOT Plot a function. % MYPLOT(fname,lims,npts,angl,subdiv) % The first two input arguments are % required; the other three have default values. ... if nargin < 5, subdiv = 20; end if nargin < 4, angl = 10; end if nargin < 3, npts = 25; end if nargout == 0 plot(x,y) else x0 = x; y0 = y; end
八、应用程序接口 应用程序接口——是Matlab的附加组件。是一个 由相关函数组成的接口函数库,可实现与外部程 序的交互。 MEX文件:是Matlab环境下调用C、FORTRAN 语言编写的应用程序模块。 Matlab 计算引擎:在使用C、FORTRAN编程时 可调用Matlab函数库进行计算。 MAT文件:实现Matlab与C、FORTRAN语言程序间的 数据交换
九、M文件的调试 Matlab语言比其他程序设计语言在说明结构上要简单得多,但是用户必须按语法的要求来编写Matlab程序,否则也会产生一些错误。 (1)调试的主要功能 可以发现和更正以下错误: 语法错误 主要包括函数名拼写和括号遗漏等,Matlab可以自动检测到,并指出可能出错的行号。
运行错误 这类错误通常是算法错误,而语法是正确的。这种情况运行的结果是错误的,却不会出现出错的地方。 运行错误一般难于跟踪,可以用下列技巧发现某些运行错误: 1、在M文件中将某些语句的分号去掉,迫使M文件输出一些中间计算的结果,以以便发现算法错误。 2、在M文件中设置断点。
(2)GUI调试界面的使用 介绍工具栏上部分按钮的使用。 菜单命令 意义 continue 恢复程序运行到结束或另一个断点 Single step 单步执行函数 Step in 深入下层局部工作区 Quit debugging 退出调试状态 Set/clear breakpoint 设置/清除光标处的断点 Clear breakpoint 清除程序中的所有断点 Stop if error 运行到错误或结束 Stop of warning 运行至警告或结束 Stop if NaN of inf 运行到计算结果出现Nan或Inf
小 结 本节主要介绍了Matlab语言程序设计基础。Matlab 编程简单,容易掌握。 通过学习,应能编写简单程序