1、第8章MATLAB高级应用8.1 MATLAB应用接口8.1.1 MEX文件MEX文件具有以下几个方面的应用:(1) 对于已存在的C或FORTRAN子程序,可以通过MEX文件在MATLAB环境中直接调用,而不必重新编写M文件。(2) 由于MATLAB是解释性语言,运行如for等循环体时,会出现速度十分缓慢的现象,为了能提高速度,往往要使用MEX程序。(3) 对于A/D、D/A卡,或其它PC硬件,可以直接用MEX文件进行访问。(4) 利用MEX文件,可以使用如Windows用户图形界面等资源。1. MEX文件系统设置下面采用Microsoft Visual C/C+ 6.0编译器,在命令窗口使用
2、“mex -setup”命令,对MEX文件编译器进行配置: mex -setup则会出现如下提示:Please choose your compiler for building external interface (MEX) files: Would you like mex to locate installed compilers y/n? y让用户选择是否同意mex命令自动定位已经安装的编译器,输入“y”后,回车出现如下提示:Select a compiler: 1 Digital Visual Fortran version 6.0 in C:Program FilesMicros
3、oft Visual Studio 2 Lcc C version 2.4 in D:MATLAB6P1syslcc 3 Microsoft Visual C/C+ version 6.0 in D:Program FilesMicrosoft Visual Studio 0 None 提供用户选择编译器作为默认的MEX文件编译器,通过键盘输入“3”后,回车出现如下提示: Please verify your choices: Compiler: Microsoft Visual C/C+ 6.0 Location: D:Program FilesMicrosoft Visual Studio
4、 Are these correct?(y/n): 确认所选择的编译器,通过键盘输入“y”后,回车出现如下提示:The default options file: D:Documents and SettingsZJDCYApplication DataMathWorksMATLABR12mexopts.bat is being updated from D:MATLAB6P1BINWIN32mexoptsmsvc60opts.bat. Installing the MATLAB Visual Studio add-in . Updated D:Program FilesMicrosoft V
5、isual Studiocommonmsdev98templateMATLABWizard.awx from D:MATLAB6P1BINWIN32MATLABWizard.awx Updated D:Program FilesMicrosoft Visual Studiocommonmsdev98templateMATLABWizard.hlp from D:MATLAB6P1BINWIN32MATLABWizard.hlp Updated D:Program FilesMicrosoft Visual Studiocommonmsdev98addinsMATLABAddin.dll fro
6、m D:MATLAB6P1BINWIN32MATLABAddin.dll Merged D:MATLAB6P1BINWIN32usertype.dat with D:Program FilesMicrosoft Visual Studiocommonmsdev98binusertype.dat 则表示编译器成功配置。2. 测试配置在MATLAB环境的当前目录浏览器窗口中,将MATLAB的externexamplesmex目录设置为当前目录,然后在命令窗口中输入: mex yprime.c 则在externexamplesmex目录下,就生成了“yprime.dll”文件,查看该yprime.d
7、ll文件的信息,在命令窗口中输入: which yprimeD:MATLAB6p1externexamplesmexyprime.dll并调用yprime.dll文件: yprime(1,1:2:7)ans = 3.0000 14.9925 7.0000 -1.03773. C语言MEX文件的构成程序的构成主要由入口子程序和计算功能子程序两部分组成。(1) 入口子程序第一部分入口子程序的作用是在MATLAB系统与被调用的外部子程序之间建立通信联系。入口子程序必须是mexFunction,其构成形式为:void mexFunction( int nlhs, mxArray *plhs, int
8、nrhs, const mxArray*prhs ) /*用来完成MATLAB与计算子程序之间通信任务的代码*/mexFunction函数的参数含义为: nrhs:为输入参数的数目。 prhs:为输入参数数组,是指针数组。 nlhs:为输出参数的数目。 plhs:为输出参数数组,是指针数组。(2) 计算功能子程序第二部分为计算功能子程序,包含所有的实际需要完成的功能源代码,可以是用户以前所编写的算法和程序,以函数的形式存在。4. C语言MEX文件的建立(1) 常用MATLAB API函数在MEX文件中,常用MATLAB API函数有: mxGetM:获得矩阵的行数。 mxGetN:获得矩阵的列
9、数。 mxGetPr:获得矩阵的实数部分的数据指针。 mexErrMsgTxt:输出错误信息,并返回到MATLAB命令提示符下。 mxCreateString:创建一个字符串矩阵。 mxCreateDoubleMatrix:创建一个二维未赋值的双精度浮点类型的矩阵。 mxIsDouble:判断矩阵是否为双精度类型。(2) C语言MEX文件的创建步骤通过创建计算一个数平方倒数值的程序,来介绍一个MEX文件创建的过程。【例8.1】在Microsoft Visual C+6.0环境下创建一个MEX文件,实现计算一个数平方的倒数值。 在Microsoft Visual C+6.0环境创建一个“C+ S
10、ource File”文件,文件名为“Ex0801.cpp”。 编写该文件的程序代码如下:#include mex.h#include math.h/*计算功能子程序Ex0801,计算平方的倒数*/void Ex0801(double y,double x)y0=1/(x0*x0);return;/*入口子程序mexFunction*/void mexFunction(int nlhs,mxArray *plhs,int nrhs,const mxArray *prhs)double *x,*y;unsigned int m,n;/*检查输入变量的个数是否正确*/if(nrhs!=1)mexE
11、rrMsgTxt(Only one input argument allowed.);/*检查输出变量的个数是否正确*/else if(nlhs!=1)mexErrMsgTxt(Only one output argument allowed.); m = mxGetM(prhs0); n = mxGetN(prhs0);/*检查输入变量必须是非复数单个双精度数*/if (!mxIsDouble(prhs0) | mxIsSparse(prhs0) |mxIsComplex(prhs0)|! (m=1&n=1) mexErrMsgTxt(Input argument must be a sca
12、lar.);/*创建矩阵变量为输出变量*/plhs0=mxCreateDoubleMatrix(m,n,mxREAL);y = mxGetPr(plhs0); x = mxGetPr(prhs0); /*调用计算功能子程序*/Ex0801(y,x); 在MATLAB命令窗口的当前目录浏览器中将当前目录设置为用户的目录,输入命令创建MEX文件并运行: mex Ex0801.cpp y=Ex0801(2)y = 0.2500扩展名为cpp是C+文件,在其同一文件夹中生成Ex0801.dll文件,运行Ex0801.dll文件的运算结果正确。 为该文件添加帮助M文件为了在MATLAB中可以方便地查看该
13、Ex0801.dll文件的帮助信息,可以建立一个Ex0801.M文件,并输入以下内容:%function y=Ex0801(x)%计算一个数平方的倒数值% y=1/(x2)% copyright 2003-10-10则在MATLAB命令窗口中,用help命令只能看到M文件来查看帮助信息: help Ex0801 function y=Ex0801(x) 计算一个数平方的倒数值 y=1/(x2) copyright 2003-10-108.1.2 使用MATLAB编译器生成MEX和EXE文件1. MEX文件与EXE文件的区别MEX文件只能在MATLAB环境中运行;而EXE文件是可以独立与MATL
14、AB环境运行的。2. 配置编译器的准备图8.1 安装MATLAB对话框如果要创建MEX文件,如图8.1所示。则只需勾选“MATLAB Compiler”;如果要创建EXE文件,则需要勾选如图中的三个选项。3. 由M文件创建C MEX文件利用MATLAB编译器来由M文件创建MEX文件,使用“mcc x”命令,。【例8.2】在MATLAB环境中创建一个M函数文件,用来绘制正弦信号波形。在MATLAB的编辑/调试窗口中创建一个Ex0802.m函数文件,编写程序代码如下:function Ex0802% Ex0802 绘制正弦信号波形x=0:0.1:2*pi;y=sin(x);plot(x,y)保存文
15、件,在MATLAB命令窗口中由该M文件创建MEX文件: mcc -x Ex0802 %创建Ex0802.dll文件 Ex0802 %运行Ex0802.dll文件运行该Ex0802.dll文件,绘制出正弦信号波形图。在该目录下,可以看到在创建dll文件的同时,还创建了Ex0802.c、Ex0802.h和Ex0802_mex.c文件。注意:如果上述的Ex0802.m文件删除第一行,变为M脚本文件,则用mcc命令直接编译会出错,并出现如下提示: mcc -x Ex0802? Error: Cannot create MEX File Ex0802 from MEX File C:My Documen
16、tsCAOYiBookMATLAB20031008exeEx0802.dll.Error in = D:MATLAB6p1toolboxcompilermcc.dll4. 创建独立的外部程序EXE文件【例8.3】第一次使用mbuild命令由C文件创建EXE文件。由“matlabexternexamplescmath”目录下的现成文件“ex1.c”,创建独立的EXE文件。先将“matlabexternexamplescmath”目录设置为当前目录,然后输入mbuild命令,由于系统中安装了LCC和Microsoft Visual C/C+两个编译器,则MATLAB会提示用户选择默认的编译器: m
17、build ex1.cPlease choose your compiler for building standalone MATLAB applications: Would you like mbuild to locate installed compilers y/n? y 选择一个默认的编译器Select a compiler: 1 Lcc C version 2.4 in D:MATLAB6P1syslcc 2 Microsoft Visual C/C+ version 6.0 in D:Program FilesMicrosoft Visual Studio 0 None Co
18、mpiler: 2后面就会出现提示和确认的信息。如果要改变默认的编译器,则需要使用“mbuild -setup”命令重新选择。(1) mbuild命令由C文件生成EXE文件【例8.3续】用mbuild命令由C文件编译生成EXE文件。使用mbuild命令可以由“ex1.c”文件创建独立的可执行文件: mbuild ex1.c则产生了“ex1.exe”文件,可以脱离MATLAB独立运行,同时在同一目录下还产生了“bin”文件夹。(2) mcc命令由M文件生成EXE文件【例8.4】用mcc命令由【例8.2】中的M文件编译生成EXE文件。 mcc -B sglcpp Ex0802.m %创建需要图形库
19、的C+独立应用程序如果不希望MCC自动调用mbuild,可以添加使用“-c”选项,如命令“mcc -mc”和“mcc -pc”。8.2 低级文件的输入输出8.2.1打开和关闭文件1. 打开文件语法:fid = fopen(filename,permission) %以指定格式打开文件fid,message = fopen(filename,permission) %返回打开文件的信息说明:fid为返回的文件指针(File Identifier),通常是一个非负的整数,如果返回-1,则表示无法打开文件;message用来显示打开文件的信息,如果无法打开,则显示错误信息;filename为文件名,
20、是字符串,如果文件不在MATLAB的搜索路径中,则需要指定文件路径;permission为指定文件的打开模式,有以下几种模式: r:只读文件 r+:读写文件 w:删除已存在文件内容或建立新文件,并只写文件 w+:删除已存在文件内容或建立新文件,并读写文件 a:以只写方式建立并打开一个新文件或打开一个已存在的文件,只能在文件末尾添加内容 a+:以读写方式建立并打开一个新文件或打开一个已存在的文件,在文件末尾添加内容fopen的permission参数在打开文件时还可标明文件格式,如果打开文本格式文件,在后添加字母“t”,如果打开二进制格式文件,则在permission参数后添加字母“b”,如wb
21、、rb+等。2. 关闭文件打开文件进行读写操作后,应立即关闭文件,删除文件指针。语法:status=fclose(fid) %关闭文件指针所指的文件status=fclose(all) %关闭所有打开的文件说明:status为关闭文件指针所指文件的状态,如果成功则返回0,如果失败则返回-1;fid为所打开的文件指针。【例8.5】打开和关闭一个文本文件。文本文件“Ex0805.txt”,在MATLAB环境中显示的文件内容如下: type Ex0805.txt a 1 2 3 b 4 5 6使用fopen和fclose命令打开和关闭文件: fid,message=fopen(Ex0805.txt,
22、w+) %打开文件读写 fid = 3message = if fid=-1disp(无法打开该文件)elsedisp(成功打开该文件)end 成功打开该文件 status=fclose(fid) %关闭文件 status = 0 8.2.2读写格式化文件1. fscanf命令fscanf命令为读格式化文件数据。语法:a,count=fscanf(fid,format,size) %读取格式化数据说明:fid为文件指针,所指为需要读取的格式化文件;format指定读取数据格式,指定的格式必须和文件中的数据格式相同,否则读取的数据可能会出现错误,以“%”开头,有%c、%d、%e、%f、%g、%i
23、、%o、%s、%u、%x等(与C语言相同);count为成功读取的数据元素个数,可省略;a返回读取的数据;size为需要读取的数据个数,如果省略,则读到文件末尾,size的取值可以有: n:读n个数据到一个列向量 inf:读到文件末尾,数据放到一个列向量 m,n:读出的数据个数为mn,数据放到矩阵中,读出的数据按列的顺序填充矩阵,不够的数据用0填补。【例8.5续】读取Ex0805.txt文件的前四个字符。 fid=fopen(Ex0805.txt) fid = 3 a1=fscanf(fid,%s,4) %以字符串格式读取四个数据 a1 =a123 fclose(fid) ans = 0 2.
24、 fprintf命令fprintf命令为写格式化数据。语法:count=fprintf(fid,format,a,) %写入格式化数据说明:fid为文件指针,所指为二进制文件;a为矩阵数据,将a写到fid指向的文件;format为写入的格式,除了包含fscanf命令的数据格式之外,还有%E、%G、%X,并具有对齐格式-(左对齐)、+(右对齐)、0(补齐位数),还有转义字符;count为成功写入数据的个数。【例8.6】使用Ex0805.txt文件进行读取和写入数据。a=%This is a example.;fid=fopen(Ex0805.txt,a+) %打开Ex0803.txt文件在末尾添
25、加 fid = 3 fprintf(fid,%s,a) %写入a到文件末尾 ans = 19 fclose(fid) %关闭文件 ans = 0 fid=fopen(Ex0805.txt,r) %打开Ex0803.txt文件只读 fid = 3 fscanf(fid,%s) %读取文件所有内容 ans =a123b456%Thisisaexample.%Thisisaexample.%Thisisaexample.%Thisisaexample. fclose(fid) ans = 0 程序分析:在向文件中写入数据后,先关闭文件,然后再打开文件则从文件开头读取数据,如果写完数据后直接读取数据,
26、则实际读取数据的位置将从写入的最后一个数据之后开始。3. fgetl和fgets命令fgetl和fgets命令都是用来读取文件的下一行,两者的差别是fgetl会舍去换行符,而fgets则保留换行符。语法:tline=fgetl(fid) %读取文件的下一行,不包括换行符tline=fgets(fid) %读取文件的下一行,包括换行符tline=fgets(fid,nchar) %限制读取文件字符个数说明:fid为文件指针;tline为以字符串形式的返回值,如果到文件末尾则返回-1;nchar为最多返回的字符个数。【例8.6续】以行的形式读取Ex0805.txt文件。 fid=fopen(Ex0
27、805.txt,r) ; %打开Ex0803.txt文件只读 fgetl(fid) %读取第一行数据 ans =a 1 2 3 fgets(fid) %读取第二行数据 ans =b 4 5 6 fgets(fid,10) %读取第三行数据,限制10个字符 ans =%This is a fgets(fid,10) ans = example.% 8.2.3读写二进制数据fread命令为读二进制数据。语法:a,count=fread(fid,size,precision,skip) %读取二进制数据说明:fid为文件指针;size与fscanf命令含义相同;precision为一个字符串,用来指
28、定读取数据的精度,即数据类型,有uchar、schar、int8、int16、int32、int64、unit8、unit16、unit32、unit64、single、float32、double、float64等,可省略;a为矩阵数据;count为成功读取的数据元素个数,可省略;skip为每读取一个数据后跳过的字节数,可省略。2. 写数据fwrite命令为写二进制数据。语法:count=fwrite(fid,a,precision,skip) %写二进制数据说明:fid为文件指针;a为矩阵数据;precision和skip参数含义与fread命令相同;count为成功写入数据的个数。【例8
29、.7】写入数据到MAT文件中,并读取数据。 x1=1:10; fid,message=fopen(Ex0805.mat,a) %打开文件添加数据 fid = 4message = count1=fwrite(fid,x1) %写入数据 count1 = 10 x2=11:15; count2=fwrite(fid,x2) %添加数据 count2 = 5 status=fclose(fid); fid=fopen(Ex0805.mat,r); %打开文件只读 a1=fread(fid,2,5) %读取数据 a1 = 1 3 5 7 9 2 4 6 8 10 a2=fread(fid,1,5)
30、a2 = 1 2 3 4 5 fclose(fid); 8.2.4文件定位1. fseek命令fseek命令用来移动文件位置指针。语法:status=fseek(fid,offset,origin) %移动文件位置指针说明:fid为文件指针;offset指定移动的字节数,如果offset 0,则向后移动,否则向前移动,等于0则不移动;status为返回值,如果移动成功则返回0,否则返回-1;origin指定移动位置指针的参考起点: bof 或-1:文件的开头 cof 或0:文件的当前位置 eof 或1:文件的末尾。2. ftell命令ftell命令是用来获取文件位置指针的当前位置。语法:pos
31、=ftell(fid) %获取当前指针位置说明:pos指字节数,当前位置指针指在此字节数之后。3. frewind命令frewind命令用来将文件位置指针移到文件的开头。语法:frewind(fid)4. feof命令feof命令用来测试位置指针是否在文件结束位置,如果是则返回1,否则返回0。语法:feof(fid)【例8.8】创建两个mat文件,在Ex0808_1.mat文件中写入110的数据,并进行求和,在Ex0808_2.mat文件中写入1、2、3三个数据,将第二个数据与前面所求的和进行相乘运算。程序保存在Ex0808.m文件中,程序代码如下:% Ex0808 文件读取和定位 x=1:1
32、0;s=0;fid1=fopen(Ex0808_1.mat,w+) %打开文件读写数据fwrite(fid1,x); %写入数据frewind(fid1); %指针移到文件开头while feof(fid1)=0 %判断是否到文件末尾a1=fread(fid1,1) %读取数据 if isempty(a1)=0 %判断是否为空值 s=a1+s %求和 endendfclose(fid1);y=1 2 3;fid2=fopen(Ex0808_2.mat,w+) %打开文件读写数据fwrite(fid2,y) %写入数据fseek(fid2,-2,eof) %指针移动到第二个数据a2=fread(
33、fid2,1) %读取数据s=s*a2fclose(fid2);运行结果得出:s = 110程序说明: 使用文件位置控制就可以不用反复打开和关闭文件,而直接从文件中读写数据。 使用while循环结构,从文件中读取数据,直到文件末尾。 当文件位置指针移动到文件最后时,取出的数据为空值,但feof函数返回0,因此用isempty函数判断是否为空值来判断是否到文件最后,文件指针再向下移则到文件末尾,feof函数返回1。 “fseek(fid2,-2,eof)”语句是将文件位置指针从末尾向前2个数据。8.3 图形文件的转储图8.2 “Export”对话框MATLAB生成的图形文件为.fig文件格式,有
34、时需要将图形文件转储为多种常用的标准格式,如tif、bmp、jpg等。选择菜单“File”“Export”命令,则在出现的“Export”对话框中,在“保存类型”栏选择需要转储的图形文件类型,如图8.2所示。8.4 Notebook8.4.1 Notebook的安装MATLAB 6.5的Notebook安装步骤如下:(1) 启动MATLAB,出现MATLAB命令窗口。(2) 在命令窗口中运行“notebook -setup”命令出现如下提示: notebook -setupWelcome to the utility for setting up the MATLAB Notebookfor
35、interfacing MATLAB to Microsoft WordChoose your version of Microsoft Word:1 Microsoft Word 972 Microsoft Word 20003 Microsoft Word 2002 (XP)4 Exit, making no changesMicrosoft Word Version: (3) 根据自己机器上所用Word的版本,在提示的冒号后填写数值,如“2”,并按回车键。则出现以下提示,表示Notebook安装结束。Notebook setup is complete.如果安装程序不能找到所需的文件,则
36、也会提示用户指定“winword.exe”和“normal.exe”文件的路径。8.4.2 Notebook的启动1. 创建M-book文件(1) 从Word中启动Notebook创建M-book文件的步骤如下:选择Word窗口的菜单“文件”“新建”,在出现的对话框中,选择“m-book.dot”图标,如图8.3所示的为Word2000的新建对话框,按“确定”按钮。当保存文件时,默认的文件名为“The MATLAB Notebook v1.doc”。图8.3 新建word文件对话框(2) 从MATLAB中启动Notebook在MATLAB命令窗口输入“notebook”命令,就可以启动Note
37、book。语法:notebook%打开一个新的M-book文档notebook FileName%打开已存在的M-book文件说明:FileName应包括文件的完整路径和文件名。例如,在命令窗口中打开已建立的M-book文件: notebook C:My DocumentsMyMbook0801.doc2. M-book的界面图8.4 Notebook菜单M-book的界面比普通的Word多一个“Notebook”菜单,Notebook菜单项如图8.4所示。其菜单项功能如表8.1所示。表8.1 Notebook菜单项功能表下拉菜单组合键功能Define Input CellAlt+I定义输入单
38、元Define AutoInit CellAlt+A定义自动初始化单元Define Calc ZoneAlt+Z定义计算区Undefine CellsAlt+U将单元转换为文本Purge Output CellsAlt+P清除输出单元Group CellsAlt+G定义单元组Ungroup CellsAlt+p将单元组转换为单个单元Hide/Show Cell MarkersAlt+C隐藏/显示单元标志Toggle Graph Output for cell为每个单元锁定图形输出Evaluate CellCtrl+Enter运行当前单元或单元组Evaluate Calc ZoneAlt+Ent
39、er运行当前计算区Evaluate M-bookAlt+M运行M-book中所有单元Evaluate LoopAlt+L循环运行单元Bring MATLAB to front将MATLAB置于屏幕之前Notebook OptionsAlt+O定义输出显示选项8.4.3 Notebook的使用Notebook定义了几种格式来表示MATLAB的函数和命令,包括AutoInit、Calc、Error、Input、Nograph、Output以及Word默认的格式。Notebook对常用各单元格式的默认设置见表8.2所示。表8.2 M-book各单元样式样式名含义字体Input输入单元10磅 (poi
40、nts)深绿色英文粗体Courier NewOutput输出单元(数据和字符)10磅(points)蓝色英文细体Courier NewAutoInit自动初始化单元10磅(points)深蓝色英文粗体Courier NewError出错提示10磅(points)深红色英文粗体Courier New1. 输入单元(1) 只创建不运行输入单元在英文状态下按普通的文本输入方式,输入MATLAB命令,可以是独立行或嵌在文本中,然后用光标选中,按组合键“Alt-D”,或选择菜单“Notebook”“Define Input Cell”,则所选中的文本形式命令就变成了输入单元。【例8.9】在M-book文
41、件中创建输入单元(用黑框表示M-book中的输入文本)。在文本中输入以下文字:利用:来生成向量,例如x=1:0.1:3; 用光标选中“x=1:0.1:3;”文字,并按组合键“Alt-D”,则创建了输入单元显示如下:利用:来生成向量,例如x=1:0.1:3; (2) 创建并同时运行输入单元在英文状态下按普通的文本输入方式,输入MATLAB命令,然后用光标选中,按组合键“Ctrl-Enter”,或选择菜单“Notebook”“Evaluate Cell”,则所选中的文本形式命令就会自动变成输入单元,并得出运算结果,即输出单元。【例8.9续】创建并运行输入单元。在文本中继续输入MATLAB命令:y=
42、sin(x)y=sin(x) y =Columns 1 through 7 0.8415 0.8912 0.9320 0.9636 0.9854 0.9975 0.9996Columns 8 through 14 0.9917 0.9738 0.9463 0.9093 0.8632 0.8085 0.7457Columns 15 through 21 0.6755 0.5985 0.5155 0.4274 0.3350 0.2392 0.1411 用光标选中“y=sin(x)”文字,并按组合键“Ctrl-Enter”,则创建并运行输入单元,显示如下:程序分析:其中的“x”的值来自MATLAB的工作空间,M-book文件和MATLAB命令窗口共享一个工作空间;如果在命令“y=sin(x)”后加分号,则不以输出单元显示运行结果。2. 自动初始化单元创建自动初始化单元的方法是先将文本形式的MATLAB命令或已存在的输入单元用光标选中,然后选择菜单“Notebook”“Define AutoInit Cell”,则选中的文本形式MATLAB命令就会自动变成AutoInit 格式。3. 单元组创建单元组的方法:(1) 将多行文本形式MATLAB命令用光标选中,然后选择菜单“Note