Alex_Golubev 0 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба Добрый день. Подскажите как проще всего распознать входную команду составленную из нескольких байт и выполнить необходимое действие? Пример. У нас на входе есть последовательность байт вида: пришла команда 0x01 0x02 0x01 -> вызываем обработчик команды 0x01 0x02 0x01 пришла команда 0x01 0x02 0x02 -> вызываем обработчик команды 0x01 0x02 0x02 пришла команда 0x01 0x02 0x03 -> вызываем обработчик команды 0x01 0x02 0x03 пришла команда 0x01 0x03 0x01 -> вызываем обработчик команды 0x01 0x03 0x01 пришла команда 0x03 0x03 0x01 -> вызываем обработчик команды 0x03 0x03 0x01 и так далее. На if else не охота будет много ветвлений и плохо читабельный код. С помощью хэш тоже не охота из - за коллизии. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба Через таблицу с шаблонами и указателями на обработчики. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Priest_89 8 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба if ((Command[0]==0x01)&&(Command[1]==0x02)&&(Command[2]==0x01)) { //обработчик } else if ((Command[0]==0x01)&&(Command[1]==0x02)&&(Command[2]==0x02)) { //обработчик } Где тут проблема с читаемостью? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 18 minutes ago, Priest_89 said: Где тут проблема с читаемостью? 1. Неудобно выискивать и проверять коды в тексте 2. Забитые вручную индексы - лишний источник опечаток 3. Про скобки вообще молчу По-моему, так много лучше: { {0x01, 0x02, 0x03, &f1}, {0x01, 0x01, 0x03, &f2}, {0x02, 0x02, 0x03, &f3}, } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arhiv6 18 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба Соглашусь с aaarrr, лучше соответствие всех команд и их кодов описать в одном месте, например: void command_a(); void command_b(); // функции-обработчики команд void command_c(); typedef struct // структура, объединяющая массив с кодом команды и функцией-обработчиком { char code[3]; void (*pfunc)(); } Command; Command commands[] = // всё описано в одном месте { {{0x01, 0x02, 0x01}, command_a}, {{0x01, 0x02, 0x02}, command_b}, {{0x01, 0x03, 0x01}, command_c}, }; bool parse_command(char *input_command) { int commadns_number = sizeof(commands) / sizeof(commands[0]); for (int i = 0; i < commadns_number; i++) // ищем в списке команд { if (memcmp(input_command, commands[i].code, 3)) { commands[i].pfunc(); // вызов функции-обработчика return true; } } return false; // команда не найдена в списке комманд } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба Если формат пакета фиксированый и не планируется его расширение как по формату, так и по функциям - табличный вариант, который приводили выше. Я бы также не исключал switch-case в этом случае. Если формат "изменчивый", то, IMHO, будет не просто его описать в унифицированной таблице или она будет очень избыточной. Если формат пакетов меняется (дополняется), и требуется потоковая обработка принятых байт "на лету" (например в векторе прерывания) опять же IMHO, принимаемые байты считать событиями для FSM. Как будет FSM реализовано - на switch или иначе - не принципиально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба Спасём отца русской демократии: enum { API_K_type, API_K_cfg, API_K_addr, API_K_success, API_K_error, API_K_version, API_K_title, API_K_dive, API_K_scale, API_K_mode, API_K_min, API_K_max, API_K_offset, ... API_K_n }; #define apiKeyLen 12 //[байт] char const apiKeys[apiKeyLen * API_K_n + 1] __attribute__ ((aligned (4))) = "type " //API_K_type "cfg " //API_K_cfg "addr " //API_K_addr "success " //API_K_success "error " //API_K_error "version " //API_K_version "title " //API_K_title "dive " //API_K_dive "scale " //API_K_scale "mode " //API_K_mode "min " //API_K_min "max " //API_K_max "offset " //API_K_offset ... ; void (* const cmdHandler[API_K_n])(char const *cmdTail) = { CmdType, //API_K_type CmdCfg, //API_K_cfg CmdAddr, //API_K_addr ... }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 75 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 1 hour ago, arhiv6 said: Соглашусь с aaarrr, лучше соответствие всех команд и их кодов описать в одном месте, например: а потом ещё заменить перебор на бинарный поиск. и если ограничиться 3-4 байтными командами, то среди uint32_t значений 0x010102, 0x010201, ... а не строк. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 22 minutes ago, jcxz said: Спасём отца русской демократии: . . . enum { API_K_type, API_K_cfg, API_K_addr, API_K_success, API_K_error, API_K_version, API_K_title, API_K_dive, API_K_scale, API_K_mode, API_K_min, API_K_max, API_K_offset, ... API_K_n }; struct_array[] = { [API_K_type] = { 0x01, 0x02, 0x03, &fun_1 }, [API_K_cfg] = { 0x21, 0x12, 0x13, &fun_2 }, [API_K_addr] = { 0x31, 0x22, 0x23, &fun_3 }, . . . . } Это "прокатывает" для IAR. Очень удобный формат, можно произвольно добавлять-удалять занчения из enum, менять местами очередность итп. Если ошибка - ее покажет сразу компилятор, а не придется юлозить исходник и искать места, где требуется поменять индексы массива. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 2 hours ago, k155la3 said: Это "прокатывает" для IAR И для gcc (откуда, собственно, "это" пришло), и для чего угодно современного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 4 hours ago, aaarrr said: По-моему, так много лучше: { {0x01, 0x02, 0x03, &f1}, {0x01, 0x01, 0x03, &f2}, {0x02, 0x02, 0x03, &f3}, } Алгоритм полного перебора? Полагаете три байта на команду сделано для того чтобы три команды передать. И ТС про хэши вспомнил просто потому что слово такое знает? Что-то мне кажется вопрос не так прост. Начать надо как минимум с n-D таблицы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 7 minutes ago, AlexandrY said: Полагаете три байта на команду сделано для того чтобы три команды передать. Мне известны в том числе и такие протоколы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 17 minutes ago, aaarrr said: Мне известны в том числе и такие протоколы. Ну и мне известны. Это обычный CAN. Но делать табличный поиск простым перебором в CAN-е - последнее дело. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 7 января, 2019 Опубликовано 7 января, 2019 · Жалоба 1 hour ago, AlexandrY said: Начать надо как минимум с n-D таблицы. Поясните наглядным примером. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 8 января, 2019 Опубликовано 8 января, 2019 · Жалоба 14 hours ago, Alex_Golubev said: Добрый день. С помощью хэш тоже не охота из - за коллизии. Добрый день! Если памяти не жалко, можете std::map использовать. Ключом будет ваша последовательность из трёх байт, а вторым параметром указатель на обработчик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться