1、第6章 MATLAB程序设计,MATLAB有两种常用的工作方式, 交互式命令行操作方式, M文件的编程工作方式,6.1 M文件,M文件有两种形式:脚本文件(Script File)和函数文件(Function File)。脚本文件通常用于执行一系列简单的MATLAB命令,运行时只需输入文件名字,MATLAB就会自动按顺序执行文件中的命令;函数文件和脚本文件不同,它可以接受参数,也可以返回参数,在一般情况下,用户不能靠单独键入其文件名来运行函数文件,而必须由其他语句来调用,MATLAB的大多数应用程序都是由函数文件的形式给出的。,6.1.1 局部变量与全局变量,函数文件所定义的变量是局部变量,这
2、些变量独立于其他函数的局部变量和工作空间的变量,即只能在该函数的工作空间引用,而不能在其它函数工作空间和命令工作空间引用。,如果某些变量定义成全局变量,就可以在整个MATLAB工作空间进行存取和修改,以实现共享。因此,定义全局变量是函数间传递信息的一种手段。 用命令global定义全局变量,其格式为: global A B C 习惯上我们可以将全局变量定义为大写字母。,6.1.2 M文件的编辑与运行,新建文件: 单击MATLAB的主界面的工具栏上的图标; 在命令窗口输入命令edit建立新文件,或输入命令edit filename, 利用MATLAB主界面的File|New子菜单,再从右拉菜单中
3、选择“M-file”项;,打开文件: 编辑文件: 保存文件,运行文件,l 在命令窗口输入要运行的文件名即可开始运行,需要注意的是,在运行前,一定要先保存文件,否则运行的是保存前的程序。 l 如果在编辑器中完成编辑后需要直接运行,可以选择编辑器的Debug|Save and Run选项(如果文件已经保存过,该选顶则变为Run)。 按F5键则保存程序并直接运行;如果是新建M文件,则弹出“保存文件”对话框,用户保存文件后直接运行。,6.1.3 脚本文件,脚本文件是M文件中最简单的一种,不需要输入输出参数,用命令语句可以控制MATLAB命令工作空间的所有数据。在运行过程中,产生的所有变量均是命令工作空
4、间变量,这些变量一旦生成,就一直保存在内存空间中,除非用户运行clear命令将它们清除。,运行一个脚本文件等价于从命令窗口中顺序运行文件里的命令。由于脚本文件只是一串命令的集合,因此只需像在命令窗口中输入命令那样,依次将命令编辑在脚本文件中即可。,例6. 1 编程计算向量元素的平均值。 % average_1.m 计算向量元素的平均值 x=input(输入向量:x=); m,n =size(x); %判断输入量的大小 if(m=1)|(n=1)| (m=1)& (n=1) %判断输入是否为向量error(必须输入向量。) end average=sum(x)/length(x),注意:运行前,
5、应该将文件存放的目录设置成可搜索路径,设置方法见1.7。例外一种简单的方法是:选择编辑器的Debug|Save and Run或按F5键直接运行,若文件不在搜索路径列表中,则弹出图6.1所示对话框,可以将文件所在的目录设置成当前目录、添加到MATLAB搜索路径的开头或最后,然后直接运行。,6.1.4 函数文件,如果M文件的第一个可执行语句以function开始,该文件就是函数文件,每一个函数文件都定义一个函数。事实上,MATLAB提供的函数命令大部分都是由函数文件定义的,这足以说明函数文件的重要。,函数文件区别于脚本文件之处在于脚本文件的变量为命令工作空间变量,在文件执行完成后保留在命令工作空
6、间中;而函数文件内定义的变量为局部变量,只在函数文件内部起作用,当函数文件执行完后,这些内部变量将被清除。,例6. 2 编写average_2函数用于计算向量元素的平均值。 function y=average_2(x) % 函数average_2(x)用以计算向量元素的平均值。 % 输入参数x为输入向量,输出参数y为计算的平均值。 % 非向量输入将导致错误。 m,n=size(x); %判断输入量的大小 if(m=1)|(n=1)| (m=1) %计算向量x所有元素的平均值, z=1:99; average_2(z) ans =50,通常函数文件由以下几个基本部分组成: (1)函数定义行:函
7、数定义行由关键字function引导,指明这是一个函数文件,并定义函数名、输入参数和输出参数,函数定义行必须为文件的第一个可执行语句,函数名与文件名相同,可以是MATLAB中任何合法的字符。 函数文件可以带有多个输入和输出参数,如: function x,y,z=sphere(theta,phi,rho) 也可以没有输出参数,如: function printresults(x),(2)H1行:H1行就是帮助文本的第一行,是函数定义行下的第一个注释行,是供lookfor查询时使用的。一般来说为了充分利用MATLAB的搜索功能,在编制M文件时,应在H1行中尽可能多地包含该函数的特征信息。由于在搜
8、索路径上包含average的函数很多,因此用lookfor average可能会查询到多个有关的命令。如: lookfor average_2 average_2.m: % 函数average_2(x)用以计算向量元素的平均值。,(3)帮助文本:在函数定义行后面,连续的注释行不仅可以起到解释与提示作用,更重要的是为用户自己的函数文件建立在线查询信息,以供help命令在线查询时使用。如: help average_2函数average_2(x)用以计算向量元素的平均值。输入参数x为输入向量,输出参数y为计算的平均值。 非向量输入将导致错误,(4)函数体:函数体包含了全部的用于完成计算及给输出参数
9、赋值等工作的语句,这些语句可以是调用函数、流程控制、交互式输入/输出、计算、赋值、注释和空行。 (5)注释:以%起始到行尾结束的部分为注释部分,MATLAB的注释可以放置在程序的任何位置,可以单独占一行,也可以在一个语句之后,如: %非向量输入将导致错误 m,n=size(x); %判断输入量的大小,6.1.5 函数调用,调用函数文件的一般格式为: 输出参数表=函数名(输入参数表) 调用函数时应注意: (1)当调用一个函数时,输入和输出参数的顺序应与函数定义时的一致,其数目可以按少于函数文件中所规定的输入和输出参数调用函数,但不能使用多于函数文件所规定的输入和输出参数数目。例如: x,y=si
10、n(pi) y=linspace(2),(2)在编写函数文件调用时常通过nargin、nargout函数来设置缺省输入参数,并决定用户所希望的输出参数。函数nargin可以检测函数被调用时用户指定的输入参数个数;函数nargout可以检测函数被调用时用户指定的输出参数个数。在函数文件中通过nargin、nargout函数,可以适应函数被调用时,用户输入和输出参数数目少于函数文件中function语句所规定数目的情况,以决定采用何种缺省输入参数和用户所希望的输出参数。,function y = linspace(d1, d2, n) %LINSPACE Linearly spaced vecto
11、r.if nargin = 2n = 100; end n = double(n); y = d1+(0:n-2)*(d2-d1)/(floor(n)-1) d2;,(3)当函数有一个以上输出参数时,输出参数包含在方括号内。例如,m,n=size(x)。注意:m,n在左边表示函数的两个输出参数m和n;不要把它和m,n在等号右边的情况混淆,如y=m,n表示数组y由数组m和n所组成。 (4)当函数有一个或多个输出参数,但调用时未指定输出参数,则不给输出变量赋任何值。,function t=toc % TOC Read the stopwatch timer.Global TICTOC If nar
12、gout1elapsed_time=etime(clock,TICTOC) else t=etime(clock,TICTOC); end,如果用户调用toc时不指定输出参数t,例如: tic toc elapsed_time =4.0160 函数在命令窗口显示函数工作空间变量elapsed_time的值,但在MATLAB命令工作空间里不给输出参数t赋任何值,也不创建变量t。,如果如果用户调用toc时指定输出参数t,例如: tic out=toc out =2.8140 则以变量out的形式返回到命令窗口,并在MATLAB命令工作空间里创建变量out。,(5)函数有自己的独立工作空间,它与MA
13、TLAB的工作空间分开。除非使用全局变量,函数内变量与MATLAB其它工作空间之间唯一的联系是函数的输入和输出参数。如果函数任一输入参数值发生变化,其变化仅在函数内出现,不影响MATLAB其它工作空间的变量。函数内所创建的变量只驻留在该函数工作空间,而且只在函数执行期间临时存在,以后就消失。因此,从一个调用到另一个调用,在函数工作空间以变量存储信息是不可能的。,(6)在MATLAB其它工作空间重新定义预定义的变量(例如pi),它不会延伸到函数的工作空间;反之亦然,即在函数内重新定义预定义的变量不会延伸到MATLAB的其它工作空间中。 (7)如果变量说明是全局的,函数可以与其它函数、MATLAB
14、命令工作空间和递归调用本身共享变量。为了在函数内或MATLAB命令工作空间中访问全局变量,全局变量在每一个所希望的工作空间都必须说明。,(8)全局变量可以为编程带来某些方便,但却破坏了函数对变量的封装,所以在实际编程中,无论什么时候都应尽量避免使用全局变量。如果一定要用全局变量,建议全局变量名要长、采用大写字母,并有选择地以首次出现的M文件的名字开头,使全局变量之间不必要的互作用减至最小。 (9)MATLAB以搜寻脚本文件的同样方式搜寻函数文件。例如,输入cow,MATLAB首先认为cow是一个变量;如果它不是,那么MATLAB认为它是一个内置函数;如果还不是,MATLAB检查当前cow.m的
15、目录或文件夹;如果仍然不是,MATLAB就检查cow.m在MATLAB搜寻路径上的所有目录或文件夹。,(10)从函数文件内可以调用脚本文件。在这种情况下,脚本文件查看函数工作空间,不查看MATLAB命令工作空间。从函数文件内调用的脚本文件不必调到内存进行编译,函数每调用一次,它们就被打开和解释。因此,从函数文件内调用脚本文件减慢了函数的执行。 (11)当函数文件到达文件终点,或者碰到返回命令return,就结束执行和返回。return命令提供了一种结束函数的简单方法,而不必到达文件的终点。,6.2 MATLAB的程序控制结构,作为一种程序设计语言,MATLAB语言和其他的程序设计语言一样,除了
16、按正常顺序执行的程序结构外,还提供了各种控制程序流程的语句,如循环语句、条件语句、开关语句等。控制流程极其重要,通过对流程控制语句的组合使用,可以实现多种复杂功能的程序设计,经常出现在M文件中。,6.2.1 循环结构,在MATLAB中实现循环结构的语句有两种:for循环语句和while循环语句,1. for 循环,for循环允许一组命令以固定的和预定的次数重复。For循环的一般形式是: for 循环控制变量=表达式1:表达式2:表达式3 语句 end 在for循环语句中,循环体内不能出现对循环控制变量的重新设置,否则将会出错;for循环允许嵌套使用。,例6. 3 求的值。 s=0; for n
17、=1:10s=s+n; end s,例6. 4 在区间2 ,0.75 内,以步长0.25,对函数y=f(x) = 1+1/x求值,并列表显示。 r= ; s= ; for x= -2.0:0.25:-0.75 y=1+1/x; r=r x; s=s y; end r; s,使用for循环语句值得注意的是: (1)for循环不能用循环内重新给循环变量赋值来终止。例如: x=0; for n=1:4x =x+1 n=5; end,(2)for循环的循环变量= 表达式1:表达式2:表达式3,其实为一行向量,例如:1:2:10= 0 2 4 6 8 10,它还可以是数组,其更一般的形式为: for 循
18、环控制变量 = 数组表达式 语句 end,例6. 5 用for循环求行向量-2,5,3,6,-2各元素之和。 a=-2,5,3,6,-2; s=0; k=0; for n=an %显示每一次循环变量的值k=k+1; %记录循环次数s=s+n; %计算行向量a各元素之和 end k,s %显示总的循环次数和计算结果,例6. 6 观察下列程序的运行结果。 data=3 9 45 6; 7 16 -1 5 k=0; for n=datan %显示每一次循环变量的值k=k+1; %记录循环次数x=n(1)-n(2) end k,从例6.46.6的结果,大家可以看出,当循环变量为m1 m2 mn维数组x
19、时,for循环的总循环次数为m2 mn,第i次循环时循环变量n的值为列向量x(i, j,k),j、k分别为第2n维的下标,从1m2,1mn依次变化。,(3)for循环可嵌套使用。,例6. 8 以for循环求1!+2!+10!的值。 s=0; for i=1:10p=1;for j=1:ip=p*j;end s=s+p; end s,4)当有一个等效的数组方法来解给定的问题时,应避免用for循环。 例6. 9 比较下面两段程序的执行情况。 (a)for n=1:10x(n)=sin(n*pi/10);endx (b)n=1:10;x=sin(n*pi/10),(5)为了得到更快的速度,在for循
20、环(while循环)被执行之前,应预先分配数组。如例6.9(a),在for循环内每执行一次命令,变量x的大小增加1,迫使MATLAB每进行一次循环都要花费时间对x分配更多的内存。为了省去这个步骤,可以在例6.9(a)程序的首行加入:x=zeros(1,10); %为x分配内存单元,2. while循环,for循环的循环次数往往是固定的,而while循环可不定循环次数,其一般形式为:while 关系表达式语句end 只要在表达式里的所有元素为真,就执行while和end 语句之间的“语句”。通常,表达式的求值给出一个标量值,但数组值也同样有效。在数组情况下,所得到数组的所有元素必须都为真。,例6
21、. 10 分析下列程序的功能。 num=0; EPS=1; while (1+EPS)1 EPS=EPS/2; num=num+1; end num=num-1 EPS=2*EPS,注意:for循环的循环变量为m1 m2 mn维数组,循环次数在一开始就由数组确定为m2 mn,所以在循环体内并不能通过改变循环控制变量的值终止循环;而while循环是先执行循环体内的语句,再判断循环的条件是否成立,在循环体内可以通过改变循环控制变量的值终止循环。,6.2.2 选择结构,很多情况下,需要根据不同的条件执行不同的语句,在编程语言里,是通过选择结构实现的。MATLAB的选择结构语句有if语句、switch
22、语句和try语句。,1. if语句,if语句的一般结构是:if 表达式 语句1 else语句2end,例6. 11 以for循环求容差变量eps。 EPS=1; for n=1:100EPS=EPS/2;if (1+EPS)=1EPS=EPS*2breakend end num = n -1,if语句可以嵌套使用,其结构形式为:if 表达式1语句1elseIf表达式2语句2elseif 表达式n语句nelse语句n+1endendend,if 表达式1语句1elseif 表达式2语句2elseif 表达式n语句nelse语句n+1end,试用for语句和if语句创建下列矩阵:,A= ; for
23、 k=1:5for j=1:5if k=jA(k,k)=5;elseif abs(k-j)=1A(k,j)=1;else A(k,j)=0;endend end A,2. switch语句,switch语句的一般结构是: switch 表达式case 表达式1语句1case 表达式2语句2 . . case 表达式n语句notherwise语句n+1 end,例6. 13 试用switch语句完成卷面成绩score的转换:(1)score 90分,优;(2)90score 80分,良;(3)80score 70分,中;(4)70score 60分,及格;(5)60score,不及格。,scor
24、e=input(请输入卷面成绩:score=);switch fix(score/10)case 9grade=优case 8grade=良case 7grade=中case 6grade=及格otherwisegrade=不及格end,3. try语句,try语句是MATLAB特有的语句,其一般结构是: try 语句1 catch 语句2 end 它先试探性地执行语句1,如果出错,则将错误信息存入系统保留变量lasterr中,然后再执行语句2;如果不出错,则转向执行end后面的语句。此语句可以提高程序的容错能力,增加编程的灵活性。,例6. 14 已知某图像文件名为pic,但不知其存储格式为.
25、bmp还是.jpg,试编程正确读取该图像文件。trypicture=imread(pic.bmp,bmp);filename=pic.bmp; catchpicture=imread(pic.jpg,jpg);filename=pic.jpg; end filename,6.2.3 程序流的控制,1. break语句 终止本层for或while循环,跳转到本层循环结束语句end的下一条语句。 2. return语句 终止被调用函数的运行,返回到调用函数。,3. pause语句 其调用格式有: (1)pause:暂停程序运行,按任意键继续; (2)pause(n):程序暂停运行n秒后继续; (3
26、)pause on/off:允许/禁止其后的程序暂停。 4. continue语句 在for循环或while循环中遇到该语句,将跳过其后的循环体语句,进行下一次循环,6.3.1 键盘输入语句(input),其调用格式有: (1)x = input(prompt):显示提示字符串prompt,要求用户键盘输入x的值; (2)x = input(prompt,s):显示提示字符串prompt,要求用户键盘输入字符型变量x的值,不至于将输入的数字看成是数值型数据。,6.3 数据的输入与输出,6.3.2 屏幕输出语句(disp),屏幕输出最简单的方法是直接写出欲输出的变量或数组名,后面不加分号(;)。
27、此外,可以采用disp语句,其调用格式有:disp(x)。,6.3.3 M数据文件的存储/加载,1. save语句 2. load语句,6.4 MATLAB文件操作,1. fopen语句,(1)fid = fopen(filename):以只读方式打开名为filename的二进制文件,如果文件可以正常打开,则获得一个文件句柄号fid;否则fid =-1。 (2)fid = fopen(filename,permission):以permission指定的方式打开名为filename的二进制文件或文本文件,如果文件可以正常打开,则获得一个文件句柄号fid(非0整数);否则fid =-1。,表6.2 参数permission的设置,2. fclose语句,(1)status = fclose(fid):关闭句柄号fid指定的文件。如果fid是已经打开的文件句柄号,成功关闭,status =0;否则status = -1。 (2)status = fclose(all):关闭所有文件(标准的输入、输出核错误信息文件除外)。成功关闭,status =0;否则status = -1。,