【问题标题】:Adding a field to an empty struct将字段添加到空结构
【发布时间】:2013-01-27 15:08:15
【问题描述】:

假设我有一个大小为 0x1 的结构体 S,其中包含 ab 字段,那么向其中添加字段 c 的最优雅的方法是什么?

通常我可以这样做:

S = struct('a',0,'b',0); %1x1 struct with fields a,b
S.c = 0

但是,如果我收到一个空结构,这将不再起作用:

S = struct('a',0,'b',0);
S(1) = []; % 0x1 struct with fields a,b
S.c = 0;
% A dot name structure assignment is illegal when the structure is empty.  
% Use a subscript on the structure.

我想了两种方法来解决这个问题,但两者都很丑陋,感觉像是变通方法而不是解决方案。 (注意非空结构体的可能性也应妥善处理)。

  1. 向结构中添加一些内容以确保其不为空,添加字段,并使结构再次为空
  2. 使用所需的字段名初始化新结构,用原始结构中的数据填充它,并覆盖原始结构

我意识到我关心空结构可能很奇怪,但不幸的是,如果字段名不存在,那么不由我管理的部分代码将会崩溃。我查看了help structhelp subsasgn 并搜索了给定的错误消息,但到目前为止我还没有找到任何提示。因此非常感谢您的帮助!

【问题讨论】:

    标签: matlab struct variable-assignment


    【解决方案1】:

    你可以使用deal来解决这个问题:

    S = struct('a',0,'b',0);
    S(1) = [];
    
    [S(:).c] = deal(0);
    

    这会导致

    S = 
    
    1x0 struct array with fields:
        a
        b
        c 
    

    这也适用于非空结构:

    S = struct('a',0,'b',0);
    
    [S(:).c] = deal(0);
    

    导致

    S = 
    
        a: 0
        b: 0
        c: 0
    

    【讨论】:

    • 感谢这个不错的解决方案。您能否解释一下为什么这样可行,但为什么 [S.c] = deal(0) 不行?
    • 请见谅,但实际上,我不知道为什么会这样。
    • 有兴趣的读者可以查看我的后续问题:stackoverflow.com/questions/16342688/…
    【解决方案2】:

    怎么样

    S = struct('a', {}, 'b', {}, 'c', {} );
    

    要创建一个空结构?

    另一种方法是使用带有mxAddFieldmex 文件作为您遇到的错误的解决方法:

    当结构为空时,点名结构赋值是非法的。
    在结构上使用下标。

    【讨论】:

    • 我想我可以使用一个if语句来查看它是否确实为空然后使用它,但我仍然希望有一种方法可以不先检查。
    【解决方案3】:

    您可以使用setfield解决问题。

    S = struct('a', {}, 'b', {});
    S = setfield(S, {}, 'c', [])
    

    这会导致

    S = 
    
    0x0 struct array with fields:
        a
        b
        c
    

    【讨论】:

    • 非常好,我在文档中看不到这种可能性,但它似乎与公认的解决方案一样工作。 -- 在看这个的时候,我偶然发现了一种使 Matlab 崩溃的罕见方法(2012b):S = struct(); S(:)=[]; S().e=[]; S(3,3).f=[]; S().g=[];
    • 这段代码给了我Expected one output from a curly brace or dot indexing expression, but there were 0 results. (R2016b)。
    【解决方案4】:

    只是为了扩展@Shai's answer,这是一个您可以使用的简单 MEX 函数:

    addfield.c

    #include "mex.h"
    
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
    {
        char *fieldname;
    
        /* Check for proper number of input and output arguments */
        if (nrhs != 2) {
            mexErrMsgIdAndTxt("struct:nrhs", "Two inputs required.");
        } else if (nlhs > 1) {
            mexErrMsgIdAndTxt("struct:nlhs", "Too many output arguments.");
        } else if (!mxIsStruct(prhs[0])) {
            mexErrMsgIdAndTxt("struct:wrongType", "First input must be a structure.");
        } else if (!mxIsChar(prhs[1]) || mxGetM(prhs[1])!=1) {
            mexErrMsgIdAndTxt("struct:wrongType", "Second input must be a string.");
        }
    
        /* copy structure for output */
        plhs[0] = mxDuplicateArray(prhs[0]);
    
        /* add field to structure */
        fieldname = mxArrayToString(prhs[1]);
        mxAddField(plhs[0], fieldname);
        mxFree(fieldname);
    }
    

    例子:

    >> S = struct('a',{});
    >> S = addfield(S, 'b')
    S = 
    0x0 struct array with fields:
        a
        b
    

    【讨论】:

    • @down-voter:为什么,想发表评论?如果代码有问题,我很乐意改进它......它在我的最终工作正常!
    猜你喜欢
    • 2020-02-29
    • 1970-01-01
    • 2022-07-16
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    相关资源
    最近更新 更多