Function to check if received message matches any of the expected messages I have a message coming in and I need to match it against the expected messages. The program will eventually do something as a result of receiving those messages. I am not very experienced at programming, but surely there should be a better way to declare all those messages it can be in like a separate entity and then be able to use it within this HexSearch.cpp file? 

I tried to search how to do that but I couldn't find the right words to ask about this using a search engine. There is many more messages than those show here which still need to be declared but this is just a sample, which I don't like to look at already. 

#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 &lt; respL; x++) {
            serialPC.putc(resps[x]);
        }
    }
}


The code works. I am interested in improving it only. num is the total number of bytes of a message. E.g. readReq has one byte of data, but has also got 2 start bytes and 1 end byte so a total of 4. readResp array has the 2 start bytes, 2 data bytes, and one end byte and so it has a total size of 5 bytes. The 2nd byte is the one which specifies the length of a message. msg[] is the message coming in from a serial connection essentially.

As an example, if msg[] = { 0x00, 0x01, 0x92, 0x56 } then num = 4 and replyMsg will compare the 3rd byte to see that it matches readReq and so output readResp...
Unfortunately your code is incomplete and can't be run in this state. Still I want to recommend some improvements to this snippets.

My first impression from this code is that it looks like plain C, not C++  (besides the use of std::equal). 

To pass your Message and compare it you are using plain char arrays.
With this approach you have to also pass the size. You shouldn't feel the need for this in C++ any more. Check out containers such as std::array (fixed size) std::vector, std::string or std::string_view.

There's a bug which can make your program truncate the compared values depending on the platform:

static const char readReq[] = { 0x92 };


Consider that 0x92 = 146(int).

Not all platforms have char == unsigned char.  If you are not lucky it can mean char == signed char. See https://stackoverflow.com/questions/2054939/is-char-signed-or-unsigned-by-default

I found this by accident when I switched your plain C Array:

static const char readReq[] = { 0x92 }; 


To C++ std::vector:

const std::vector&lt;char&gt; readRequest = { 0x92 };


This doesn't event compile. The compiler complains that 0x92 truncates. So I changed it to:

const std::vector&lt;unsigned char&gt; readRequest = { 0x92 };


Then I thought probably it is event better to really declare your values as an array of constants. So I changed to std::array like this:

constexpr std::array&lt;unsigned char, 1&gt; readRequest = { 0x92 };
constexpr std::array&lt;unsigned char, 5&gt; readResponse = { 0x00, 0x02, 0x12, 0x34, 0xA1 


Now it is similar to the old macro defines in C but better because it follows the rules of the language.:

#define readRequest 0x92 


With std::array I refactored your code like this:

#include &lt;algorithm&gt;
#include &lt;array&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;

template&lt;typename MessageBegin, typename MessageEnd, typename ReceiveType, 
    typename ResponseType&gt;
void replyMessage(
    const MessageBegin&amp; messageBegin,
    const MessageEnd&amp; messageEnd,
    const ReceiveType&amp; receive,
    const ResponseType&amp; response)
{
    if (std::equal(messageBegin, messageEnd, receive.begin())) {
        for (const auto&amp; sign : response) {
            std::cout &lt;&lt; sign;
            //serialPC.putc(sign);
        }
    }
}

void searchFunction(int number, const std::vector&lt;unsigned char&gt;&amp; message)
{
    constexpr std::array&lt;unsigned char, 1&gt; readRequest = { 0x92 };
    constexpr std::array&lt;unsigned char, 5&gt; readResponse = { 0x00, 0x02, 0x12, 0x34, 0xA1 };

    constexpr std::array&lt;unsigned char, 2&gt; writeRequest = { 0x0A, 0xE0 };
    constexpr std::array&lt;unsigned char, 5&gt; writeResponse = { 0x00, 0x02, 0x11, 0x01, 0x98 };

    constexpr std::array&lt;unsigned char, 2&gt; resetRequest = { 0x00, 0xFF };
    constexpr std::array&lt;unsigned char, 7&gt; resetResponse = { 0x00, 0x21, 0x23, 0x0E, 0xAE, 0x11, 0x3A };

    constexpr std::array&lt;unsigned char, 2&gt; verReqeust = { 0x00, 0xA2 };
    constexpr std::array&lt;unsigned char, 7&gt; verResponse = { 0x00, 0x03, 0x82, 0xAA, 0x07, 0x88, 0xA9 };

    constexpr std::array&lt;unsigned char, 2&gt; typeRequest = { 0x00, 0x67 };
    constexpr std::array&lt;unsigned char, 6&gt; typeResponse = { 0x00, 0x03, 0x00, 0x00, 0xC4, 0x77 };

    constexpr std::array&lt;unsigned char, 2&gt; askRequest = { 0x00, 0x55 };
    constexpr std::array&lt;unsigned char, 4&gt; askResponse = { 0x00, 0x01, 0xFE, 0xFF };

    if (number == 4) {
        replyMessage(message.begin() + 2, message.begin() + 3, readRequest, readResponse);
    }
    else if (number == 5) {
        replyMessage(message.begin() + 2, message.begin() + 4, writeRequest, writeResponse);
        replyMessage(message.begin() + 2, message.begin() + 4, resetRequest, resetResponse);
        replyMessage(message.begin() + 2, message.begin() + 4, verReqeust, verResponse);
        replyMessage(message.begin() + 2, message.begin() + 4, typeRequest, typeResponse);
        replyMessage(message.begin() + 2, message.begin() + 4, askRequest, askResponse);
    }
}


In this code, other stuff was improved:


Cryptic names like msg, resps, respl or replyMsg were renamed. Sure, you can find out what they mean, but it is more stressful to read the code and get the meaning. Make a experiment. Forget the code for 6 months and come back to it. How long does it take you to get its meaning?
Functions can now accept Containers, which know their size. Also, we can simply iterate over them.


Compare this:

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 &lt; respL; x++) {
            serialPC.putc(resps[x]);
        }
    }
}


with this:

template&lt;typename MessageBegin, typename MessageEnd, typename ReceiveType, 
    typename ResponseType&gt;
void replyMessage(
    const MessageBegin&amp; messageBegin,
    const MessageEnd&amp; messageEnd,
    const ReceiveType&amp; receive,
    const ResponseType&amp; response)
{
    if (std::equal(messageBegin, messageEnd, receive.begin())) {
        for (const auto&amp; sign : response) {
            std::cout &lt;&lt; sign;
            //serialPC.putc(sign);  // btw what is this???
        }
    }
}


Besides the template, which we had to use because of different array sizes, which is easier to understand?