Member 14157703 Ответов: 3

Что делать, когда у вас есть длинный список массивов для проверки?


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

HexSearch.cpp:
#include "HexSearch.h"

void searchFunction(int num, char msg[]) {

    static const char readReq[] = { 0x92 };                            
    static const char readResp[] = { 0x00, 0x02, 0x12, 0x34, 0xA1 };

    static const char writeReq[] = { 0x0A, 0xE0 };                     
    static const char writeResp[] = { 0x00, 0x02, 0x11, 0x01, 0x98 };

    static const char resetReq[] = { 0x00, 0xFF };                       
    static const char resetResp[] = { 0x00, 0x21, 0x23, 0x0E, 0xAE, 0x11, 0x3A };

    static const char verReq[] = {0x00, 0xA2};
    static const char verResp[] = {0x00, 0x03, 0x82, 0xAA, 0x07, 0x88, 0xA9};

    static const char typeReq[] = {0x00, 0x67};
    static const char typeResp[] = {0x00, 0x03, 0x00, 0x00, 0xC4, 0x77};

    static const char askReq[] = {0x00, 0x55};
    static const char askResp[] = {0x00, 0x01, 0xFE, 0xFF};

    if (num == 4) {
        replyMsg(msg, 2, 3,  readReq, readResp, sizeof(readResp) / sizeof(readResp[0]));
    }
    else if (num == 5) {
        replyMsg(msg, 2, 4, writeReq, writeResp, sizeof(writeResp) / sizeof(writeResp[0]));
        replyMsg(msg, 2, 4, resetReq, resetResp, sizeof(resetResp) / sizeof(resetResp[0]));
        replyMsg(msg, 2, 4, verReq, verResp, sizeof(verResp) / sizeof(verResp[0]));
        replyMsg(msg, 2, 4, typeReq, typeResp, sizeof(typeResp) / sizeof(typeResp[0]));
        replyMsg(msg, 2, 4, askReq, askResp, sizeof(askResp) / sizeof(askResp[0]));
    }
}

void replyMsg(char msg[], int startArr, int endArr, const char* receiv, const char* resps, int respL) {
    if (std::equal(msg + startArr, msg + endArr, receiv)) {
        for (int x = 0; x < respL; x++) {
            serialPC.putc(resps[x]);
        }
    }
}


Моя проблема заключается в том, что я не чувствую, что это хороший способ инициализации массивов символов. Я бы подумал, что можно, может быть, объявить их как отдельный файл, чтобы затем использовать в этой функции или что-то подобное? Я думаю, что мне кажется довольно грязным инициализировать их все в начале функции.

Что я уже пробовал:

Код работает и хорошо справляется со своей задачей, я просто хочу знать, есть ли лучший способ сделать это.

Richard MacCutchan

Поскольку вы объявили их всех как static и const, они будут созданы во время компиляции, так что не должно быть никаких проблем. Вы можете переместить Объявления за пределы функции для ясности, но это все.

Member 14157703

Хорошо спасибо

Rick York

Один совет : есть макрос, доступный с некоторыми компиляторами под названием _count_of или _countof или некоторые его вариации. Он определяется как :

#define _countof(a)  sizeof(a)/sizeof(a[0])
именно так вы и используете его в своей функции replyMsg. Это означает, что ваши звонки могут стать чем-то вроде этого :
replyMsg( msg, 2, 3, readReq, readResp, _countof( readResp ) );

Stefan_Lang

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

3 Ответов

Рейтинг:
1

CPallini

Не совсем то, что вы просили, но я думаю, что вы поймете идею

#include <cstdint>
#include <iostream>
#include <vector>
#include <map>

using bvect = std::vector<uint8_t>; // 'vector of bytes'

class Replier
{
  static std::map< bvect, bvect > m_reply_map;

public:
  static void reply( const bvect & msg)
  {
    auto  it = m_reply_map.find( msg );
    std::cout << "message: < ";
      for ( auto b : msg)
        std::cout << std::hex << static_cast<unsigned>(b) << " ";

    if ( it != m_reply_map.end())
    {
      std::cout << ">, reply: < ";
      for ( auto b : it->second)
        std::cout << std::hex << static_cast<unsigned>(b) << " ";
      std::cout << ">\n";
    }
    else
      std::cout << ">, no reply (unrecognized message)\n";
  }
};

std::map< bvect, bvect > Replier::m_reply_map =
  {
    { { 0x92 },       { 0x00, 0x02, 0x12, 0x34, 0xA1 } },
    { { 0x0A, 0xE0 }, { 0x00, 0x02, 0x11, 0x01, 0x98 } },
    { { 0x00, 0xFF }, { 0x00, 0x21, 0x23, 0x0E, 0xAE, 0x11, 0x3A } },
    { { 0x00, 0xA2 }, { 0x00, 0x03, 0x82, 0xAA, 0x07, 0x88, 0xA9 } },
    { { 0x00, 0x67 }, { 0x00, 0x03, 0x00, 0x00, 0xC4, 0x77 } },
    { { 0x00, 0x55 }, { 0x00, 0x01, 0xFE, 0xFF } }
  };


int main()
{
  Replier::reply( { 0x0A, 0xE0 } );
  Replier::reply( { 0x92 } );
  Replier::reply( { 0x00, 0xE0 } );
  Replier::reply( { 0x00, 0x67 } );
}


jeron1

ЛОЛ, по какой-то причине я знал, что это произойдет...
+5, я действительно люблю читать (и учиться на ваших ответах). :-)

CPallini

Большое спасибо. :-)

Rick York

Когда я вижу несколько экземпляров атипичного типа, я обычно добавляю для него typedef. В вашем решении я бы добавил :

typedef std::vector<uint8_t> vecuint8;
а затем используйте тот тип, где он появляется, который будет находиться в пяти местах.

CPallini

Действительно, это хорошая идея. Хотя я использовал "использование" (простите за каламбур).
Спасибо за предложение.

Рейтинг:
1

Gerry Schmitz

С вашим дизайном все в порядке.

Вы можете поместить все ваши константы в их собственный статический класс для лучшей "изоляции".

Все больше и больше программ получают "песочницу"; то есть мало или вообще нет доступа к файлам без согласия пользователя.

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

И строить таблицы в коде иногда проще, чем смотреть на абстрактные данные, а затем иметь с ними дело.


Рейтинг:
1

KarstenK

Это не так уж плохо, но когда C++ вы можете использовать некоторый дизайн класса, но также использовать статические переменные.

Подсказка: оператор sizeof разрешается компилятором, поэтому вы не получаете за него никакого штрафа за производительность.

Вы можете оптимизировать это, потому что начальное смещение является постоянным

replyMsg(msg, 2, ...
совет по дизайну: в этой функции нет обработки ошибок.


Rick York

Я согласен с вами. Кроме того, первая часть msg, похоже, игнорируется, поэтому я бы передал &msg[2] и начал проверку оттуда.