昨晚看到的好东西,拿来分享
函数结构与参数传递(by simwe cwit)作者: 猎鹰发布日期: 2006-1-06 查看数: 166 出自: http://www.bylm.net
某个函数的子函数,可能具有复用性,而我又不想改变原来的函数,怎样才能调用这个子函数呢?那就是给每一个函数加一个壳。例如这个函数结构:
function varargout = test_function( varargin )
% ....................
if nargin == 0
% 创建界面。
% 即使不创建界面,也可以采用这种函数结构。
figurehandle = test_generatefigurecontent;
% 初始化函数,可以用于创建初始化数据。
test_initfiguecontent(figurehandle);
if nargout > 0
varargout{1} = figurehandle ;
end
elseif ischar( varargin{1} )
try
if nargout > 0
= feval( varargin{:} ) ;
else
feval( varargin{:} ) ;
end
catch
disp( lasterr ) ;
end
end
% -------------------------------------------------------------------------
function figurehandle = test_generatefigurecontent;
.....................................
handles = guihandles( figurehandle );
guidata( figurehandle, handles ) ;
% --------------------------------------------------
function test_initfiguecontent( h )
handles = guidata( h ) ;
DefaultData = test_GetDefaultData ;
........................................
% --------------------------------------------------
function DefaultData = test_GetDefaultData ;
DefaultData.ParaName = {'height'; 'width';} ;
DefaultData.ParaKanaName = {'高度'; '宽度';} ;
DefaultData.height = 20 ;
DefaultData.width= 5 ;
% --------------------------------------------------
function test_Uicontrol_Callback( h ) ;
handles = guidata( h ) ;
........................................
% return ;
-------------------------------------------------------------------------
如果你要得到test_function里面的默认数据,就可以在其他函数中使用如下调用方式就能够得到:
DefaultData = test_function( 'test_GetDefaultData' ) ;
程序会通过这个转换器进入子函数:
elseif ischar( varargin{1} )
try
if nargout > 0
= feval( varargin{:} ) ;
else
feval( varargin{:} ) ;
end
catch
disp( lasterr ) ;
end
end
===================================================================
cwit:
这种结构还便于传递参数,同时varargin,varargout的使用,便于定制不同的输入方式。曾经写了一个函数,可以支持3到8个输入参数,实现详细的输入参数定制。
关于参数传递
1. 尽量在内存中提取:方法有三种:① 采用function的varargin和varargout传送,② 存在handle的ApplicationData中,③保存在handles里面。当然还有其他方法。
2.存在硬盘上,采用save和load。
3.用全局变量,最次的办法,有时却是最好的办法。
关于nargin,nargout,varargin,varargout
nargin:输入参数的个数,主要用于两个方面:①判断输入参数的个数,如果输入参数个数不对,可以警告或其他处理;②根据参数个数的不同可以做不同的处理。如:
if nargin == 0
error;
elseif nargin == 1
…………
elseif nargin == 2
…………
else
warndlg( '……‘, ’‘,‘modal')
return ;
end
nargout:输出参数的个数,用法同上。
varargin:输入参数的总和,保存为cell结构。提取方式如下:
A = varargin{1} ;
B = varargin{2:end} ;
varargout 输出参数。见到的最常见的用法是:
if nargout > 0
varargout{1} =figurehandle ;
end
=======================================================================
cwit:
关于handles:
实际上这个handles是MATLAB中GUI编程中最常用的一个句柄管理变量。
handles的生成:handles = guihandles( figurehandle );将figure中所有对象中“Tag”属性有值的句柄的handle采集在一起。handles是结构名,每个“Tag”域名里保持此对象的句柄。
handles的保存:guidata( figurehandle, handles );handles将保存在figure对象的“ApplicationData”的一个域名里。
handles的使用:handles = guidata( h );其中为figure中任意一个对象的句柄。
handles.SpeechSourceGui可能是一个figure的句柄,“userdata”是一个对象的属性,可以在其中存取任何数据。但是我不怎么用它,一则它只能存一个变量;二则它无法存入变量的名字,很难区分。
====================================================================
cwit:
关于feval
feval,首先我们可以把它理解为一个函数转换器。执行到feval时,系统将首先寻找内部函数,如果没有找到,再尝试找外部函数。
feval也是一个函数封装器,在执行时它能够调用某个函数;但是在编译时,又可以不将这个函数编译到当前模块中。
feval还有一个很强大的功能,如果结合了这个函数结构,就可以在函数外部调用一个函数的内部函数或子函数
===================================================================
cwit:
关于setappdata,getappdata
setappdata,将数据保存在对象的“ApplicationData”属性中。
getappdata,从对象的“ApplicationData”属性中提取数据,如果没有定义,就为空。
setappdata和getappdata操作的对象,最好为figure_handle,便于管理和扩展。
Matlab的高级编程和对象控制,将大量使用这两个函数
====================================================================
nostalgica:
受教了。
不过要调用一个函数的子函数,可以设法得到子函数的句柄。
不过程序执行时是看不到其他函数子函数的。这就要在主程序运行之前把要用的子函数“注册”一下,就像这样
function func1
k=@aa;
save subfunction k
%own codes
function aa
a=1
这样就把aa的句柄存了下了,当然也能存到GUI里。
然后load subfunction;feval(k)
不过感觉这样用似乎不大方便,因为其他函数要在此函数调用之前就想调用它的子函数便不可行了。是否可以设置一个programmestarted的标识,在所有函数调用之前把它们都执行一下,注册其子函数
if programmestarted==0
k=@aa;
save subfunction k
return
end
不过这样又增加了不少无谓的代码。
=======================================================================
cwit:
关于function_handle
function_handle在matlab环境下还是可以用的,但是不能支持编译,也就是说无法脱离matlab环境安全运行。在构建程序时,一定要考虑到扩展性,有些在某些条件下属于技术缺陷的方法,尽量不要用
====================================================================
snow_man_0:
"就是某个函数的子函数,可能具有复用性,而我又不想改变原来的函数,怎样才能调用这个子函数呢?"
我的办法是将子函数升级,函数多加了一个参数action
function fun(varargin,action)
switch action
case 'fun1'
case 'fun2'
end
另外,handles = guihandles( figurehandle );
这个函数要谨用,
1、由于其中用的是for循环,界面上的对象多了后会影响运行速度;
2、由于使用结构体,不支持中文'tag'。
建议还是使用内置函数findobj
=====================================================================
nostalgica:
fucntionhandel,feval,eval在R13中不支持编译。在R14中呢是否可以了呢。?
===================================================================
cwit:
R14的Compiler 4,应该不叫编译吧。所以fcuntion_handle,eval这些问题不存在。
所以R14的路应该是另外一条道路,前面没有声明,我的理解主要是基于Matlab 6.1,这个版本的compiler比较好用。
关于try...catch...end
昨晚给他们做培训,for和if结构讲了一个小时,下次有时间整理一下。
在函数结构里面用到了try...catch...end结构,这个东西虽然保险,但还是尽量少用。因为它屏蔽了很多警告信息,无法很好的调试程序。
=================================================================
bzzz:
记得以前读
matlab混合编程那本书上当时谈到try...catch...end结构
说最正式的应该是每写一个功能(函数?),就要用try...catch把它包一次
不过这个很麻烦因而很多时候不需要(?)
忘了这段话是在讲matlab基础部分还是混编中提到,似乎是后者,介绍怎么用C
math library的时候
当时看过也没太注意-____-||| 感觉看得不是很懂,欢迎讨论!
页:
[1]