如何将一个可变长度的十六进制字符串(例如"01A1"
)转换为包含该数据的字节数组。
即将此转换为:
std::string = "01A1";
变成这样
char* hexArray;
int hexLength;
或者这个
std::vector<char> hexArray;
我希望将其写入文件,并使用hexdump -C
命令,以便获取包含01A1
的二进制数据。
如何将一个可变长度的十六进制字符串(例如"01A1"
)转换为包含该数据的字节数组。
即将此转换为:
std::string = "01A1";
变成这样
char* hexArray;
int hexLength;
或者这个
std::vector<char> hexArray;
我希望将其写入文件,并使用hexdump -C
命令,以便获取包含01A1
的二进制数据。
我发现了这个问题,但是被接受的答案对我来说不像是用C++解决任务的方式(这并不意味着它是一个坏答案或者其他什么,只是解释了添加这个答案背后的动机)。我回忆起了这个好的答案,并决定实现类似的东西。这里是我最终得到的完整代码(它也适用于std::wstring
):
#include <cctype>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <stdexcept>
#include <string>
#include <vector>
template <typename OutputIt>
class hex_ostream_iterator :
public std::iterator<std::output_iterator_tag, void, void, void, void>
{
OutputIt out;
int digitCount;
int number;
public:
hex_ostream_iterator(OutputIt out) : out(out), digitCount(0), number(0)
{
}
hex_ostream_iterator<OutputIt> &
operator=(char c)
{
number = (number << 4) | char2int(c);
digitCount++;
if (digitCount == 2) {
digitCount = 0;
*out++ = number;
number = 0;
}
return *this;
}
hex_ostream_iterator<OutputIt> &
operator*()
{
return *this;
}
hex_ostream_iterator<OutputIt> &
operator++()
{
return *this;
}
hex_ostream_iterator<OutputIt> &
operator++(int)
{
return *this;
}
private:
int
char2int(char c)
{
static const std::string HEX_CHARS = "0123456789abcdef";
const char lowerC = std::tolower(c);
const std::string::size_type pos = HEX_CHARS.find_first_of(lowerC);
if (pos == std::string::npos) {
throw std::runtime_error(std::string("Not a hex digit: ") + c);
}
return pos;
}
};
template <typename OutputIt>
hex_ostream_iterator<OutputIt>
hex_iterator(OutputIt out)
{
return hex_ostream_iterator<OutputIt>(out);
}
template <typename InputIt, typename OutputIt>
hex_ostream_iterator<OutputIt>
from_hex_string(InputIt first, InputIt last, OutputIt out)
{
if (std::distance(first, last) % 2 == 1) {
*out = '0';
++out;
}
return std::copy(first, last, out);
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " hexstring" << std::endl;
return EXIT_FAILURE;
}
const std::string input = argv[1];
std::vector<unsigned char> bytes;
from_hex_string(input.begin(), input.end(),
hex_iterator(std::back_inserter(bytes)));
typedef std::ostream_iterator<unsigned char> osit;
std::copy(bytes.begin(), bytes.end(), osit(std::cout));
return EXIT_SUCCESS;
}
执行命令 ./hex2bytes 61a062a063 | hexdump -C
的输出结果为:
00000000 61 a0 62 a0 63 |a.b.c|
00000005
关于 ./hex2bytes 6a062a063 | hexdump -C
(注意字符数为奇数)的内容:
00000000 06 a0 62 a0 63 |..b.c|
00000005
unsigned int result;
sscanf(data, "%x", &result);
std::vector<std::byte> vec(...);
。std::string_view in("09e1c5f70a65ac519458e7e53f36");
auto view = in
| std::views::transform([](char c) {
// map ASCII characters onto hex digit numeric values
// (doesn't work correctly if c isn't a hex digit)
return c >= '0' && c <= '9' ? c - '0' : 10 + c - 'a';
})
| std::views::adjacent_transform<2>([](unsigned char hi, unsigned char lo) {
return std::byte(hi << 4 | lo);
});
// note: you might not even need the vector and could work with the view directly
// create a vector containing all the elements in the view
std::vector<std::byte> bytes(std::from_range, view);
// if std::from_range is not support yet:
std::vector<std::byte> bytes(view.begin(), view.end());
请查看在编译器资源管理器上的实时示例。
请注意,char
不适合作为“字节”类型;尽可能使用 std::byte
来代替。