String value to varible value (macro?)

Hi, greetings to all
I am trying to assign a string variable value another variable value
something like:

int led_1_state = LOW;

String var1Value = "led_" + "1" + "_state";

and when print the string value:

Serial.print(var1Value);
but instead of printing "led_1_state", the printing will be "LOW" (the value of the variable)

could macro or something could work ?
Thank you in advance

I know that an array could work, but i am trying a more direct control to it

C++ is compiled and all the names you declare are gone when running code so you can't build up a variable name and hope to access its content this way.

You have to use arrays

const byte nbLeds = 4; // we have 10 LEDs
const byte ledPins[nbLeds] = {4,5,6,7};
byte ledStates[nbLeds] = {LOW}; // they are all LOW at start, array starts at 0 so indexes from 0 to 3

then you can store the 3rd led state

ledStates[2] = digitalRead(ledPins[2]);

or test if with

if (ledStates[2] == HIGH) {…}

or print all states with

for (byte l=0; l < nbLeds; l++) Serial.prinln(ledStates[l] == HIGH ? F("HIGH") : F("LOW"));

(side note: building variable names in Strings and trying to find the associated variable is very far from being a "more direct control to it")

Pointers and references are other way you could explore.

Thanks for the quick reply JML,
I am an older programmer, from DBASE era, and in clipper we have what is call "macro variable substitution", that basically is that.

I know next to nothing of c++, but once the variable is declared, you access it by the name

String a = "one";
Serial.print(a);

one
what i am trying is this (continuing with the code...)

String b = "a";

Serial.print(b);

a

Serial.print(&b);

one

(the "&" was the macro variable substitution in clipper)

It is possible ?

Thanks again

I know next to nothing of c++, but once the variable is declared, you access it by the name

you access it by its name in the code. But once compiled, all names are gone so there is 0 chance you get dynamically to find a variable by it name in the original code.

if you want to use a macro to build up a variable name, that would be

#define var(x) variable_##x

int variable_1 = 1;
int variable_2 = 2;
int variable_3 = 3;

void setup() {
  Serial.begin(115200);
  
  Serial.println(var(1));
  Serial.println(var(2));
  Serial.println(var(3));
}

void loop() {}

--> but everything needs to be resolved at compile time, so there is no much gain...

the real question is why do you need this ?

#define var(x) variable_##x

String var1 = "var";

String variable_1 = "one";
int variable_2 = 2;
int variable_3 = 3;

void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
Serial.println();

String var1 = "var";
String var2 = "(";
String var3 = "1";
String var4 = ")";
String var5 = var1+var2+var3+var4;

Serial.println(var5);

Serial.println(var(1));
Serial.println(var(2));
Serial.println(var(3));
}

void loop() {
// put your main code here, to run repeatedly:

}

monitor output:
var(1)
one
2
3

and what i want to approach:

one
one
2
3

I want to put the code in a for-loop, i understand i can do that with an array, but could be easier with the
variable macro substitution.

Thanks a lot JML for the help you are giving me

as I said that won't work because what you build is no longer done at compile time but run time. The macro is only applied once, at compile time. then everything goes away and becomes memory pointers to bytes with associated code that understands what's going on.

if you really really really need dynamic variable access through some sort of name, you need to build that up and store in memory the name of the variable, then iterate through your list of variables and search the one with the right name... that's basically what clipper was doing for you in the background.

Thank you very much JML,
Any piece of code that you can share to point me in the right direction?

that is NOT the right direction... it's a bad idea to try to apply an old thing to a new language. You'll endup with memory problems in your code and things being way more complicated than needed...

but that's an example of a very poor, non scalable solution

struct t_variable {
  const char *varName;
  int varValue;
};

t_variable myVariables[] = {
  {"foo",   0},
  {"bar0", 10},
  {"bar1", 11},
  {"bar2", 12},
  {"baz",  30},
  {"qux",  40},
  {"fum",  50}
};

t_variable tempHack;
#define valueOf(s) (getValue(s, tempHack) ? String(tempHack.varValue) : String("Error"))

bool getValue(String aName, t_variable& v)
{
  for (auto& a : myVariables) {
    if (aName == a.varName) {
      v = a;
      return true;
    }
  }
  return false;
}

void setup() {
  Serial.begin(115200);

  Serial.println(valueOf("foo"));

  String s = "bar";
  for (int i = 0; i < 3; i++)   Serial.println(valueOf(s + i)); // get bar0, bar1 and bar2

  Serial.println(valueOf("badIdea")); // Error
}

void loop() {}

valueOf("xxx") will return a String with either "Error" or the number (as a String)

you could also explore key value pairs in JSON format or other arbitrary storage options.

BUT REALLY - THAT'S A VERY BAD IDEA. DON'T GO THERE !!!

mexicanto:
Thank you very much JML,
Any piece of code that you can share to point me in the right direction?

First you need to explain the why behind what you are trying to do, not just the what. This is almost certainly an X-Y problem.

As already explained for technical reasons (mainly C/C++ being a compiled language without any metadata) it's impossible to reflect back on the names of variables from your compiled code.

Suggest posting a real world example of how you need to use this.

Thank you very much to all for your help, i will use arrays

wise decision :slight_smile: