How to map a string to enum

Thread Starter

zazas321

Joined Nov 29, 2015
926
In my program, I have an enum that is used for indexing my array members. The reason is that it is much easier for me to understand which parameter I am accessing without knowing its index in the array
Code:
enum param_enum
{
    AA,
    AB,
    AC,
    AD,
    PARAM_COUNT
};


static int16_t parameters[PARAM_COUNT] =
{
    [AA] = 5,
    [AB] = 3,
    [AC] = 4,
    [AD] = 8,
};
I can then access any parameter for example:
Code:
parameters[AA] = 10; // Update AA parameter to value 10.
I will be receiving serial commands such as :
Code:
"AA:15"
When I receive this command, I must determine what parameter I need to modify based on the first 2 characters, then skip the 3rd character( because it is just ":" and I dont care about it) and the remaining characters will show the new value)

I wonder if there is any easier way to map the enum to a string

My current method:

Code:
// line holds the string data
// cmd_size is the length of string data

static void parse_data(uint8_t* data, uint16_t length){
    int16_t temp_var;
    char temp_storage[3]={0};
    if( strncmp((char*)data,"AA:",3) == 0 ){
    printf("AA: detect\n");
    for(int i = 3;i<=length; i++){
        temp_storage[i-3]=data[i];
        if(data[i] == 0){
            temp_var = strtol(temp_storage,NULL,10);
            printf("temp var is set to =%u \n",temp_var);
            parameters[AA] = temp_var;
        }
    }
}
}
The above method seems to work fine, However I do not think that this is the best possible solution. I wonder if it is possible to somehow map the string to the enum so that I can know which parameter I need to modify without perform annoying strcmp statements and etc. I hope to get some clarification on this.

If I have 50 parameters, that means that I will need to have to a strcmp block for each parameter which seems like really unconvenient. I hope its possible to do something like ( pseudo code:)
Code:
static void parse_data(uint8_t* data, uint16_t length){
    int16_t temp_var;
// pass data, length do the function and empty int16_t variable which will be assigned to a updated data
/* map_to_string will need to map string for example "AB" to the which number it corresponds in param_enum. For example "AB" should correspond to 1 according to:
enum param_enum
{
    AA, //0
    AB, //1
    AC,// 2
    AD,// 3
    PARAM_COUNT
};
*/
    parameter_to_change = map_string_to_enum(data,length,&temp_var) // map_string_to_enum returns parameter and data
    parameters[parameter_to_change ] = temp_var;
}
 

xox

Joined Sep 8, 2017
623
Having the enums start at zero helps a lot. In that case, maybe just a simple reverse-lookup table?

Code:
static const char* tags[PARAM_COUNT] = {
    [AA] = "AA",
    [AB] = "AB",
    [AC] = "AC",
    [AD] = "AD",
};

static void parse_data(uint8_t* data, uint16_t length) {
  for (int i = 0; i < PARAM_COUNT; ++i) {
    if (strncmp((char*)data, tags[i], 2) == 0 && data[2] == ':') {
      parameters[i] = strtol(data + 3, NULL, 10);
      printf("parameters[%s] is set to %d \n", tags[i], parameters[i]);
    }
  }
}
 

click_here

Joined Sep 22, 2020
471
There are a few ways of doing this, but the most obvious (to me) would be to make a struct that contains the a const enum value and the string literal. You would then make an array of them.

This would have the advantage of going one way or the other.
 
The table is the way to go. You don't really need to store the enum value, though. The table index can be used to locate the parameter to modify.


Code:
struct
{
  char cmd[2];
} table[] =
{{'A','A'},
{'A','C'},
{'X','Y'},
0};

for (int i = 0; table[i][0]; i++)
{
  if (data[0] == table[i][0] && data[1] == table[i][1])
  {
    parameter[i] = whatever;
    break;
  }
}
 

Thread Starter

zazas321

Joined Nov 29, 2015
926
Having the enums start at zero helps a lot. In that case, maybe just a simple reverse-lookup table?

Code:
static const char* tags[PARAM_COUNT] = {
    [AA] = "AA",
    [AB] = "AB",
    [AC] = "AC",
    [AD] = "AD",
};

static void parse_data(uint8_t* data, uint16_t length) {
  for (int i = 0; i < PARAM_COUNT; ++i) {
    if (strncmp((char*)data, tags[i], 2) == 0 && data[2] == ':') {
      parameters[i] = strtol(data + 3, NULL, 10);
      printf("parameters[%s] is set to %d \n", tags[i], parameters[i]);
    }
  }
}

Hello. I have been using the method that you have suggested and it seemed to work fine. However, there is a slight change that I made in terms of setting up parameters. I want to allow setting multiple parameters at once. For example:
I would write BLE command:

Code:
"AA:12,AB:20,AC:5"
The following command must set::
AA = 12
AB = 20
AC = 5

My current code:
Code:
bool parse_data(uint8_t* data, uint16_t length, uint16_t conn_id, uint32_t trans_id) {
  for (int i = 0; i < PARAM_COUNT; ++i) {
    if (strncmp((char*)data, reverse_table[i], 2) == 0 && data[2] == ':') {
        int16_t test_var = strtol( (const char*)(data+3), NULL, 10);
        printf("parameters[%s] is set to %d \n", reverse_table[i], test_var);
        Set_param(reverse_table[i],test_var);
        return true;
        }
  }
return false;
}
Could you suggest me how to parse a long string that is separated by "," ?
 
Last edited:

Thread Starter

zazas321

Joined Nov 29, 2015
926
Thanks for pointing me in the right direction. Way easier than I thought.

Code:
bool parse_data(uint8_t* data, uint16_t length, uint16_t conn_id, uint32_t trans_id) {
    char* pch;
    pch = strtok ((char*)data,",");
    while (pch != NULL)
    {
        printf ("%s\n",pch);
        for (int i = 0; i < PARAM_COUNT; ++i) {
            if (strncmp((char*)pch, reverse_table[i], 2) == 0 && pch[2] == ':') {
                int16_t test_var = strtol( (const char*)(pch+3), NULL, 10);
                printf("parameters[%s] is set to %d \n", reverse_table[i], test_var);
                Set_param( reverse_table[i],test_var);


            }
        }
        pch = strtok (NULL, ",");
    }
  return true;
  }
 

jiggermole

Joined Jul 29, 2016
50
I had a project a while ago that I was forced to brute force this kind of operation but it was python. So now thanks to strtok, which I had no clue about till now, I now will have to revisit that old project and shrink it significantly. Thanks for the involuntary, tangential help.
 
Top