1

I'm trying to compare a char array that I'm assembling to a string and I'm having trouble comparing the strings.

I'm getting the data for the char array as a set of bytes and I'm compiling it into a char array like this:

void messageHandler(char *topic, byte *payload, unsigned int length)
{
  char buffer[length];
  for (int i = 0; i < length; i++)
  {
    buffer[i] = (char)payload[i];
  }

So grabbing each of the ASCII codes and converting it into a character as I add it to the buffer.

After I do that I'm trying to print the buffer to the monitor and then compare it to a string. Though it's not working:

enter image description here

I know I'm getting all of those extra characters in the println b/c the buffer doesn't end in 0 so print keeps reading out memory bytes till it hits the zero, but I don't know why strcmp isn't showing the buffer matching the string "ravenclaw".

I'm sure it's for the same "missing the null terminator" issue, but I'm not sure how to fix it. Help is appreciated!!

victcdva
  • 5
  • 3
Chris Schmitz
  • 357
  • 6
  • 18

2 Answers2

2

You seem to already understand that it's not null-terminated and that's why it's not working the way you expect. So, I'll take a different tact for "how to fix it".

You can simply not treat the payload as a string, and instead use memcmp, as in:

if (length == 9 && memcmp(payload, "ravenclaw", 9) == 0) {

memcmp behaves similarly to strcmp, except that it isn't looking for a null terminator. It just compares however many bytes (chars) you specify. In practice you may want to use a variable to hold "ravenclaw" and to strlen() on it rather than specifying the length separately as I've done above, e.g.:

static const char ravenclaw[] = "ravenclaw";
static const size_t ravenclaw_len = sizeof ravenclaw - 1;
if (length == ravenclaw_len && memcmp(payload, ravenclaw, ravenclaw_len) == 0) {

or any number of variations on that which might use strlen(), or a pointer rather than array (if not using sizeof) or PROGMEM with strlen_P() and memcmp_P() or... etc, etc, possibly putting this into a function so you can reuse it.


As a side note, if you know payload contains non-null-terminated text that you want to print, you can use the overload of write() that allows you to specify the length.

Serial.write(payload, length);
timemage
  • 5,639
  • 1
  • 14
  • 25
2

The easier way to simply the code is to use strcpy to create a buffer that is 1 byte longer than the length and then terminate it with \0.

void messageHandler(char *topic, byte *payload, unsigned int length) {
  char buffer[length+1];
  strcpy(buffer, (const char*) payload);
  buffer[length] = '\0';

Serial.println(buffer);

int matched = strcmp(buffer, "ravenclaw"); }

hcheung
  • 1,933
  • 8
  • 15