2009-06-02 20 views
6

No tengo idea de lo que está pasando aquí. Estoy usando R2006b. ¿Alguna posibilidad de que alguien con una versión más nueva pueda probar para ver si obtienen el mismo comportamiento, antes de que presente un informe de error?MATLAB "error" (o comportamiento realmente extraño) con estructuras y matrices de celdas vacías

código: (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 

de salida:

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

Parece que el vacío/nada de la S.something le permite cambiar los argumentos de una llamada de función. Esto parece muy mal comportamiento. En el corto plazo, quiero encontrar a mi alrededor (estoy intentando hacer una función que agregue elementos a una matriz de celdas inicialmente vacía que es miembro de una estructura).

Editar:

pregunta Corolario: lo que no hay manera de construir un struct que contienen las matrices de células vacías literales?

Respuesta

14

Como ya has descubierto, esto no es un error sino una "característica". En otras palabras, es el comportamiento normal de la función STRUCT.Si pasa matrices de celdas vacías como valores de campo a STRUCT, se supone que desea una matriz de estructura vacía con los nombres de campo dados.

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

s = 

0x0 struct array with fields: 
    a 
    b 

pasar una matriz celda vacía como un valor real del campo, que haría lo siguiente:

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

s = 

    a: {} 
    b: {} 

Por cierto, cualquier tiempo que desea establecer un valor de campo a un conjunto de celdas usando STRUCT requiere que lo abarques en otra matriz de celdas. Por ejemplo, esto crea un único elemento de estructura con campos que contienen una matriz de células y un vector:

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

s = 

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

Pero esto crea una matriz de dos elementos de la estructura, la distribución de la serie de células pero replicar el 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] 
+0

AH: gracias - No vi las notas en la función struct que hablan sobre el uso de llaves adicionales cuando quiera pasar una matriz de celdas. Grrr. –

1

de salida es idéntica en 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 
2

ARGH ... creo que he encontrado la respuesta. struct() tiene múltiples comportamientos, incluyendo:

Nota Si alguno de los campos de los valores es una matriz celda vacía {}, el software MATLAB crea un vacío estructura matriz en la que todos los campos son también vacía.

y aparentemente si pasa un miembro de una estructura 0x0 como argumento, es como un tipo de fantasma vacío que realmente no aparece en la lista de argumentos. (Que sigue siendo probablemente un error)

bug2.m:

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

caso de prueba:

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

Este comportamiento persiste en 2008b, y de hecho no es realmente un error (aunque i wouldn No digas que los diseñadores lo intentaron): Cuando ingresas en add_something (S, 'boing') y miras el primer argumento (digamos seleccionándolo y presionando F9), obtienes alguna salida relacionada con el vacío estructura S. Entra en add_something (S.something, 'test') y mira el primer argumento, y verás que de hecho se interpreta como 'prueba'.

La sintaxis struct.fieldname está diseñada para devolver un objeto de tipo 'lista separada por comas'. Las funciones en matlab están diseñadas para recibir un objeto de este tipo exacto: los nombres de los argumentos se dan a los valores en la lista, en el orden en que se pasan. En su caso, dado que el primer argumento es lista vacía, la lista separada por comas que recibe la función comienza realmente en el segundo valor que pasa, es decir, 'prueba'.

+0

En realidad, los diseñadores * sí * intentaron este comportamiento. La sintaxis para pasar argumentos a la función STRUCT está diseñada para que pueda crear una estructura que contenga matrices o una matriz de estructuras, dependiendo de su uso de la encapsulación de matriz de celdas de los argumentos de entrada. – gnovice

+0

También, el comportamiento de la lista separada por comas (CSL) también está previsto. Las listas de argumentos de entrada y salida están diseñadas como CSL, y las siguientes sintaxis crean un CSL: structureArray.fieldName, cellArray {:}. – gnovice

+0

Por supuesto, los dos comportamientos que describes son por diseño. Sin embargo, como acabamos de ver, una situación en la que varios argumentos se pasan a una función y uno en el medio es una CSL vacía, conlleva consecuencias de este diseño que son * seguras * de causar confusión. Tal escenario (me parece) justifica la atención del diseño por separado. Al menos, por ejemplo, generar una advertencia de tiempo de ejecución. –

Cuestiones relacionadas