0

我一直在研究一个令人费解的问题,该问题涉及将一个 ascii 文件读入 matlab,其中包含 2 个不同格式的部分,第一部分还包括不同的列号。

MESH2D
MESHNAME "XXX"
E3T 1 1 29 30 1
E4Q 2 2 31 29 1 1
E4Q 3 31 2 3 32 1
...
...
...
ND 120450 5.28760039e+004 7.49260000e+004 8.05500000e+002
ND 120451 5.30560039e+004 7.49260000e+004 6.84126709e+002
ND 120452 5.32360039e+004 7.49260000e+004 6.97750000e+002
ND 120453 5.34010039e+004 7.49110000e+004 7.67000000e+002
NS  1 2 3 4 5 6 7 8 9 10
NS  11 12 13 14 15 16 17 18 19 20
NS  21 22 23 24 25 26 27 -28
BEGPARAMDEF
GM  "Mesh"

我只对包含三角形并以 E3T/E4Q 开头的线以及包含三角形节点坐标并以 ND 开头的相应线感兴趣。对于三角形(E3T/E4Q 线),我只对前 4 个数字感兴趣,因此我试图做这样的事情:

fileID = fopen(test);
t1 = textscan(fileID, '%s',3);
t2 = textscan(fileID, '%s %d %d %d*[^\n]');
fclose(fileID);

所以读入表头跳转到数据然后读取第一个字符串和后面的4个数字,然后跳转到行尾重新开始。但这不起作用。我只得到一行数据,而不是文件的其余部分。另外,我不知道如何处理文件的第二部分,它以任意数量的数字开始(我当然可以手动查找并输入 matlab,但希望 matlab 自动找到格式的这种变化) .

你有什么建议吗?

干杯!

4

2 回答 2

2

我建议您首先使用textscan字符串读取文件的所有行,然后过滤掉您需要的任何内容:

fid = fopen(filename, 'r');
C = textscan(fid, '%s', 'delimiter', '');
fclose(fid);

然后使用以下方法仅解析 E3T/E4Q/ND 行regexp

C = regexp(C, '(\w*)(.*)', 'tokens');
C = cellfun(@(x){x{1}{1}, str2num(x{1}{2})}, C, 'UniformOutput', false);
C = vertcat(C{:});

然后将相应的 E3T/E4Q 和 ND 线分组:

idx1 = strcmp(C(:, 1), 'E3T') | strcmp(C(:, 1), 'E4Q');
idx2 = strcmp(C(:, 1), 'ND');
N = max(nnz(idx1), nnz(idx2));
indices = cellfun(@(x)x(1:4), C(idx1, 2), 'UniformOutput', false);
S = struct('tag', [C(idx1, 1); cell(N - nnz(idx1), 1)], ...
    'indices', [indices; cell(N - nnz(idx1), 1)], ...
    'nodes', [C(idx2, 2); cell(N - nnz(idx2), 1)]);

我将 E3T/E4Q 值命名为“索引”,将 ND 值命名为“节点”。结果数组S包含结构,每个都有三个字段:tag(E3T 或 E4Q)indicesnodes. 请注意,如果您的“索引”多于“节点”或反之亦然,则缺失值由空矩阵表示。

于 2013-05-16T14:46:06.297 回答
1

我知道这并不完美,但如果你的文件不是太大,你可以这样做:

fileID = fopen(test,'r');
while ~feof(fileID)
    FileLine        = fgetl(fileID);
    [LineHead,Rem]  = strtok(FileLine);     % separated string header and numbers
    switch LineHead
        case 'MESH2D'
            % do something here
        case 'MESHNAME'
            % do something here
        case 'E3T'
            % parse integer numbers
            [Num,NumCount]  = sscanf(Rem, '%d');
        case 'E4Q'
            % parse integer numbers
            [Num,NumCount]  = sscanf(Rem, '%d');
        case 'ND'
            % parse integer numbers
            [Num,NumCount]  = sscanf(Rem, '%d');

            % or if you prefer to parse first number separately
            [strFirst,strOthers]    = strtok(Rem);
            FirstInteger            = str2num(strFirst);
            [Floats,FloatsCount]    = sscanf(strOthers, '%g');
        % and so on...
    end
end
fclose(fileID);

当然,您必须分别处理以MESH2D MESHNAMEGM开头的字符串

于 2013-05-16T13:29:38.530 回答