Save variable as string from user input

43 views (last 30 days)
I have a gui which let the user create a test. I store the user input as a new structure because the user should be able to save the test parameters. When the user pushes the save button i want to save the new structure as a .mat file containing this structure. The problem is naming the saved structure. I'm using "save(filename, varname)" which let me name the .mat file whatever I want to. But the structure name which is saved will be named after the variable 'varname'. But i want the structure to be named after what the user named the test. I hope I'm making sence. From what i have understood it's bad practise to create a variable with the name of a string. Is there another way of achieving this?
Edit* Example:
%returns the structure with test %parameters
editedTest = getNewTest(handles,editedTestName);
%Save structure
save(fileName,'editedTest');
This saves my structure in a .mat file which I want, but the structure in the .mat file is named 'editedTest', I want to name this variable after a string (I want the saved structure to be named as what the user named the test to).
The whole function looks like this:
% --- Executes on button press in pushbutton_saveTest.
function pushbutton_saveTest_Callback(hObject, ~, handles)
listboxItems = get(handles.listbox_tests,'String');
editedTestName = char(get(handles.edit_testName,'String'));
editedTest = getNewTest(handles,editedTestName);
currentFolderPath = pwd;
if ismember({'-Empty-'},listboxItems)
listboxItems{1,:} = editedTestName;
elseif ismember({editedTestName}, listboxItems)
% Construct a questdlg with three options
choice = questdlg('Test already exists, do you want to overwrite?', ...
'Test already exists', ...
'default');
% Handle response
switch choice
case 'Yes'
fileName = [currentFolderPath '\Tests\' editedTestName];
case 'No'
answer = char(inputdlg({'Enter new test name'},'Save new test',1,{'untitled test'}));
fileName = [currentFolderPath '\Tests\' answer];
listboxItems(end+1,:) = {answer};
case 'Cancel'
%Do nothing
fileName=[];
end
else
fileName = [currentFolderPath '\Tests\' editedTestName];
listboxItems(end+1,:) = {editedTestName};
end
if ~isempty(fileName)
save(fileName,'editedTest');
handles.tests = setfield(handles.tests, editedTestName, editedTest);
end
set(handles.listbox_tests,'String',listboxItems);
guidata(hObject, handles);

Accepted Answer

Stephen23
Stephen23 on 26 Jun 2015
Edited: Stephen23 on 18 Mar 2019
There are two overlapping issues here:
  1. The non-robustness of string evaluation (which was covered in your other question). There are many reasons why string evaluation should be avoided, but it boils down to robustness, performance, code reliability and ease of debugging. For discussions of this, read any question on this forum about string evaluation, such as this one, or my TUTORIAL: Why Variables Should Not Be Named Dynamically (eval).
  2. The inclusion of meta-data within variable names or fieldnames (e.g. naming a variable with the user's input, or more commonly trying to include an index in a variable name) is more subtle, but is also a poor programming practice. Forcing meta-data into variable names makes accessing that meta-data much slower and more complex. In contrast, storing meta-data as data in a variable allows you to write more generalized code, which is more robust, more adaptable, easier to write, and easier to fix. Here is why...
Consider a collection of tests at several speeds, with accompanying data, and we include the test meta-data in the fieldnames:
X.test_5kmh = [1,2,3];
X.test_100kmh = [5,6,7];
If this meta-data is required to be displayed in a figure title, then it requires some complicated processing: get the fieldnames, identify and extract certain parts, then display. Now what happens when the test conditions change and expanded, and it is decided to also include temperature:
X.test_5kmh_20deg = [1,2,3];
X.test_5kmh_60deg = [8,9,NaN];
X.test_100kmh_20deg = [4,5,6];
etc.
But notice: in order to permit this change every piece of code that handles these fieldnames will have to be checked, and probably changed. It is not possible to make any small change to those fieldnames without requiring all related code to be reviewed and updated. Our code breaks, those titles do not work any more, and even worse perhaps we do not even realize which parts of our code are broken. Did we miss a bit? Did we forget to check some part somewhere? It is clear that this is not robust, nor is it generalized. The parsing of those names might break when we include a negative sign, or NaN values, or change how many digits the values use, or need to include new meta-data that suddenly becomes relevant. It might break, and we can't even easily check where it might break (because we cannot search for one simple fieldname), and we also don't know how it might break...
Now consider when the meta-data are treated as data in their own right:
X(1).data = [1,2,3];
X(1).speed = 5;
X(2).data = [4,5,6;
X(2).speed = 100;
When it is required to include other data, we can do this without making any other changes to our existing code:
X(1).temperature = 20;
X(2).temperature = 20;
etc.
Our figure title generation, based simply on the speed values, will still work! It is not affected by adding more meta-data (i.e. fields) or even any data's values. Other fields and values can completely change, and yet everything related to the speed values will still work. And even better: if we then need to change the original speed meta-data itself (different units, make it a range of values, empty as a placeholder, NaN, etc) then the only places required to be updated are where those speed values are referred to, and nowhere else. And now finding those bits of code is also easy using a simple search for "X.speed", or "speed(", in all of our files. How could one search for dynamically named variables or fieldnames? How can one locate every place that they are referred to?
Now lets consider your situation: "But i want the structure to be named after what the user named the test" The question is, why do you want this? Presumably it is to keep the information handy. So lets keep it handy:
X(1).data = ...
X(1).user_input = ...
With this you can simply save what the user gives you... it could even be empty, it does not matter because your code does not depend on their value: this is robust! The user could even decide to change to inputting a cell array instead of a string, and your code would still store it correctly. Of course any processing of this value would have to change, but these processing locations are now much easier to locate and update... and it still does not affect any of the other fields or data! Now that is generalized!
Some other discussions on this topic:
And for some other languages advising "DO NOT create dynamic variable names":
  3 Comments
Stephen23
Stephen23 on 26 Jun 2015
Edited: Stephen23 on 26 Jun 2015
"maybe it's unnecessary" a few bits [sic] of meta-data hanging around never hurts. It might just be useful one day!
As the save and load commands use structures, these would be the natural choice here. There are lots of neat shortcuts for working with structure data too:
But of course generally in MATLAB use the simplest array class that you can, and this usually makes the programming much easier.

Sign in to comment.

More Answers (0)

Tags

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!