В поисках лучшего способа представления массивов без знака - PullRequest
0 голосов
/ 15 октября 2018

У меня есть куча объявлений вроде этого:

unsigned char configurePresetDelivery[] = { 0x7E, 0x01, 0x00, 0x20, 0x38, 0x0B, 0x04, 0x03, 0xF2, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3 };
unsigned char beginPresetDelivery[] = { 0x7E, 0x01, 0x00, 0x20, 0x3C, 0x01, 0x04, 0x2B };
unsigned char configureDirectDelivery[] = { 0x7E, 0x01, 0x00, 0x20, 0x37, 0x02, 0X03, 0XF2, 0xD5 };
...

Это команды, которые я отправляю на оборудование через последовательный порт.

Был бы лучший способпредставлять их?В структуре или классе или что-то?

Я ограничен C ++ 98.

Спасибо.

1 Ответ

0 голосов
/ 15 октября 2018

То, как вы представляете команды, будет в значительной степени зависеть от последовательности команд, которую будет отправлять ваша программа.

Если ваша программа полностью универсальна и должна иметь возможность отправлять буквально любую возможную последовательностьиз байтов, тогда const unsigned char массив (или const uint8_t, если вы хотите быть немного более явным), вероятно, путь.

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

Например, если вы точно знаете, что ваше последовательное устройство всегда требует, чтобы каждая команда начиналась с префикса 0x7E, 0x01, 0x00, 0x20, то вы можете сократить дублирование (и, следовательно, шансы созданияопечатка), удалив этот префикс из ваших последовательностей и автоматически добавив к нему функцию send, ввместо, например:

const unsigned char configurePresetDelivery[] = { 0x38, 0x0B, 0x04, 0x03, 0xF2, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3 };
const unsigned char beginPresetDelivery[]     = { 0x3C, 0x01, 0x04, 0x2B };
const unsigned char configureDirectDelivery[] = { 0x37, 0x02, 0X03, 0XF2, 0xD5 };

const unsigned char prefix[] = {0x7e, 0x01, 0x00, 0x20};

void send_prefix_and_command(const unsigned char * cmdWithoutPrefix, int numBytes)
{
   send(prefix, sizeof(prefix));
   send(cmdWithoutPrefix, numBytes);
}

[...]

send_prefix_and_command(configurePresetDelivery, sizeof(configurePresetDelivery));

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

// This is easier to do using std::vector, so I will use it
std::vector<unsigned char> generatePresetDataCommand(unsigned char presetID, unsigned short presetValue)
{
   // I'm totally making this up just to show an example
   std::vector<unsigned char> ret;
   ret.push_back(0x66);
   ret.push_back(0x67);
   ret.push_back(presetID);
   ret.push_back((presetValue>>8)&0xFF);  // store high-bits of 16-bit value into a byte
   ret.push_back((presetValue>>0)&0xFF);  // store low-bits of 16-bit value into a byte
   return ret;
}

// Convenience wrapper-function so later code can send a vector with less typing
void send_prefix_and_command(const std::vector<unsigned char> & vec)
{
   send_prefix_and_command(&vec[0], vec.size());
}

[...]

// The payoff -- easy one-liner sending of a command with little chance of getting it wrong
send_prefix_and_command(generatePresetDataCommand(42, 32599));
...