结构和空单元格数组的MATLAB“bug”(或非常奇怪的行为)

时间:2021-10-21 15:57:48

I have no idea what's going on here. I'm using R2006b. Any chance someone out there with a newer version could test to see if they get the same behavior, before I file a bug report?

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

code: (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

output:

>> 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');

It looks like the emptiness/nothingness of S.something allows it to shift the arguments for a function call. This seems like Very Bad Behavior. In the short term I want to find away around it (I'm trying to make a function that adds items to an initially empty cell array that's a member of a structure).

看起来S.something的空虚/虚无允许它移动函数调用的参数。这看起来像非常糟糕的行为。在短期内我想找到它周围(我正在尝试创建一个函数,将项添加到最初为空的单元格数组,该数组是结构的一部分)。

Edit:

Corollary question: so there's no way to construct a struct literal containing any empty cell arrays?

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

4 个解决方案

#1


As you already discovered yourself, this isn't a bug but a "feature". In other words, it is the normal behavior of the STRUCT function. If you pass empty cell arrays as field values to STRUCT, it assumes you want an empty structure array with the given field names.

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

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

s = 

0x0 struct array with fields:
    a
    b

To pass an empty cell array as an actual field value, you would do the following:

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

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

s = 

    a: {}
    b: {}

Incidentally, any time you want to set a field value to a cell array using STRUCT requires that you encompass it in another cell array. For example, this creates a single structure element with fields that contain a cell array and a vector:

顺便说一句,只要您想使用STRUCT将字段值设置为单元格数组,就需要将其包含在另一个单元格数组中。例如,这会创建一个单独的结构元素,其中的字段包含单元格数组和向量:

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

s = 

    strings: {'hello'  'yes'}
    lengths: [5 3]

But this creates an array of two structure elements, distributing the cell array but replicating the vector:

但是这会创建一个包含两个结构元素的数组,分配单元格数组但复制矢量:

>> 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]

#2


ARGH... I think I found the answer. struct() has multiple behaviors, including:

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

Note If any of the values fields is an empty cell array {}, the MATLAB software creates an empty structure array in which all fields are also empty.

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

and apparently if you pass a member of a 0x0 structure as an argument, it's like some kind of empty phantom that doesn't really show up in the argument list. (that's still probably a bug)

显然,如果你传递一个0x0结构的成员作为参数,它就像某种空幻像,并没有真正显示在参数列表中。 (那可能还是一个bug)

bug2.m:

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

test case:

>> 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


This behaviour persists in 2008b, and is in fact not really a bug (although i wouldn't say the designers intended for it): When you step into add_something(S,'boing') and watch the first argument (say by selecting it and pressing F9), you'd get some output relating to the empty structure S. Step into add_something(S.something,'test') and watch the first argument, and you'd see it's in fact interpreted as 'test' !

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

The syntax struct.fieldname is designed to return an object of type 'comma separated list'. Functions in matlab are designed to receive an object of this exact type: the argument names are given to the values in the list, in the order they are passed. In your case, since the first argument is an empty list, the comma-separated-list the function receives starts really at the second value you pass - namely, 'test'.

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

#4


Output is identical in R2008b:

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

#1


As you already discovered yourself, this isn't a bug but a "feature". In other words, it is the normal behavior of the STRUCT function. If you pass empty cell arrays as field values to STRUCT, it assumes you want an empty structure array with the given field names.

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

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

s = 

0x0 struct array with fields:
    a
    b

To pass an empty cell array as an actual field value, you would do the following:

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

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

s = 

    a: {}
    b: {}

Incidentally, any time you want to set a field value to a cell array using STRUCT requires that you encompass it in another cell array. For example, this creates a single structure element with fields that contain a cell array and a vector:

顺便说一句,只要您想使用STRUCT将字段值设置为单元格数组,就需要将其包含在另一个单元格数组中。例如,这会创建一个单独的结构元素,其中的字段包含单元格数组和向量:

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

s = 

    strings: {'hello'  'yes'}
    lengths: [5 3]

But this creates an array of two structure elements, distributing the cell array but replicating the vector:

但是这会创建一个包含两个结构元素的数组,分配单元格数组但复制矢量:

>> 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]

#2


ARGH... I think I found the answer. struct() has multiple behaviors, including:

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

Note If any of the values fields is an empty cell array {}, the MATLAB software creates an empty structure array in which all fields are also empty.

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

and apparently if you pass a member of a 0x0 structure as an argument, it's like some kind of empty phantom that doesn't really show up in the argument list. (that's still probably a bug)

显然,如果你传递一个0x0结构的成员作为参数,它就像某种空幻像,并没有真正显示在参数列表中。 (那可能还是一个bug)

bug2.m:

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

test case:

>> 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


This behaviour persists in 2008b, and is in fact not really a bug (although i wouldn't say the designers intended for it): When you step into add_something(S,'boing') and watch the first argument (say by selecting it and pressing F9), you'd get some output relating to the empty structure S. Step into add_something(S.something,'test') and watch the first argument, and you'd see it's in fact interpreted as 'test' !

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

The syntax struct.fieldname is designed to return an object of type 'comma separated list'. Functions in matlab are designed to receive an object of this exact type: the argument names are given to the values in the list, in the order they are passed. In your case, since the first argument is an empty list, the comma-separated-list the function receives starts really at the second value you pass - namely, 'test'.

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

#4


Output is identical in R2008b:

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