Assignin Evalin into Matlab variable struct - matlab

I'm trying to modify my Farzeug structure from inside a gui popupmenu. I'm trying to use the assignin function.
contents = get(hObject,'Value')
Klima_Regler_GUI = evalin('base','Fahrzeug.Klima_Regler');
switch contents
case 1
Klima_Regler_GUI = 1;
assignin('base','Fahrzeug.Klima_Regler',Klima_Regler_GUI);
case 2
Klima_Regler_GUI = 0.75;
assignin('base','Fahrzeug.Klima_Regler',Klima_Regler_GUI);
case 3
Klima_Regler_GUI = 0.50;
assignin('base','Fahrzeug.Klima_Regler',Klima_Regler_GUI);
case 4
Klima_Regler_GUI= 0.25;
assignin('base','Fahrzeug.Klima_Regler',Klima_Regler_GUI);
case 5
Klima_Regler_GUI = 0;
assignin('base','Fahrzeug.Klima_Regler',Klima_Regler_GUI);
otherwise
but I keep getting this error:
I will appreciate any help

It is impossible to change the structure field using assignin because
assignin(ws, 'var', val) assigns the value val to the variable var in the workspace ws. The var input must be the array name only; it cannot contain array indices.
But you can use evalin to do this:
evalin('base',['Fahrzeug.Klima_Regler = ' num2str(Klima_Regler_GUI)])

Related

Swap variable names and field names in a set of structs, so the field names become the struct names and vice versa?

