# Working with structs

MATLAB has some functions that are specifically designed for exploring the contents of structures (entities known in MATLAB by the class struct). I find the functions isfield and fieldnames particularly helpful. The reason I raise this area of functionality is because some users new to MATLAB occasionally have trouble finding these functions and try to use the function exist to do the work for them and find it doesn't work out.

### Example Application

Suppose I'm writing an M-file to analyze data that I expect to come in a struct with two fields, named time and amplitude. Since I intend to pass this M-file to lots of other folks, I want to write it somewhat carefully so errors the users make give them enough information to correct problems without having to consult me too often.

### snippet Help

Let's look at the help for our function first:

help snippet

 SNIPPET plots time vs. amplitude from an input struct.
SNIPPET(D) plots data from a struct D which must contain the two fields:
time : a sequence of times
amplitude : corresponding amplitudes
If either D.time or D.amplitude are missing, SNIPPET errors out.



### Sample Data

Next let's get some data that is suitable for this function (ss and ssExtra), and some that is not (ssBad).

sunspots = load('sunspot.dat');
ss.time = sunspots(:,1);
ss.amplitude = sunspots(:,2);
ssExtra = ss;
ssExtra.other = datestr(today);


### Checking Inputs for Suitability with snippet with exist

Let's explore how I might check our different versions of the sunspot data to see which one or ones is suitable for use with snippet so I can figure out what code to put into snippet to do the error checking. Remember, we want to check to see if the input is a struct and, if so, that it has fields time and amplitude. I'll begin by trying exist, and I am placing the code inside a try-catch. so I can capture any errors and easily show them.

try
exist(ss.time)
catch
err = lasterror;
disp(err.message)
end

Error using ==> exist
The first input to exist is a string.


That didn't work because exist expects string input. So here's my next attempt.

try
exist('ss.time')
catch
err = lasterror;
disp(err.message)
end

ans =

0



and that didn't work either! What went wrong? I gave exist a string input. Looking at the help carefully, I see that the name I give must be a variable name or the name of some file or method. So now let me check my variable name using the function isvarname.

isvarname('ss.time')

ans =

0



I can also see what variables I do have in my workspace:

whos

  Name           Size                    Bytes  Class

ans            1x1                         1  logical array
err            1x1                      2158  struct array
f              1x25                      200  double array
fibo           1x25                      200  double array
n              1x1                         8  double array
nmax           1x1                         8  double array
spots        288x2                      4608  double array
ss             1x1                      4856  struct array
ssExtra        1x1                      5002  struct array
sunspots     288x2                      4608  double array

Grand total is 3969 elements using 31361 bytes



and I see that I have ss but not ss.time because ss.time is a member of the struct but not a variable itself. I've seen this confusion between structures, their fields, and variables, fairly regularly on the MATLAB newsgroup.

### Try struct-specific functions

I now understand that I have to look at the details of the structure variables to see if the fields I need are there. Here's the code I wrote:

type snippet

function snippet(D)
%SNIPPET plots time vs. amplitude from an input struct.
%   SNIPPET(D) plots data from a struct D which must contain the two fields:
%           time : a sequence of times
%      amplitude : corresponding amplitudes
%   If either D.time or D.amplitude are missing, SNIPPET errors out.

if ~isstruct(D) || ...
~(isfield(D,'time') && isfield(D,'amplitude'))
error('snippet:incorrectInput', ...
'snippet expects a struct with fields time and amplitude');
end
plot(D.time,D.amplitude)


### Try snippet on Incorrect Inputs

try
snippet(sunspots)
catch
err = lasterror;
disp(err.message)
end
try
catch
err = lasterror;
disp(err.message)
end

Error using ==> snippet
snippet expects a struct with fields time and amplitude
Error using ==> snippet
snippet expects a struct with fields time and amplitude


### Try snippet with Good Inputs

I leave it as an exercise for you to show that snippet runs correctly using either ss or ssExtra as inputs.

### Extra Credit

For extra credit, anyone care to write the code I'd need to add to snippet to disallow inputs with an extra fields to work? I gave a hint earlier in this column.

Any thoughts on this topic? If so, enter them here.

|