ここに完全な解決策があります(@Marcが説明したものと同様です):
%# read lines
fid = fopen('file.txt','rt');
C = textscan(fid, '%s', 'Delimiter',''); C = C{1};
fclose(fid);
%# start/end of each structure
startIdx = find(ismember(C, 'struct'));
endIdx = find(ismember(C, 'endstruct'));
%# array of strucutres
N = numel(startIdx);
arr = struct('studentname','', 'notes','', 'n1',0, 'n2',0, 'average',0);
arr = repmat(arr,[N 1]);
%# parse and store each structure in the array
for i=1:numel(startIdx)
%# parse key/value of struct
s = C(startIdx(i)+1:endIdx(i)-1);
s = regexp(s, '(\w+)\s*[:=]\s*([^%$]*)(?:%[^$]*)?', 'tokens', 'once');
s = vertcat(s{:});
%# try to parse as numbers
v = str2double(s(:,2));
s(~isnan(v),2) = num2cell(v(~isnan(v)));
%# store: struct.key = value
for j=1:size(s,1)
arr(i).(s{j,1}) = s{j,2};
end
end
結果:
>> arr(1)
ans =
studentname: 'joe'
notes: ''
n1: 1.3
n2: 2
average: 1.7
>> arr(2)
ans =
studentname: 'marc'
notes: ''
n1: 2.3
n2: 3
average: 2.7
もちろん、これはファイルが適切にフォーマットされていることを前提としています(struct / endstructブロック、すべての構造体に同じフィールドが含まれ、フィールドタイプが一貫している)
説明:
コードは、ファイル行をセル配列に読み込むことから始まります。次に、struct/endstruct構造体の開始/終了位置を探します。構造体の空の配列をいくつかのデフォルト値で初期化し、ファイルを反復処理して各ブロックを解析し、その情報を1つの構造体に格納します。
次に、正規 表現を使用して次のパターンを検出します。
some_key_name = some value % optional comment here
=
スペースのバリエーションを考慮し、または:
その間の文字としても受け入れます。正規表現でキャプチャトークンを使用して、上記の各コンポーネントを回復し、一時セル配列に格納します。この時点で、すべてが文字列として保存されます。
これで、実際の値は数値または文字列のいずれかになります。最初に、STR2DOUBLEを使用してそれらを数値として解析しようとします。この関数はNaN
、失敗した場合に返されます。これは、正常に変換された部分のみを変更するために使用されます。
最後に、上記の結果で、動的フィールド名を使用して、構造体配列内の対応するキーに各値を格納します。