HEX String to byte array
- Войдите на сайт для отправки комментариев
Чт, 15/01/2015 - 20:36
Добрый день!
Никак не могу найти решение:
Есть строка:
String s = "1942E560613C";
Как из нее получить подобное?:
Byte s[6] = { 0x19, 0x42, 0xE5, 0x60, 0x61, 0x3C };
посмотрите функцию sscanf, она сканирует из строки, но формат такой же как у потоковой scanf http://avr-libc.narod.ru/glibc-7.html#ss7.11
давно не применял, будет что-то типа такого, за корректность не ручаюсь, прочтете описание - сами подправите:
или так
Благодарю!
Сделал вот так:
String trs = "ABCDEF89"; byte dd[4]; char tr[8]; trs.toCharArray(tr, 8); for (int i = 0; i < 4; i++) sscanf(&tr[i * 2], "%2x", &dd[i]); dump_byte_array(dd, 4); Serial.println();В результате чуть чуть НЕ верно:
AB CD EF 08
Какое то смещение в конце !?
Возможно так (не пробовал):
Плюс что там в dump_byte_array неизвестно.
вы неправильно используете sscanf ибо она работает со строкой заканчивающейся нулем. А ваш массив tr нулем не заканчивается, такой код в принципе может привести к сбою программы.
Для корректности сделайте массив из 9 символов и в последний элемент запишите ноль
Да, по-моему так, но тоже не пробовал. :)
toCharArray копирует в буфер строку вместе с завершающим нулём, значит для нуля нужно тоже выделить место.
А вообще, в большинстве случаев нет смысла тратить драгоценную ардуиновскую память, и копировать строку в отдельный буфер. В объекте String точно такой же буфер уже есть, и есть метод для получения указателя на него:
Как-то так должно получиться:
Если sscanf будет ругаться, то так: (проверить сейчас не могу)
UPD: А для лентяев исходник:
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const { if (!bufsize || !buf) return; if (index >= len) { buf[0] = 0; return; } unsigned int n = bufsize - 1; if (n > len - index) n = len - index; strncpy((char *)buf, buffer + index, n); buf[n] = 0; }А чтобы не говорили, что это другой метод, выдержка из WString.h:
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const {getBytes((unsigned char *)buf, bufsize, index);}Надеюсь теперь понятно, что если указать 8, то в последний байт запишется '\0', а если сделать как я написал, то '\0' запишется в tr[9]; т.е. остальные 8 байт будут содержать нужные данные.
Точно, так оно и будет. :)
Но чтобы уж совсем точно - '\0' запишется всё-таки в tr[8], а остальные 8 байт - это байты с tr[0] по tr[7].
Точно, так оно и будет. :)
Но чтобы уж совсем точно - '\0' запишется всё-таки в tr[8], а остальные 8 байт - это байты с tr[0] по tr[7].
Это да, но кто хотел, тот понял правильно :)
Доброго времени суток !
scanf, умножение, Вам программы не под контроллеры 8-ми битные писать, а под win !
typedef struct { char a; char b; } Btype; char *str1={"12345678ABCDEF"}; // строка тестовая int convert(char *str,unsigned char *byte) // первый параметр указывает на массив символов, второй байт, возвращает колл-во байт { Btype *chp; chp = (Btype*)str; int i = 0; unsigned char c1,b1; while(chp[i].a) { c1=(chp[i].a >= 65)?55:48; b1 = (chp[i].a - c1) << 4; c1=(chp[i].b >= 65)?55:48; byte[i] = b1 | (chp[i].b - c1);i++; } return i; }в вашем случае вызывать
i1=convert(s.c_str(),bytes);
Да ладно, стыдно нам... :(
А давайте. Давайте мериться, этими самыми... умением двигать биты, да. :)
inline unsigned char toHex( char ch ) { return ( ( ch >= 'A' ) ? ( ch - 'A' + 0xA ) : ( ch - '0' ) ) & 0x0F; } // str - указатель на массив символов // bytes - выходной буфер // функция возвращает колл-во байт // int convert( char* str, unsigned char* bytes ) { unsigned char Hi, Lo; int i = 0; while( ( Hi = *str++ ) && ( Lo = *str++ ) ) { bytes[i++] = ( toHex( Hi ) << 4 ) | toHex( Lo ); } return i; }То же весьма красивое решение ! :)
А главное без вызова не нужных функций и долгих операторов. Дело не в мерятся, просто эти посты читают начинающие в основном программисты. По этому подсказывать лучше "правильные" решения. Они на начальном этапе должны учится экономить ресурс.
этапе должны учится экономить ресурс.
вы куда больше сэкономите если загоните строки в PROGMEM и откажетесь от использования форматирования в Serial
ну а все остальное вопрос компромиса между простотой и эффективностью. При применение sscanf просто и прозрачно и более универсально (можно делать разбор куда более сложных строк). Пример последний с самостоятельной конвертацией более эффективен, менее прозрачен, не универсален.
Даже С++ который использует ардуина это уже значительное перерасходование ресурсов, но зато удобно и упрощает многое и прощает многое новичкам. Впрочем и Си тоже чуть меньше жрет, но куда больше чем ассемблер. Общее правило - чем проще програмисту, тем сложнее железке и наоборот
И мой пример и Datak не припядствует использованию PROGMEM для хранения строк. sscanf использует строковый анализатор и еще с десяток функций которые для решения вопроса топикстартера не нужны (по этому функция сильно жирная и по размеру и по быстродействию). Приведенный алгоритм мне кажется достаточно прозрачным, хотя и не имеет защиты от дурака (выдаст не правильные данные при произвольном наборе символов), но мне кажется что для контроллера это нормально. И по моему скромному мнению - универсальность в программировании контроллеров это роскош. То есть, если очень надо - то можно, но лучше не частить.
Если универсальность это роскошь уходите с ардуино. Остальное все компромисс между решаемой задачей, имеющимися ресурсами и сложностью реализации