Dennis Jaheruddin
Dennis Jaheruddin

Reputation: 21561

Adding a field to an empty struct

Assuming I have a struct S of size 0x1 with the fields a and b, what is the most elegant way to add a field c to it?

Usually I am able to do it like this:

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

However, if I receive an empty struct this does not work anymore:

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.

I have thought of two ways to deal with this, but both are quite ugly and feel like workarounds rather than solutions. (Note the possibility of a non-empty struct should also be dealt with properly).

  1. Adding something to the struct to ensure it is not empty, adding the field, and making the struct empty again
  2. Initializing a new struct with the required fieldnames, filling it with the data from the original struct, and overwriting the original struct

I realize that it may be odd that I care about empty structs, but unfortunately part of the code that is not managed by me will crash if the fieldname does not exist. I have looked at help struct, help subsasgn and also searched for the given error message but so far I have not yet found any hints. Help is therefore much appreciated!

Upvotes: 6

Views: 21599

Answers (4)

Peter Biggelaar
Peter Biggelaar

Reputation: 56

You can use setfield to solve the problem.

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

This results in

S = 

0x0 struct array with fields:
    a
    b
    c

Upvotes: 2

Amro
Amro

Reputation: 124563

Just to expand on @Shai's answer, here is a simple MEX-function you can use:

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

Example:

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

Upvotes: 1

H.Muster
H.Muster

Reputation: 9317

You can use deal to solve this problem:

S = struct('a',0,'b',0);
S(1) = [];

[S(:).c] = deal(0);

This results in

S = 

1x0 struct array with fields:
    a
    b
    c 

This works also for non-empty structs:

S = struct('a',0,'b',0);

[S(:).c] = deal(0);

which results in

S = 

    a: 0
    b: 0
    c: 0

Upvotes: 7

Shai
Shai

Reputation: 114966

How about

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

To create an empty struct?

Another way is to use mex file with mxAddField as a workaround to the error you got:

A dot name structure assignment is illegal when the structure is empty.
Use a subscript on the structure.

Upvotes: 2

Related Questions