I have a set of structs that all have the same field names. For example structs A, B, and C all have field names name and section. Is there a way to rearrange this organization of data so that the data goes from:
A.name = 'bb';
A.section = 199;
B.name = 'joe';
B.section = 101;
C.name = 'rob';
C.section = 33;
to this:
name =
A: 'bb'
B: 'joe'
C: 'rob'
section =
A: 199
B: 101
C: 33
The current code I have, for example, operates like this:
% ORIGINAL STRUCTS
A.name = 'bb';
A.section = 199;
B.name = 'joe';
B.section = 101;
C.name = 'rob';
C.section = 33;
% CREATE VARIABLE NAMES FOR NEW STRUCTS
oldFNames = fieldnames(A); % old field names
oldVNames{1} = varname(A); % old variable names
oldVNames{2} = varname(B);
oldVNames{3} = varname(C);
% RESTRUCTURE STRUCTS (SWITCH FIELDNAMES AND VARIABLE NAMES)
for j = 1:length(oldFNames)
for k = 1:length(oldVNames)
eval([oldFNames{j} '.' oldVNames{k} ' = ' oldVNames{k} '.' oldFNames{j}]);
end
end
function out = varname(var) % Function to get variable name
out = inputname(1);
end
I find the hack to use the varname function to be not great, and I don't know whether there is a way to make it easily adaptable to the number of variables I have. Any input on how to simplify this procedure would be great. Thanks.
It would be easier to do it all in a function, instead of just using a function to get the input variable name. Here's one solution:
function invert_struct(varargin)
varNames = arrayfun(#inputname, 1:nargin, 'UniformOutput', false); % Get input names
s = [varargin{:}]; % Combine inputs into a structure array
for f = fieldnames(s).' % Loop over fields
assignin('caller', f{:}, cell2struct({s.(f{:})}, varNames, 2));
end
end
And you would call it like so, with however many inputs you like:
invert_struct(A, B, C, ...);
The function uses assignin to create your new variables in the calling function and cell2struct to create a new structure from your field data and old variable names. Note that it also makes use of dynamic field names.

Nested structure access using dynamic fieldnames

I'd like to achieve the following using dynamic fieldnames instead of setfield:
Say a struct 'myStruct' has a set of nested structures, i.e.
myStruct.a.b.c = 0
myStruct.a.d = 0
myStruct.a.e.f.g = 0
I want to be able to flexibly set the leaf structure values as follows:
fields = {'a', 'b', 'c'}
paramVal = 1
setfield(myStruct, fields{:}, paramVal)
This works using setfield. Is there a syntax that will do this using dynamic fieldnames? The following obviously doesn't work because the fieldname needs to be a string not an array, but demonstrates what I want:
myStruct.(fields{:}) = 0
Which would be equivalent to:
myStruct.('a').('b').('c') = 0
Recursive solution without eval, ripped from one of my old utility functions:
function s = setsubfield(s, fields, val)
if ischar(fields)
fields = regexp(fields, '\.', 'split'); % split into cell array of sub-fields
end
if length(fields) == 1
s.(fields{1}) = val;
else
try
subfield = s.(fields{1}); % see if subfield already exists
catch
subfield = struct(); % if not, create it
end
s.(fields{1}) = setsubfield(subfield, fields(2:end), val);
end
I guess the try/catch can be replaced with if isfield(s, fields{1}) ..., I don't remember why I coded it like that.
Usage:
>> s = struct();
>> s = setsubfield(s, {'a','b','c'}, 55);
>> s = setsubfield(s, 'a.b.d.e', 12)
>> s.a.b.c
ans =
55
>> s.a.b.d.e
ans =
12
Below is a simple, if crude, solution that works for scalar structs. Applying it to your example,
S=setfld(myStruct,'a.b.c',1)
>> S.a.b.c
ans =
1
In general, though, deeply nested structs are unrecommended.
function S=setfld(S,fieldpath,V)
%A somewhat enhanced version of setfield() allowing one to set
%fields in substructures of structure/object S by specifying the FIELDPATH.
%
%Usage: setfld(S,'s.f',V) will set S.s.f=V
%
%
%%Note that for structure S, setfield(S.s,'f') would crash with an error if
%S.s did not already exist. Moreover, it would return a modified copy
%of S.s rather than a modified copy of S, behavior which would often be
%undesirable.
%
%
%Works for any object capable of a.b.c.d ... subscripting
%
%Currently, only single structure input is supported, not structure arrays.
try
eval(['S.' fieldpath '=V;']);
catch
error 'Something''s wrong.';
end

MATLAB - Cleanly read variables out of a function possibly using some type of varargout...?

I have function f1 which must contain subfunctions, so I can't use another script:
function vars = f1()
a = 1;
b = 'hello';
c = {[1 2 3]};
currvars = whos; %all variable info
for k = 1:size(currvars, 1)
eval(['vars.(currvars(k).name) = ' currvars(k).name ';']);
end
end
I call the function in a script, and then I create the variables in the script using genvarname() and eval():
vars = f1();
varnames = genvarname(fieldnames(vars));
for k = 1:size(varnames(:),1) %Creates vars with the struct's fieldnames.
eval([varnames{k} ' = vars.' varnames{k} ';']);
end
clearvars vars varnames
I'd like to fit the variable creation process into a function somehow while reading out all the variables only to the script calling it, but I don't want to assign a hundred different variable names to the output. Does anyone have any advice on how to do this?
DON'T CREATE zillions of automatically named variables. This is foolish and terribly poor programming style. Instead, learn to use arrays. Multidimensional arrays, cell arrays, struct arrays.
Or, do what you have done, and then be forced to find a kludge like you are looking for.
Take your pick. Eval is evil.
You could return a structure with "corrected" fieldnames:
function output = someFunc
vars = f1();
protected = { %# some list of varnames you don't want
};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
output.(newnames{k}) = vars.(names{k});
end
end
If you then use
output = someFunc;
varnames = fieldnames(output);
for k = 1:numel(fieldnames)
eval([varnames{k} ' = output.' varnames{k} ';']);
end
in the script/function where you want the variable names, you have a relatively clean way of locking everything up in the function someFunc without having to pre-define all output variable names.
You can also do this in one step:
function someFunc2
vars = f1();
protected = { %# some list of varnames you don't want
};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
assignin('caller', newnames{k}, vars.(names{k}));
end
end
Which means you just call the function
someFunc2;
in your script, and the function then defines and assigns all the variables in the script's workspace.
A tiny step forward, but forward nonetheless :)
CREDIT TO RODY...
#Old semi-"global" variables:
function vars = f1()
a = 1;
b = 'hello';
c = {[1 2 3]};
currvars = whos; %all variable info
for k = 1:size(currvars, 1)
eval(['vars.(currvars(k).name) = ' currvars(k).name ';']);
end
end
#Function to assign variables to the calling script's/function's workspace. Variable names are determined by the single structure's fieldnames:
function setvars(func)
vars = func;
protected = {'If needed, put variable names you do not want here'};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
assignin('caller', newnames{k}, vars.(names{k}));
end
end
#Script call:
setvars(f1);

