Название вашего вопроса наводит меня на мысль, что чего-то не хватает ни в вашем понимании массивов char
, ни в том, как вы задали вопрос.Часто людям трудно понять разницу между шестнадцатеричным символом или цифрой и представлением байта в памяти.Краткое объяснение:
Внутренне вся память просто двоичная.Вы можете представить (то есть отобразить его) в битах, ASCII, десятичном или шестнадцатеричном формате, но это не изменит то, что хранится в памяти.С другой стороны, поскольку память просто двоичная, символы всегда требуют кодировки символов.Это может быть Unicode или другие более экзотические кодировки, но обычно это просто ASCII.Поэтому, если вам нужна строка символов, независимо от того, пишут ли они шестнадцатеричное число, или предложение, или случайные буквы, они должны быть закодированы в ASCII.
Теперь тело вопроса можно легко решить:
AFAIK, нет способа "захватить" вывод Serial.println( b,HEX )
прагматично, поэтому вам нужно найти другой способ сделать ваше преобразование из шестнадцатеричных символов.getNum()
лямбда предоставляет прекрасную возможность.На данный момент он ничего не делает, но если вы настроите его так, чтобы персонаж '0'
превратился в число 0
, а персонаж 'f'
превратился в число 15
, и так далее, вы будете в порядке.на вашем пути.
Вот быстрый и грязный способ сделать это:
void setup() {
Serial.begin(9600);
char arr[] = "00000f01";
byte out[4];
byte arer[4];
auto getNum = [](char c){ return (c <= '9' ? c-'0' : c-'a'+10) ; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
int co=0;
//Check converted byte values.
for( byte b : out ){
Serial.println( co );
if(b < 0x10)
Serial.print('0');
Serial.println( b,HEX );
arer[co]=b;
co++;
}
}
void loop() {
}
Все, что я сделал, это изменил getNum
, чтобы он возвращал 0
для '0'
и 15
для 'f'
, и так далее между ними.Это происходит путем вычитания значения символа '0'
из символов '0'
до '9'
или вычитания значения символа 'a'
из символов 'a'
до 'f'
.К счастью, значения символов от '0'
до '9'
увеличиваются по одному за раз, как и символы от 'a'
до 'f'
.Обратите внимание, что это упадет, если вы введете 'F'
или что-то еще, но оно подойдет для примера, который вы показываете.
Когда я запускаю приведенный выше код на Uno, я получаю такой вывод:
0
00
1
00
2
0F
3
01
, который, кажется, вам нужен.
Эпилог
Чтобы продемонстрировать, как функции печати в C ++ могут сбить вас с пути относительно действительной ценности вещивы печатаете, рассмотрим cout
версию:
Если я скомпилирую и запусту следующий код на C ++ 14:
#include <iostream>
#include <iomanip>
#include <string>
typedef unsigned char byte;
int main()
{
char arr[] = "00000f01";
byte out[4];
byte arer[4];
auto getNum = [](char c){ return c ; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
int co=0;
//Check converted byte values.
for( byte b : out ){
std::cout << std::setfill('0') << std::setw(2) << std::hex << b;
arer[co]=b;
co++;
}
}
Я получу такой вывод:
00000f01
появляется, чтобы показать, что произошло преобразование из шестнадцатеричных символов.Но это только потому, что cout
игнорирует std::hex
и рассматривает b
как символ, который будет напечатан в ASCII.Поскольку строка "00000f01"
имеет '0'
в качестве первого символа в каждой паре, которая имеет шестнадцатеричное значение (0x30) с нулевым нижним значением nybble, (getNum( *idx++ ) << 4)
ничего не делает.Таким образом, b
будет содержать оригинальный второй символ в каждой паре, который при печати в ASCII выглядит как шестнадцатеричная строка.