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.
Contents
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);
ssBad.time = ss.time;
ssBad.amp = ss.amplitude;
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 sbad 1x1 4856 struct array spots 288x2 4608 double array ss 1x1 4856 struct array ssBad 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 snippet(ssBad) 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.
- Category:
- Structures