2009-06-02 9 views
6

Ich habe keine Ahnung, was hier vor sich geht. Ich benutze R2006b. Gibt es eine Chance, dass jemand mit einer neueren Version testen könnte, ob sie das gleiche Verhalten haben, bevor ich einen Fehlerbericht einreiche?MATLAB "Bug" (oder wirklich seltsames Verhalten) mit Strukturen und leeren Zellenarrays

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 

Ausgang:

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

Es sieht aus wie die Leere/Nichts von S.something es erlaubt, die Argumente für einen Funktionsaufruf zu verschieben. Das scheint sehr schlechtes Verhalten zu sein. Kurzfristig möchte ich etwas um mich herum finden (ich versuche eine Funktion zu machen, die Elemente zu einem anfänglich leeren Zellenfeld hinzufügt, das ein Mitglied einer Struktur ist).

Edit:

Corollary Frage: so gibt es keine Möglichkeit, eine struct wörtliche enthält alle leeren Zellen-Arrays zu konstruieren?

Antwort

14

Wie Sie bereits selbst entdeckt haben, ist dies kein Bug, sondern ein "Feature". Mit anderen Worten, es ist das normale Verhalten der STRUCT-Funktion.Wenn Sie leere Zellenarrays als Feldwerte an STRUCT übergeben, wird davon ausgegangen, dass Sie ein leeres Strukturarray mit den angegebenen Feldnamen wünschen.

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

s = 

0x0 struct array with fields: 
    a 
    b 

Um eine leere Zellen-Array als ein tatsächliches Feld Wert übergeben, können Sie das folgende tun würde:

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

s = 

    a: {} 
    b: {} 

übrigens jede Mal, wenn Sie einen Feldwert zu einem Zellenfeld festlegen möchten, verwenden STRUCT erfordert, dass Sie es in einem anderen Zellenarray einschließen. Zum Beispiel entsteht ein einziges Strukturelement mit Feldern, die eine Zellenmatrix und einen Vektor enthalten:

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

s = 

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

aber dies erzeugt eine Anordnung von zwei Strukturelementen, die Zellenmatrix zu verteilen, aber replizierende den Vektor:

>> 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: danke - Ich habe die Notizen in der Strukturfunktion nicht gesehen, die über die Verwendung zusätzlicher Klammern sprechen, wenn Sie ein Zellenfeld übergeben möchten. Grrr. –

1

Ausgang ist identisch in 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 ... Ich denke, dass ich die Antwort gefunden. struct() hat mehrere Verhaltensweisen, zB:

Hinweis Wenn einer der Werte Felder eine leere Zelle Array {}, die MATLAB Software erstellt eine leere Struktur Array, in dem alle Felder sind auch leer. Wenn Sie ein Element einer 0x0-Struktur als Argument übergeben, ist es wie eine Art leeres Phantom, das nicht wirklich in der Argumentliste erscheint.

(Das ist immer noch wahrscheinlich ein Fehler)

bug2.m:

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

Testfall:

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

Dieses Verhalten bleibt in 2008b, und ist in der Tat nicht wirklich ein Bug (obwohl ich wouldn Wenn Sie in add_something (S, 'boing') treten und das erste Argument beobachten (sagen Sie, indem Sie es auswählen und F9 drücken), erhalten Sie einige Ausgabe bezogen auf die leere Struktur S. Schritt in add_something (Something, 'test') und beobachten Sie das erste Argument, und Sie würden sehen, es wird in der Tat als 'Test' interpretiert!

Die Syntax struct.fieldname soll ein Objekt vom Typ 'durch Komma getrennte Liste' zurückgeben. Funktionen in Matlab sind dazu bestimmt, ein Objekt dieses genauen Typs zu erhalten: Die Argumentnamen werden den Werten in der Liste in der Reihenfolge gegeben, in der sie übergeben werden. In Ihrem Fall, da das erste Argument eine leere Liste ist, beginnt die kommaseparierte Liste, die die Funktion empfängt, wirklich beim zweiten übergebenen Wert - nämlich "test".

+0

Eigentlich haben die Designer * für dieses Verhalten * beabsichtigt. Die Syntax zum Übergeben von Argumenten an die STRUCT-Funktion ist so konzipiert, dass Sie abhängig von der Verwendung der Zellenarray-Kapselung der Eingabeargumente entweder eine Struktur mit Arrays oder ein Array mit Strukturen erstellen können. – gnovice

+0

Das CSV-Verhalten (Comma-Separated List) ist ebenfalls vorgesehen. Eingabe- und Ausgabeargumentlisten sind als CSLs konzipiert, und die folgenden Syntaxen erstellen eine CSL: structureArray.fieldName, cellArray {:}. – gnovice

+0

Natürlich sind beide Verhaltensweisen, die Sie beschreiben, von Entwurf. Wie wir jedoch gerade gesehen haben - eine Situation, in der mehrere Argumente an eine Funktion übergeben werden und eine in der Mitte eine leere CSL ist, sind Konsequenzen dieses Entwurfs verbunden, die * sicher * Verwirrung stiften. Solch ein Szenario (scheint mir) rechtfertigt separate Design-Aufmerksamkeit. Zumindest, sagen wir mal, eine Laufzeitwarnung. –