要调试我的Octave / MATLAB代码,我希望能够执行以下操作:
A = magic(3);
b = 42;
describe(@A, @b);
并获得如下输出:
filename.m line 3: "A" is a 3x3 matrix
filename.m line 3: "b" is a scalar of value: 42
对于多个变量,我该如何打印:
答案 0 :(得分:5)
在这个答案中,我列出了3个不同版本的函数describe
。
fpritnf
disp
describe('myvar{1}')
这样的索引。您可以使用各种标准功能获取所需信息:
varargin
接受可变数量的输入变量dbstack
获取文件名/当前行inputname
获取传入describe
fprintf
以新行字符显示varargout
可选择返回或显示结果所以像这样创建你的describe
函数:
function varargout = describe(varargin)
% varargin used to accomodate variable number of inputs
% By default, at least get functions stack (even if no variables are passed in)
st = dbstack;
% Convert cell output to string (excluding describe.m itself)
outstring = '';
% Loop backwards for more logical order (most recent last)
for ii = size(st, 1):-1:2
% new line character at end only works with fprintf, not disp
outstring = [outstring, st(ii).file, ' > ', st(ii).name, ...
', line ', num2str(st(ii).line), '\n'];
end
% Loop over variables and get info
for n = 1:nargin
% Use inputname to get name of input variables
outstring = [outstring, '"', inputname(n), '" is a ', ...
class(varargin{n}), ' of size ', mat2str(size(varargin{n})), '\n'];
end
% If output variable is requested then assign to output variable
% If not, just display output string to command window
if nargout
varargout{1} = outstring;
else
fprintf(outstring)
end
end
这里唯一需要的调整就是格式化,所有您要求的功能都在这里,希望有足够的灵活性来满足您的需求。
示例输出:
% In myMainFunction.m, in the subfunction mySubFunction
% Could store output using 'd = describe(A,B);' and use 'fprintf' later
describe(A, B);
% In the command window
myMainFunction.m > myMainFunction, line 3
myMainFunction.m > mySubFunction, line 39
"A" is a double of size [1 3]
"B" is a double of size [1 5 9 7]
在Matlab R2015b中测试过,上面列出的所有函数都是在R2006a之前根据文档存在的,因此我假设它们可能具有Octave等价物。
单元格而不是带行分隔符的字符串。
这有一个不太漂亮的输出,但也可能是一个不太笨重的方法,将字符串分配给单元格数组,而不是依赖fprintf
新行。可以使用以下(简称未注释)版本轻松完成。
function varargout = describe(varargin)
st = dbstack; outcell = {};
for ii = size(st, 1):-1:2
outcell{end+1} = [st(ii).file, ' > ', st(ii).name, ', line ', num2str(st(ii).line)];
end
for n = 1:nargin
outcell{end+1} = ['"', inputname(n), '" is a ', class(varargin{n}), ' of size [', size(varargin{n}), ']'];
end
outcell = outcell.'; % Transpose to make it a column cell array
disp(outcell)
end
将变量名称作为字符串传递,因此会显示'myvar(1)'
之类的内容。
这使用evalin
来评估caller
工作空间(调用describe
的位置)中的变量。注意:当您在此describe
函数中重新创建变量以获取其属性时,这可能会占用大量内存。
function varargout = describe(varargin)
% varargin used to accomodate variable number of input names
st = dbstack;
outstring = '';
for ii = size(st, 1):-1:2
outstring = [outstring, st(ii).file, ' > ', st(ii).name, ', line ', num2str(st(ii).line), '\n'];
end
% Loop over variables and get info
for n = 1:nargin
% Variables are passed by name, so check if they exist
try v = evalin('caller', varargin{n});
outstring = [outstring, '"', varargin{n}, '" is a ', class(v), ' of size ', mat2str(size(v)), '\n'];
catch
outstring = [outstring, 'Variable "', varargin{n}, '" not found!\n'];
end
end
fprintf(outstring)
end
使用示例:
% This can be used with indexed variables too. MUST PASS STRINGS!
describe('C{1}', 'B(1:2, :)')
% In the command window
myMainFunction.m > myMainFunction, line 3
myMainFunction.m > mySubFunction, line 39
"C{1}" is a double of size [1 3]
"B(1:2, :)" is a double of size [2 5]
% Because you're passing strings, you can use command syntax if you want
% Gives same result but don't have to pass strings
% as that's how inputs are interpreted anyway for command syntax.
describe C{1} B(1:2, :)
答案 1 :(得分:1)
我自己使用类似的东西。这是我的:
function describe(A)
fprintf(' Class : %s\n',class(A));
fprintf(' Num. Elems : %s\n',num2str(numel(A)));
fprintf(' Size : %s\n',num2str(size(A)));
fprintf(' Total Min : %s\n',num2str(min (A(:))));
fprintf(' Total Max : %s\n',num2str(max (A(:))));
fprintf(' Total Sum : %s\n',num2str(sum (A(:))));
fprintf(' Total Mean : %s\n',num2str(mean(A(:))));
fprintf('Total St.Dev : %s\n',num2str(std (A(:), 1)));
fprintf(' Unique vals : %s\n',num2str(length(unique(A))));
end
编辑:我知道这并不是您要求的字面答案,但我一直都在使用它,并认为分享可能会有用。 :)
<子> PS。话虽如此,我从未想过我可能想要以非交互方式使用这样的函数:如果我需要以这种方式检查变量,我只需要设置一个断点(或keyboard
指令)在代码中,然后检查终端中与其最相关的位置的内容,因此我手动报告文件名和亚麻布!您需要执行这样的非交互式调试的用例是什么?如果它用于验尸&#34;测试&#34;无论如何,你真的应该写出正确的测试和健全性检查!
此外,这仅适用于单个变量,但我发现这更好;如果你想要更多,它是一个非常简单的单行循环。
答案 2 :(得分:0)
您可以使用size
来获取变量的大小,类型使用class
,名称使用inputname
。
例如:
function describe(a)
s = size(a); % Return the size of a
t = class(a); % Return the type of a
name = inputname(1); % Return the name of a
printf(['filename.m line 3: ''''' name ''''' size:' s(1) 'x' s(2) ' and type: ' t]);
end
我不知道如何使用文件名和行,如果你想用另一种方式显示它,你可以使用if条件从矩阵中的向量中分离标量。