Доступ к полю структуры с использованием значения типа int или enum - PullRequest
2 голосов
/ 11 октября 2019

В настоящее время я использую систему ведения журнала, которая использует значение тега для определения параметра, который он будет хранить. Мы используем следующий формат: тег + время + значение.

Следующим шагом является получение зарегистрированного сообщения и его отправка на сервер с использованием буферов протокола для сериализации данных.

Буфер протокола .proto, предоставляет структуру со всеми полями, каждое из которых соответствует тегу в исходной системе ведения журналов.

Проблема возникает, когда мне нужно эффективно прочитать тег и присвоить значение полю вструктура буфера протокола. По сути, я хотел бы, например, взять тег 5 и найти поле 5 в структуре и записать значение.

Я знаю, что это можно сделать с помощью переключателей, но мы используем около 50теги, поэтому я хотел бы избежать этого решения, если это возможно. Я прилагаю пример структуры, чтобы проиллюстрировать проблему.

/* Struct definitions */
typedef struct _Profiles {
    int32_t param1;
    int32_t param2;
    int32_t param3;
    int32_t param4;
    int32_t param5;
    int16_t param6;
    int32_t param7;
    uint32_t param8;
    int32_t param9;
    int32_t param10;
    uint32_t param11;
    int32_t time;
/* @@protoc_insertion_point(struct:Profiles) */
} Profiles;

Ожидаемый результат будет в том, что я могу сохранить зарегистрированную строку, как показано ниже: 5 1345643 1500 (тег, время, значение)

в структуру буфера протокола:

profiles.param5 = 1500
profiles.time  = 1345643 

без необходимости в 12 случаях переключения (в этом примере). По сути, как я могу получить доступ к 5-му объявленному полю структуры, используя целое число / перечисление.

Имейте в виду, что каждое поле структуры может потенциально иметь различный тип.

Ответы [ 2 ]

4 голосов
/ 11 октября 2019

Мой подход будет иметь указатели на каждое из полей, как показано ниже.

int *ptr[11] = {&profiles.param1, &profiles.param2,  &profiles.param3,,,,,, &profiles.param11};

И когда сообщение прибудет, я обновлю поле, используя ptr.

  *ptr[tag-1] = 1500; //tag-1 because ptr[4] points to profiles.param5
2 голосов
/ 11 октября 2019

Улучшение предыдущего решения от @ kiran.

Если у вас несколько типов, вам нужно хранить пустые указатели. Но для приведения типов вам снова нужен регистр коммутатора.

Этого можно избежать двумя способами.

  1. Сохраните тип вместе с данными. т.е. хранить (tag, type, time, value). Тогда вы можете иметь ограниченное число условий для типов.

    void *ptr[11] = {&profiles.param1, &profiles.param2,  &profiles.param3,,,,,, &profiles.param11};
    
    switch (type)
    {
        case 0:
            *(char*)ptr[tag-1] = value;
            break;
        case 1:
            *(int*)ptr[tag-1] = value;
            break;
        ...
    }
    
  2. В качестве альтернативы вы можете иметь карту, в которой хранится тип значения

    void *ptr[11] = {&profiles.param1, &profiles.param2,  &profiles.param3,,,,,, &profiles.param11};
    char typearr[11] = {0,1,0,0....1};  // 0 for char, 1 for int etc
    
    type = typearr[tag-1];
    
    switch (type)
    {
       ...
    } 
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...