2009-06-02 7 views
6

ここで何が起こっているのか分かりません。私はR2006bを使用しています。私はバグレポートを提出する前に、新しいバージョンの誰かが同じ動作をするかどうかをテストすることができます。MATLAB構造体と空のセル配列を持つ "バグ"(または実際には奇妙な動作)

コード:(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リテラル含む任意の空のセル配列を構築する方法はありませんか?

答えて

14

あなた自身が既に発見したように、これはバグではなく「機能」です。つまり、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] 

をしかし、これはセルのアレイを配布2個の構造素子のアレイを作成しますが、ベクターを複製:

>> 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:ありがとうございました - セル配列を渡すときはいつも、余分な中カッコを使用することについて話しているstruct関数の注釈は表示されませんでした。 Grrr。 –

1

出力は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

なんてこった...私は答えを見つけたと思います。値フィールドのいずれかが空のセル配列{}、MATLAB ソフトウェアはすべてのフィールドも 空された空の構造 配列を作成 場合

注:struct()を含む複数の動作を有します。

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 
2

この動作は2008Bに固執し、本当に実際にはバグ(私はwouldnではないがありますあなたがadd_something(S、 'boing')に入って最初の引数を見ると(それを選択してF9を押すと)、の一部がの空に関連する出力になります構造S. add_something(S.something、 'test')に入って最初の引数を見ると、実際には 'test'と解釈されています。

構文struct.fieldnameは、 'カンマ区切りリスト'タイプのオブジェクトを返すように設計されています。 matlabの関数は、この正確な型のオブジェクトを受け取るように設計されています。引数名は、渡された順序でリストの値に渡されます。あなたのケースでは、最初の引数がの空リストであるため、関数が受け取るカンマ区切りリストは実際に渡す2番目の値、つまり 'test'から始まります。

+0

実際、デザイナー*はこの動作を意図していました。引数をSTRUCT関数に渡す構文は、入力引数のセル配列のカプセル化の用途に応じて、配列を含む構造体または構造体の配列のいずれかを作成できるように設計されています。 – gnovice

+0

また、コンマ区切りリスト(CSL)の動作も同様に意図されています。入力引数と出力引数のリストはCSLとして設計されており、次の構文ではCSL:structureArray.fieldName、cellArray {:}を作成します。 – gnovice

+0

もちろん、あなたが説明する両方の動作は設計によるものです。しかし、今見たように、いくつかの引数が関数に渡され、真ん中に空のCSLがある状況では、この設計の結果が混乱の原因になります。このようなシナリオは(私にとっては)別々のデザインの注意を正当化します。少なくとも、ランタイム警告を発する。 –

関連する問題