strcmp, похоже, не работает

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

Я получаю данные для массива char в виде набора байтов и компилирую их в массив char следующим образом:

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

Поэтому, захватывая каждый из ASCII-кодов и преобразуя его в символ, я добавляю его в буфер.

После этого я пытаюсь распечатать буфер на мониторе, а затем сравнить его со строкой. Хотя это не работает:

Я знаю, что получаю все эти дополнительные символы в println b / c буфер не заканчивается на 0, поэтому print продолжает считывать байты памяти, пока не достигнет нуля, но я не знаю, почему strcmp не показывает буфер, соответствующий строке "ravenclaw".

Я уверен, что это связано с той же проблемой "отсутствия нулевого терминатора", но я не уверен, как это исправить. Помощь приветствуется!!

, 👍1

Обсуждение

Либо я не понимаю вашего вопроса, либо вы сами на грани того, чтобы ответить на него., @timemage

Было бы лучше, если бы вы поместили код в свой вопрос как текст, а не как снимок экрана., @timemage


2 ответа


Лучший ответ:

2

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

Вы можете просто не рассматривать полезную нагрузку как строку, а вместо этого использовать memcmp, как в:

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

memcmp ведет себя аналогично strcmp, за исключением того, что он не ищет нулевой терминатор. Он просто сравнивает, сколько байтов (символов) вы укажете. На практике вы можете использовать переменную для хранения "ravenclaw" и strlen() на ней, а не указывать длину отдельно, как я сделал выше, например:

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

или любое количество вариаций того, что может использовать strlen(), или указатель, а не массив (если не используется sizeof), или PROGMEM с strlen_P() и memcmp_P() или ... и т. Д., И т. Д., Возможно, поместив это в функцию, чтобы вы могли повторно использовать ее.


В качестве дополнительного примечания, если вы знаете, что полезная нагрузка содержит ненулевой текст, который вы хотите напечатать, вы можете использовать перегрузку write(), которая позволяет указать длину.

Serial.write(payload, length);
,

Ах, потрясающе, спасибо за дополнительную информацию. Я не знал о memcmp. Этот def кажется лучшим способом сделать сравнение., @Chris Schmitz


2

Самый простой способ упростить код - использовать strcpy для создания буфера, длина которого на 1 байт больше длины, а затем завершить его с помощью \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");
}
,

о, здорово! Мне нравится этот взгляд на вещи. TBH Я думал, что попробовал это в какой-то момент, и это не сработало, хотя в то время я много работал, так что, возможно, я испортил свой код. спасибо за подсказку!, @Chris Schmitz

Ах, загвоздка в том, что после приведения к указателю const char вы ничего не можете к нему добавить. В итоге вы получаете недопустимое преобразование из `const char*' в 'char', buffer [length] = "\ 0"., @Chris Schmitz

@ChrisSchmitz, вы, кажется, упустили то, что в своем коде они использовали `\ 0", а не "\ 0", одинарную, а не двойную кавычку. Терминатор - это один символ, записываемый в один символ массива символов. Он * должен * скомпилировать любой Arduino с использованием g ++, то есть все, что я знаю; локальный массив размером с время выполнения использует расширение g ++., @timemage

@ChrisSchmitz Однако, если вы хотите попробовать этот способ сделать это, ** вам нужно поменять строку strcpy() и заменить ее на memcpy(buffer, payload, length);** В противном случае strcpy может переполнить buffer, потому что полезная нагрузка это, опять же, не прекращается. Таким образом, нет ничего, чтобы сказать strcpy" остановиться, кроме следующего "\ 0", который он находит в памяти после "полезной нагрузки., @timemage