Matlab: pass 'who' output on as argument

I have written a function that takes the names and values of the input variables and writes them to a file. eg.
a = 10;
b = 100;
writevars('file.txt',a,b);
gives me a file file.txt that contains:
\def\a{\num{10}}
\def\b{\num{100}}
It would now like to be able to pass on all variables that are found using the who command. Eg if who returns:
a b z
I would like to be able to use writevars as if I called writers('file.txt', a, b, z).
The main problem I have is that writevars makes use of inputname... (temporary variables won't work e.g. writevars('file.txt', 100) doesn't work since there is no name to be given in the file).
ANSWER
var_names = who;
for i = 1 : length(var_names)
evalin('caller',['writevars(''file.txt'', ' char(var_names(i)) ' )']);
end
You can use EVALIN to run who from within writevars, e.g.
function writevars(filename,varargin)
%# get a list of variable names in the calling workspace and read their values
if isempty(varargin)
listOfVars = evalin('caller','who');
values = cell(size(listOfVars));
for i=1:length(listOfVars)
values{i} = evalin('caller',listOfVars{i});
end
else
%# use inputname to read the variable names into listOfVars
end
%# --- rest of writevars is here ---
It can be used by using the return value of whos command:
function GetAllVars
a = 45;
x = 67;
ff = 156;
z = who();
for i=1:numel(z)
if ~isequal(z{i},'z')
fprintf(1,'%s = %f\n',z{i},eval(z{i}));
end
end

Iterate through a MATLAB structure numerically

Is it possible to iterate through a MATLAB structure numerically like a vector instead of using the field names?
Simply, I am trying to do the following inside an EML block for Simulink:
S.a.type = 1;
S.a.val = 100;
S.a.somevar = 123;
S.b.type = 2;
S.b.val = 200;
S.b.somevar2 = 234;
S.c.type = 3;
S.c.val = 300;
S.c.somevar3 = 345;
for i = 1:length(s)
itemType = S(i).type;
switch itemType
case 1
val = S(i).val * S(i).somevar1;
case 2
val = S(i).val * S(i).somevar2;
case 3
val = S(i).val * S(i).somevar3;
otherwise
val = 0
end
end
disp(var);
You should be able to generate the fieldnames dynamically using sprintf using something like the following:
for i = 1:length(s)
theFieldName = sprintf('somevar%d', S(i).type);
val = S(i).val * getfield(S(i), theFieldName);
end
You need to use the field names, but you can do so dynamically. If you have a structure defined as:
s.field1 = 'foo';
s.field2 = 'bar';
Then you can access the field field1 with either
s.field1
s.('field1')
The only thing you need is the function fieldnames to dynamically get the field names such that your code example will look somewhat like
elements = fieldnames(S);
for iElement = 1:numel(elements)
element = S.(elements{iElement});
itemType = element.type;
switch itemType
case 1
val = element.val * element.somevar1;
case 2
val = element.val * element.somevar2;
case 3
val = element.val * element.somevar3;
end
end
If those are the exact field names, you should do some other things. First of all you would need to rethink your names and secondly you could use part of Matt's solution to simplify your code.