Эффективный синтаксический анализ массива в C

0

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

данных 32 байт. 1-й байт - это версия, 2-й и 3-й байты - порядковый номер и т.д., Как указано ниже.

void parsepacket(u8_t data[]) {
    u8_t version = data[0];
    u16_t sequence_number = ?;
    u16_t error_status = ?;
    u8_t command_type = ?;
    u8_t attribute_count = ?;
    u8_t pay_load[25] = ?;
}
  • 2
    вы должны использовать struct
  • 0
    payload - это одно слово, кстати.
Теги:
arrays
embedded
byte

4 ответа

1
Лучший ответ

Я думаю, это то, что вы ищете...

void parsepacket(const u8_t data[]) {  //same as u8_t*data
        u8_t version;
        u16_t sequence_number;
        u16_t error_status;
        u8_t command_type;
        u8_t attribute_count;
        u8_t pay_load[25];
        u8_t i =0;
        version = data[i];
        i++;
        sequence_number =(u16_t)(8<<data[i] + data[i+i]);
        i+=2;
        error_status = (u16_t)(8<<data[i] + data[i+i]);
        i+=2;
        attribute_count = data[i];
        i++;
        for(int j=0;j<25;j++)
          pay_load[j] = data[i++];
    }
  • 0
    Это эффективный способ?
  • 0
    Это предполагает порядок байтов Big Endian, который может или не может работать для вас.
Показать ещё 1 комментарий
0

Самый "эффективный" метод может зависеть от ряда факторов, таких как:

  • является ли порядок байтов в массиве таким же, как в u16_t,
  • является ли целевая машина разрешенными байтовыми 16-разрядными словами,
  • поддерживает ли ваш компилятор способ структурирования упаковки
  • насколько переносимым или машинным/компилятором вы хотите, чтобы код был.
  • нужно ли вам копировать данные или просто переинтерпретировать его с помощью наложенной структуры (нулевой копии)

Ответы на большинство этих сценариев уже были даны.

Тем не менее, это всего лишь 32 байта - насколько эффективно это действительно нужно? Возможно, вам лучше ориентироваться на ясность и переносимость производительности, если в любом случае она будет соответствовать вашим ограничениям производительности.

0

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

В gcc (вам может потребоваться проконсультироваться с руководством разработчика вашей цепочки инструментов), это было сделано с

struct __attribute__((__packed__)) foo {
     u8_t data;
     u16_t version;
     ...
     u8_t payload[25];

};

Вам также может потребоваться использовать код (посредством ASSERTING) для sizeof(struct foo) == 32. Это само по себе сложно сделать с препроцессором, но выполнимо (см. Комментарий также).

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

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

int data(char *input, size_t input_length, const char *fmt_string, void *result)
{
   switch (*fmt_string)
   {
       case '\0':  break;
       case 'b' : 
          *result = input++; break;
       case 'w' :
          result = align_to(result, sizeof(uint16_t));
          *(uint16_t *)result = get_word(input);
          input+=sizeof(uint16_t); break;
    }
}

Который будет анализировать, например, строку "bWWbb25b", где капитализация может опционально обозначать утверждение.

  • 0
    Здесь вопрос о порядке байтов выводится функции get_word ().
0

Массив для аналогичного типа данных, например, вы можете массировать тип данных u8_t или u16_t и т.д. В этом случае было бы хорошо, если бы вы передали его как ссылку на структуру, например

typedef struct {
u8_t version;
u16_t sequence_number;
u16_t error_status;
u8_t command_type;
u8_t attribute_count;
u8_t pay_load[25];
..
} data_seq;

void parsepacket(data_seq *input) {

}

data_seq * ptr_dataseq; назовите его, используя

parsepacket(&ptr_dataseq);
  • 0
    На самом деле я хочу проанализировать данные из «data []» или * data. Я сделал некоторые изменения в коде.
  • 0
    Это не работает из-за отсутствия атрибута «упаковано»; и даже тогда на некоторых архитектурах ЦП (часто во встроенном мире) строгое выравнивание предотвращает извлечение uint16_t из не выровненного адреса.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню