Dictionary type lookup table (array)

Hi,

I have a set of about 30 paired commands like this:

const char* ON = "+";
const char* OFF = "-";

const char* RESTART = "RESTART";
const char* RESTARTED = "RESTARTED";

and require a way to lookup the corresponding varied value.

For example:
if the command received is "+", need to respond with '-'
if the command received is "RESTART", need to respond with "RESTARTED"

There isn't a dictionary type object for me to use key values, and I can't figure out map :frowning:

Im thinking of two options:
Option 1: create a one dimensional array of

const char* const STATE[2] = {"+", "-"};
const char* const RESTART[2] = {"RESTART", "RESTARTED"};

Lookup function would iterate the array and check if each items[0] element == whats received and return item[1]

Option 2: use a 2 dimensional array - but I don't know how to do this.

Would appreciate any help on how to define the array and the lookup function.

Thank you

Hi,

BIOT:
Option 1: create a one dimensional array

You could use your 1-d array this way round:

 const char * questions[]={
    "+",
    "RESTART",
    "Foo"
 };
 const char * answers[]={
    "-",
    "RESTARTED",
    "Bar"
 };

...lookup to match the question, use that index for the answer.

Yours,
TonyWilk

1 Like

TonyWilk:
Hi,

You could use your 1-d array this way round:

 const char * questions[]={

"+",
    "RESTART",
    "Foo"
};
const char * answers[]={
    "-",
    "RESTARTED",
    "Bar"
};




...lookup to match the question, use that index for the answer.

Yours,
TonyWilk

Thank you Tony.

Yes, I see how that would work. I worry that it is error prone as the order of the items in both arrays needs to stay correct over time during development (will be adding many commands in the coming months).

Ideally, a 1 dim array of 2 dim items in it would be safer, but I dont understand how to define the parent 1 dim array

Time for an array of structs.

1 Like

BIOT:
Yes, I see how that would work. I worry that it is error prone as the order of the items in both arrays needs to stay correct over time during development (will be adding many commands in the coming months).

Yep, you are right there. Do-able with what you know, but you want more :slight_smile:

Follow gfvalvo's suggestion.

Yours,
TonyWilk

The following code uses parallel arrays or 2-dimentioned arrays. You can toggle them by using the #define SINGLE preprocessor directive. For beginners, I would think the parallel arrays is easier to understand, but I appreiciate how they can get out of sync.

#define ELEMENTCOUNT(x) (sizeof(x) / sizeof(x[0]))

#define SINGLE  // comment out for single array

#ifdef SINGLE
char operators[] = {'+', '-', '*', '/'};
char *words[] = {"add", "subtract", "multiply", "divide"};
#else
char *tokens[][2] = { {"+","add"}, {"-", "subtract"},
                      {"*","multiply"}, {"/", "divide"}
                    };
#endif
void setup() {
  Serial.begin(9600);
}

void loop() {
  char c[2];
  int index;
  
  if (Serial.available() > 0) {
    c[0] = Serial.read();

    index = FindWord(c);

    Serial.print("For operator ");
    Serial.print(c);
    Serial.print(" the word is ");
    if (index != -1) {
#ifdef SINGLE      
      Serial.println(words[index]);
#else
      Serial.println(tokens[index][1]);
#endif
    } else {
      Serial.println("not not found in list.");
    }
  }
}

/*****
  Purpose: to search a list of operators for a match on the target operator

  Parameter list:
    char target     the operator to find

  Return value:
    int             the index for a match, -1 no match
*****/
int FindWord(char *target) 
{
  int i;

#ifdef SINGLE    
  for (i = 0; i < ELEMENTCOUNT(operators); i++) {
    if (operators[i] == target[0]) {
#else
  for (i = 0; i < ELEMENTCOUNT(tokens); i++) {
    if (strcmp(tokens[i][0], target) == 0) { 
#endif
      return i;
    }
  }
  return -1;
}

econjack:
The following code uses parallel arrays or 2-dimentioned arrays. You can toggle them by using the #define SINGLE preprocessor directive. For beginners, I would think the parallel arrays is easier to understand, but I appreiciate how they can get out of sync.

#define ELEMENTCOUNT(x) (sizeof(x) / sizeof(x[0]))

#define SINGLE  // comment out for single array

#ifdef SINGLE
char operators[] = {'+', '-', '*', '/'};
char *words[] = {"add", "subtract", "multiply", "divide"};
#else
char tokens[][2] = { {"+","add"}, {"-", "subtract"},
                      {"
","multiply"}, {"/", "divide"}
                    };
#endif
void setup() {
  Serial.begin(9600);
}

void loop() {
  char c[2];
  int index;
 
  if (Serial.available() > 0) {
    c[0] = Serial.read();

index = FindWord(c);

Serial.print("For operator ");
    Serial.print(c);
    Serial.print(" the word is ");
    if (index != -1) {
#ifdef SINGLE     
      Serial.println(words[index]);
#else
      Serial.println(tokens[index][1]);
#endif
    } else {
      Serial.println("not not found in list.");
    }
  }
}

/*****
  Purpose: to search a list of operators for a match on the target operator

Parameter list:
    char target    the operator to find

Return value:
    int            the index for a match, -1 no match
*****/
int FindWord(char *target)
{
  int i;

#ifdef SINGLE   
  for (i = 0; i < ELEMENTCOUNT(operators); i++) {
    if (operators[i] == target[0]) {
#else
  for (i = 0; i < ELEMENTCOUNT(tokens); i++) {
    if (strcmp(tokens[i][0], target) == 0) {
#endif
      return i;
    }
  }
  return -1;
}

Just pasted the code and ran it. OMG it worked! THANK YOU SO MUCH!

Now I just need to focus for a bit to understand whats its doing ... :wink:

ELEMENTCOUNT(x) (sizeof(x) / sizeof(x[0]))

Why does this not break give the size of each element can be different (depending on whats stored in each of the two arrays?

The arrays are holding pointers whose size is constant regardless of the length of the string they're pointing to.

gfvalvo:
The arrays are holding pointers whose size is constant regardless of the length of the string they're pointing to.

Many Thanks. I understand.

WARNING: This line is dangerous:

#define SINGLE // comment out for single array

A #define causes a direct copy-and-paste of the first item with the second item. It happens in the compiler before the code is compiled.

Consider this

#define three 3 // This is the number 3

x = 2 + three + 4

The compiler sees:

x = 2 + 3 // This is the number 3 + 4

Note how the + 4 is commented out. The value of x is 5, not 9 because the got put 4 in the #define comment.

Put #define comments on separate lines!

kikiorg:
WARNING: This line is dangerous:

A #define causes a direct copy-and-paste of the first item with the second item. It happens in the compiler before the code is compiled.

Consider this

#define three 3 // This is the number 3

x = 2 + three + 4



The compiler sees:



x = 2 + 3 // This is the number 3 + 4



Note how the + 4 is commented out. The value of x is 5, not 9 because the got put 4 in the #define comment.

Put #define comments on separate lines!

...written by someone who couldn't be bothered to do a 30 second experiment to check what they were typing was bollocks.
(Hint: the compiler would have told you about your missing semicolon)

1 Like