Matlab如何编写一个输入参数数目不确定的函数
背景
在绘制一个负荷功率平衡柱状图的时候,使用到了bar,plot等一些函数绘图,但是总是需要重新复制粘贴一些代码,代码显得比较繁杂,不简洁美观,故想要调用函数来批量绘制图片,但是一般函数定义的格式为
function [C,D] = myfunction(a,b)
C=a+b;
D=a-b;
end
但是如果参数需要多增加至4个?
function [C,D] = myfunction(a,b,c,d)
C=a+b+c+d;
D=a-b-c-d;
end
显得非常不方便,需要重新去定义一个函数,那么有没有一种方法可以随意输入任意数目的参数?有人可能想到了传入一个cell,这个cell包含了所有你想要输入的参数,传入进入函数再进行分解。当然可以,但是这样的操作就必须在主函数中把相关数据转化为一个cell并进行拼接,比较麻烦,那么有没有一种方法让函数按照一定的逻辑去识别处理对应的内容呢?
解决方法:
方法肯定是有的,类似于plot
函数可以输入很多"组"参数
plot(X1,Y1,…,Xn,Yn)
而varargin
则可以代替X1,Y1,…Xn,Yn这一些列的输入参数
根据matlab官方手册
varargin
是函数定义语句中的一个输入变量,允许函数接受任意数量的输入参数。使用小写字符指定varargin
。在任何显式声明的输入项后,附加varargin
作为最后一个输入参数。在执行函数时,
varargin
是一个1×N 元胞数组,其中 N 是函数在显式声明的输入后收到的输入项数。如果该函数在显式声明的输入后未收到任何输入,则varargin
是空元胞数组。
简单的来说就是如果你将函数如下设置:
function [C,D] = myfunction(varargin)
C = size(varargin,2);
D = size(varargin,1);
end
输入:
[C,D]=myfunction([1,2,3],'Hello',{3.1415},true)
输出:
C =
4
D =
1
如果我们进入到函数中去打一个断点可以发现
上面这个例子说明你随心所欲输入的四个参数被打包成了一个
1
×
4
1\times4
1×4的 cell
传入函数中,那么我们可以通过对varargin
进行引用从而处理传入的参数
nargin的意义与使用注意事项
根据官方文档说明:
nargin
针对当前正在执行的函数,返回函数调用中给定函数输入参数的数目。该语法仅可在函数体内使用。
可以理解为nargin
这个变量保存了系统输入参数的个数
在这里我使用 size(varargin,2)
函数去获取了对应的参数的数目,那么是否和系统预设变量nargin
一致呢?
我们这里更新一下代码:
function [C,D] = myfunction(arg1,arg2,varargin)
C = size(varargin,2);
D = nargin;
varargin
E = arg1;
F = arg2;
end
结果如下:
>> [C,D]=myfunction([1,2,3],'Hello',{3.1415},true)
varargin =
1×2 cell 数组
{1×1 cell} {[1]}
C =
2
D =
4
比较可以发现:第二个代码中的arg1,arg2占用了部分的位置,使得varargin
中只有两个数据使得数据变少了。
因此我们可以得出结论:
如果函数输入只有
varargin
例如:myfunction(varargin)
则
size(varargin,2)
与nargin
是等效的
如果函数输入还有其他的接受参数例如:
myfunction(arg1,agr2,varargin)
则
size(varargin,2)
代表varargin所代表的输入参数的数目
nargin
代表算上arg1,arg2以后总的输入参数的数目
示例
绘制一个功率平衡图:
示例代码:
function bf = plotBalanceFigure(varargin)
%输入格式:(data1,'+','lengend name1',...,dataN,'+','lengend nameN')
%'+'表示将在上方,'-'表示将陈列在下方
%返回数据:figure对象
%检查输入格式是否完整
if rem(nargin,3) ~= 0
warning('参数格式错误');
return ;
end
upnum = 0;
downnum = 0;
legend_text={};
%数据处理
for i=1:nargin
if rem(i,3) ==1
if strcmp(varargin{i+1},'+')
upnum = upnum+1;
balance_energy(:,upnum) = varargin{i};
elseif strcmp(varargin{i+1},'-')
downnum = downnum +1;
balance_load(:,downnum) = varargin{i};
else
warning('参数+/-设置错误');
return;
end
elseif rem(i,3) == 0
legend_text{floor(i/3)} = varargin{i};
end
end
bf = figure;
b1=bar(balance_energy,"stacked",'EdgeColor',[153,153,153]./255);
maxdata =max(sum(balance_energy,2));
ylim([-1.2*maxdata,1.2*maxdata]);
hold on
b2=bar(-balance_load,"stacked",'EdgeColor',[153,153,153]./255);
title('负荷平衡功率条形图');
xlabel('时间');
ylabel('负荷功率(MW)');
set(gca, 'XTick', 1:length(varargin{1}), 'XTickLabels', 1:length(varargin{1}));
grid on;
legend(legend_text, 'Location', 'northwest');
end
调用函数格式:
plotBalanceFigure(...
sum(ThermalPower),'+','火电功率',...
sum(HydroPower),'+','水电功率',...
WindPower,'+','风电功率',...
SolarPower,'+','光伏功率',...
[power_load.Load],'-','负荷功率'...
)
得到绘制的图样式
当然上面的代码可能会有一些bug比如输入数据是行向量还是列向量的判断等等。