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"
.
Я уверен, что это связано с той же проблемой "отсутствия нулевого терминатора", но я не уверен, как это исправить. Помощь приветствуется!!
@Chris Schmitz, 👍1
Обсуждение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
Самый простой способ упростить код - использовать 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
- форматирование строк в Arduino для вывода
- Проблемы с преобразованием byte[] в String
- Чтение строки, разделенной запятыми
- Использование строки вместо строки C, еще одна попытка затронуть загруженную проблему
- Разделение Serial.readString на массив строк
- Преобразование JSON в строку для MQTT
- Как заменить объекты String массивами символов, продолжая использовать строковые методы
- Использование c_str() для String для IPAddress с NTPClient дает неправильные значения
Либо я не понимаю вашего вопроса, либо вы сами на грани того, чтобы ответить на него., @timemage
Было бы лучше, если бы вы поместили код в свой вопрос как текст, а не как снимок экрана., @timemage