【问题标题】:MATLAB "bug" (or really weird behavior) with structs and empty cell arrays带有结构和空单元格数组的 MATLAB“错误”(或非常奇怪的行为)
【发布时间】:2009-06-02 13:30:21
【问题描述】:

我不知道这里发生了什么。我正在使用 R2006b。在我提交错误报告之前,是否有可能使用较新版本的人进行测试以查看他们是否获得相同的行为?

代码:(bug1.m)

function bug1
S = struct('nothing',{},'something',{});
add_something(S, 'boing');          % does what I expect
add_something(S.something,'test');  % weird behavior
end

function add_something(X,str)
    disp('X=');
    disp(X);
    disp('str=');
    disp(str);
end

输出:

>> bug1
X=
str=
boing
X=
test
str=
??? Input argument "str" is undefined.

Error in ==> bug1>add_something at 11
    disp(str);

Error in ==> bug1 at 4
add_something(S.something,'test');

看起来S.something 的空虚/虚无允许它转移函数调用的参数。这似乎是非常糟糕的行为。在短期内,我想绕过它(我正在尝试创建一个函数,将项目添加到最初为空的单元格数组中,该单元格数组是结构的成员)。

编辑:

推论问题:所以没有办法构造一个包含任何空元胞数组的 struct 文字?

【问题讨论】:

    标签: matlab cell-array matlab-struct


    【解决方案1】:

    正如您已经发现的那样,这不是错误,而是“功能”。换句话说,这是STRUCT 函数的正常行为。如果将空元胞数组作为字段值传递给 STRUCT,则假定您需要一个具有给定字段名称的空结构体数组。

    >> s=struct('a',{},'b',{})
    
    s = 
    
    0x0 struct array with fields:
        a
        b
    

    要将空元胞数组作为实际字段值传递,您可以执行以下操作:

    >> s = struct('a',{{}},'b',{{}})
    
    s = 
    
        a: {}
        b: {}
    

    顺便说一句,任何时候您想要使用 STRUCT 将字段值设置为元胞数组都需要将其包含在另一个元胞数组中。例如,这会创建一个结构元素,其字段包含一个元胞数组和一个向量:

    >> s = struct('strings',{{'hello','yes'}},'lengths',[5 3])
    
    s = 
    
        strings: {'hello'  'yes'}
        lengths: [5 3]
    

    但这会创建一个包含两个结构元素的数组,分布元胞数组但复制向量:

    >> s = struct('strings',{'hello','yes'},'lengths',[5 3])
    
    s = 
    
    1x2 struct array with fields:
        strings
        lengths
    
    >> s(1)
    
    ans = 
    
        strings: 'hello'
        lengths: [5 3]
    
    >> s(2)
    
    ans = 
    
        strings: 'yes'
        lengths: [5 3]
    

    【讨论】:

    • 啊:谢谢——我没有看到 struct 函数中的注释,即每当你想传入一个元胞数组时就使用额外的大括号。咕噜。
    【解决方案2】:

    啊……我想我找到了答案。 struct() 有多种行为,包括:

    注意如果任何值字段是 一个空元胞数组 {},MATLAB 软件创建一个空结构 数组,其中所有字段也是 空。

    显然,如果您将 0x0 结构的成员作为参数传递,它就像某种没有真正出现在参数列表中的空幻影。 (这仍然可能是一个错误)

    bug2.m:

    function bug2(arg1, arg2)
    disp(sprintf('number of arguments = %d\narg1 = ', nargin));
    disp(arg1);
    

    测试用例:

    >> nothing = struct('something',{})
    
    nothing = 
    
    0x0 struct array with fields:
        something
    
    >> bug2(nothing,'there')
    number of arguments = 2
    arg1 = 
    >> bug2(nothing.something,'there')
    number of arguments = 1
    arg1 = 
    there
    

    【讨论】:

      【解决方案3】:

      这种行为在 2008b 中仍然存在,实际上并不是真正的错误(尽管我不会说设计者打算这样做): 当你进入 add_something(S,'boing') 并观察第一个参数(比如选择它并按 F9),你会得到与空结构 S 相关的 some 输出。 进入 add_something(S.something,'test') 并观察第一个参数,你会发现它实际上被解释为 'test' !

      语法 struct.fieldname 旨在返回“逗号分隔列表”类型的对象。 matlab 中的函数旨在接收这种确切类型的对象:参数名称按照传递的顺序赋予列表中的值。在您的情况下,由于第一个参数是 空列表,因此函数接收的逗号分隔列表实际上从您传递的第二个值开始 - 即“测试”。

      【讨论】:

      • 实际上,设计者确实打算这样做。将参数传递给 STRUCT 函数的语法旨在让您可以创建包含数组的结构或结构数组,具体取决于您对输入参数的元胞数组封装的使用。
      • 此外,逗号分隔列表 (CSL) 行为也是预期的。输入和输出参数列表设计为 CSL,以下语法创建 CSL:structureArray.fieldName、cellArray{:}。
      • 当然,您描述的两种行为都是设计使然。然而,正如刚才看到的 - 将多个参数传递给一个函数而中间的一个是空 CSL 的情况,会导致这种设计的结果肯定会引起混淆。这种情况(在我看来)证明了单独的设计关注。至少,比如说,提出一个运行时警告。
      【解决方案4】:

      R2008b 中的输出相同:

      >> bug1
      X=
      str=
      boing
      X=
      test
      str=
      ??? Input argument "str" is undefined.
      
      Error in ==> bug1>add_something at 11
          disp(str);
      
      Error in ==> bug1 at 4
      add_something(S.something,'test');  % weird behavior
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-04
        • 2013-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多