Разобрать mac-строку char* в массив uint8_t
Мне нужно обработать строку, поступающую через UART и содержащую кучу информации, часть которой — это MAC-адрес, который я получаю с помощью String.substring(a, b), возвращающего 12-символьную строку, представляющую mac-адрес. адрес "B8C9A45BA770"
<- (просто пример).
Мне нужно, чтобы формат mac-адреса был массивом uint8_t, вот так
{ 0xB8, 0xC9, 0xA4, 0x5B, 0xA7, 0x70
.
Итак, мне нужна функция для преобразования строки в uint8_t*. К сожалению, я понятия не имею, как это преобразовать. Должен же быть простой путь, верно? это "C8"; до 0xC8 и так далее...
Есть идеи по этому поводу?
@Harald Lesan, 👍1
Обсуждение1 ответ
Лично я бы выбрал базовую реализацию, подобную этой.
const uint8_t MAC_length = 6;
uint8_t* MAC_buffer[6];
uint8_t fromHexChar(char c)
{
uint8_t result = 0
if ((c >= '0') && (c <= '9'))
result = c - '0';
else if ((c >= 'A') && (c <= 'F'))
result = 10 + c - 'A';
else if ((c >= 'a') && (c <= 'f'))
result = 10 + c - 'a';
return result
}
uint8_t* toMAC(String s)
{
for (uint8_t i = 0; i < MAC_length; i++)
{
MAC_buffer[i] = (fromHexChar(s.charAt(2*i)) << 4) | fromHexChar(s.charAt(2*i + 1));
}
return MAC_buffer;
}
Возможно, его можно оптимизировать, но это настолько простая работа, и ее нужно использовать так редко, что я думаю, этого достаточно.
Важно: я не тестировал этот код, поэтому внутри могут быть ошибки.
Если вам нужно начать с произвольной точки строки, а не с самого начала, вам просто нужно изменить ее следующим образом:
uint8_t* toMAC(String s, uint8_t startIdx)
...
MAC_buffer[i] = fromHexChar(s.charAt(2*i + startIdx)) << 4 | fromHexChar(s.charAt(2*i + startIdx + 1));
Примечание для себя на будущее: я проверял как на симуляторе, так и в коде, и charAt
безопасно использовать, даже если индекс находится за пределами границ строки (он просто возвращает 0).
Большое спасибо! Надеюсь, я смогу опробовать это в своем коде сегодня, если нет, то на следующей неделе :), @Harald Lesan
Однако у меня есть вопрос: почему вы используете глобальные переменные в этом случае? Не лучше ли было бы иметь чистую функцию, удалив буфер из глобальной области видимости и добавив его в функцию toMAC? В любом случае это то, что я изменил, @Harald Lesan
@HaraldLesan: Если вы сделаете MAC_buffer локальным для toMAC(), вам придется сделать его статическим, иначе вы получите обратно указатель на нераспределенное пространство стека, которое вы не сможете разыменовать (это неопределенное поведение). Но тогда toMAC()
не является чистым. Если вы действительно хотите, чтобы он был чистым, заставьте его возвращать массив, инкапсулированный внутри структуры., @Edgar Bonet
Спасибо @EdgarBonet, ваш вклад, как всегда, является отличным дополнением :) никогда не думал об инкапсуляции в структуры, мне придется копнуть немного глубже, @frarugi87
@HaraldLesan Как сказал Эдгар, помещение его внутрь функции удалит его из памяти при выходе из функции, поэтому вы не сможете использовать его снаружи. Если вы действительно хотите избежать этого глобального значения, я бы использовал решение — выделить его снаружи и передать функции: uint8_t* toMAC(String s, uint8_t *MAC_buffer, uint8_t MAC_length)
. Но вообще говоря, я избегаю динамической памяти в uC, поэтому обычно буферы в моем коде глобальные., @frarugi87
Возможно, я придираюсь, но charToHex
, вероятно, следует называть fromHexChar
или что-то подобное. Мы не конвертируем ничего из __to__ hex, мы конвертируем __from__ hex., @tkausl
@tkausl, честно говоря, у меня была похожая мысль при написании, но я не нашел ни одного допустимого имени (это символ целого числа, но как выразить, что оно должно быть в шестнадцатеричном формате?). Я не додумался назвать это «от» чего-то. Я меняю :) спасибо, @frarugi87
@frarugi87: Вы все равно можете выделить буфер снаружи и передать его вызываемой функции без использования кучи. Просто его время жизни должно быть больше, чем у вызываемой функции. Если буфер является локальным для вызывающей функции, а) он все равно будет невидим для других функций; б) не будет использовать кучу; и c) будет освобождено при возврате вызывающей функции., @JRobert
@JRobert Да, модификация, позволяющая выделить его снаружи и просто передать в функцию, была тем, что я написал в комментарии выше. Спасибо за ваш комментарий :), @frarugi87
Это было сделано специально для решения проблемы «избегания динамической памяти».; эта автоматическая память — еще один неглобальный вариант., @JRobert
- Проблемы с преобразованием byte[] в String
- форматирование строк в Arduino для вывода
- Как преобразовать строку в массив байтов
- Преобразование строки в IP-адрес
- Чтение строки, разделенной запятыми
- Использование строки вместо строки C, еще одна попытка затронуть загруженную проблему
- Разделение Serial.readString на массив строк
- Преобразование JSON в строку для MQTT
Вы можете использовать sscanf, @Volkan Ünal
Было бы легче увидеть ваше замешательство, если бы вы действительно показали какой-нибудь код., @Rohit Gupta
Добро пожаловать в SE/Arduino! Пожалуйста, посетите [тур], чтобы узнать, как работает этот сайт, и прочитайте «[спросить]». Большую часть исследований вы должны провести самостоятельно. Поэтому, пожалуйста, [отредактируйте] свой вопрос и добавьте, что выявило ваше исследование и почему оно вам не помогло. Подсказка: быстрый поиск в Интернете по запросу «Преобразование строки в целое число в C++» дает много хороших результатов..., @the busybee