Can't use user input and eval() to add a row to a table within a structure.

2 vues (au cours des 30 derniers jours)
Hello Matlab community,
I'm pretty new to Matlab and to coding in general. I wrote some code that adds a row to one of two tables (tableA and tableB), but the table is selected by the user. In lieu of having the user type in 'myStruct.tableA,' I wanted the code to just take 'A,' and then I'd strcat() the rest, and then use eval() to call the correct table.
var1 = ["A"];
var2 = ["B"];
var3 = ["C"];
tableA = table(var1, var2, var3);
tableB = table(var1, var2, var3);
myStruct.tableA = tableA;
myStruct.tableB = tableB;
userInput = input('Which table would you like to add a row to (A or B)? ', 's');
T = strcat("myStruct.table",userInput);
newRow = {var1, var2, var3};
eval(T) = [eval(T); newRow];
When I do this, I get the following error:
Subscripting into a table using one subscript (as in t(i)) is not supported. Specify a row subscript and a variable subscript, as in t(rows,vars). To select variables, use t(:,i) or for one variable t.(i). To select rows, use t(i,:).
However, this works fine to call the table:
eval(T)
And when I don't use eval(), this does what I want:
myStruct.tableA = [myStruct.tableA; newRow]
So I'm a little confused, and the error message doesn't make much sense to me for this particular case. Any advice would be great. Thank you.

Réponse acceptée

Dave B
Dave B le 12 Nov 2021
Modifié(e) : Dave B le 12 Nov 2021
First of all, this is not a good way to do things. In general, if you find yourself using eval, you should stop and rethink the problem. Just search for eval up above in the Search Answers box and you'll see lots of pros saying don't do it! You should do that search, and you'll learn lots more about why it's bad, and what to do instead. But I'll answer your specific situation below.
Note: eval does have uses, or we it wouldn't be in MATLAB, but it's far more easy to misuse than to use correctly, so save this until you don't feel like a beginner and you'll know when it's appropriate (almost never).
Why did this particular use or eval fail? because you're trying to use the result of eval as a target for assignment. Consider what happens in a simpler, non table, case:
a=1;
b='a';
eval(b)
a = 1
eval(b)=2
eval = 1×97
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
whos % note this gets a list of variables in the workspace
Name Size Bytes Class Attributes a 1x1 8 double b 1x1 2 char eval 1x97 776 double
The expression eval(b)=2 has created a variable called eval, and put the value 2 into the index associated with the letter 'a' (the letter 'a' being the 97th character in ascii, i.e. double('a')). In other words this was equivalent to typing eval('a')=2, which is equivalent to typing eval(97)=2.
As I wrote above, it's strongly discouraged to use eval for something like this, and every seasoned MATLABber will give you that advice. But if you really felt complled to experiment, you'd want to put the equals sign inside the eval string:
eval(T + "=[" + T + ";newRow];") % I can't even bring myself to mark it as code, not pretty!
So if that's a bad solution, what should you do instead?
Well in this case it's pretty simple, because you can use a variable to index into a struct:
myStruct.("table" + userInput) = [myStruct.("table" + userInput); newRow];
An alternative, more general solution (just to illustrate the approach) might be to use indexing and a cell array instead of a struct:
thetables = {tableA tableB};
options = ["A" "B"];
if ~ismember(userInput,options)
% put an error here!
% what should we do here? prompt again? Should the script stop running?
else
thetables(userInput==options) = [thetables(userInput==options); newRow];
end

Plus de réponses (0)

Catégories

En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange

Produits


Version

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by