将可变长度十六进制字符串转换为"01A1"包含该数据的字节数组的最佳方法是什么.
即转换这个:
std::string = "01A1";
Run Code Online (Sandbox Code Playgroud)
进入这个
char* hexArray;
int hexLength;
Run Code Online (Sandbox Code Playgroud)
或这个
std::vector<char> hexArray;
Run Code Online (Sandbox Code Playgroud)
所以当我把hexdump -C它写入文件时,我得到包含的二进制数据01A1.
Nie*_*jes 31
这应该工作:
int char2int(char input)
{
if(input >= '0' && input <= '9')
return input - '0';
if(input >= 'A' && input <= 'F')
return input - 'A' + 10;
if(input >= 'a' && input <= 'f')
return input - 'a' + 10;
throw std::invalid_argument("Invalid input string");
}
// This function assumes src to be a zero terminated sanitized string with
// an even number of [0-9a-f] characters, and target to be sufficiently large
void hex2bin(const char* src, char* target)
{
while(*src && src[1])
{
*(target++) = char2int(*src)*16 + char2int(src[1]);
src += 2;
}
}
Run Code Online (Sandbox Code Playgroud)
根据您的特定平台,可能还有一个标准的实现.
Chr*_*lli 21
此实现使用内置strtol函数来处理从文本到字节的实际转换,但适用于任何偶数长度的十六进制字符串.
std::vector<char> HexToBytes(const std::string& hex) {
std::vector<char> bytes;
for (unsigned int i = 0; i < hex.length(); i += 2) {
std::string byteString = hex.substr(i, 2);
char byte = (char) strtol(byteString.c_str(), NULL, 16);
bytes.push_back(byte);
}
return bytes;
}
Run Code Online (Sandbox Code Playgroud)
小智 8
所以为了好玩,我很好奇我是否可以在编译时进行这种转换.它没有很多错误检查,并且在VS2015中完成,它不支持C++ 14 constexpr函数(因此HexCharToInt看起来如何).它采用c字符串数组,将字符对转换为单个字节,并将这些字节扩展为统一初始化列表,用于初始化作为模板参数提供的T类型.T可以替换为类似std :: array的东西来自动返回一个数组.
#include <cstdint>
#include <initializer_list>
#include <stdexcept>
#include <utility>
/* Quick and dirty conversion from a single character to its hex equivelent */
constexpr std::uint8_t HexCharToInt(char Input)
{
return
((Input >= 'a') && (Input <= 'f'))
? (Input - 87)
: ((Input >= 'A') && (Input <= 'F'))
? (Input - 55)
: ((Input >= '0') && (Input <= '9'))
? (Input - 48)
: throw std::exception{};
}
/* Position the characters into the appropriate nibble */
constexpr std::uint8_t HexChar(char High, char Low)
{
return (HexCharToInt(High) << 4) | (HexCharToInt(Low));
}
/* Adapter that performs sets of 2 characters into a single byte and combine the results into a uniform initialization list used to initialize T */
template <typename T, std::size_t Length, std::size_t ... Index>
constexpr T HexString(const char (&Input)[Length], const std::index_sequence<Index...>&)
{
return T{HexChar(Input[(Index * 2)], Input[((Index * 2) + 1)])...};
}
/* Entry function */
template <typename T, std::size_t Length>
constexpr T HexString(const char (&Input)[Length])
{
return HexString<T>(Input, std::make_index_sequence<(Length / 2)>{});
}
constexpr auto Y = KS::Utility::HexString<std::array<std::uint8_t, 3>>("ABCDEF");
Run Code Online (Sandbox Code Playgroud)
您可以使用提升:
#include <boost/algorithm/hex.hpp>
char bytes[60] = {0};
std::string hash = boost::algorithm::unhex(std::string("313233343536373839"));
std::copy(hash.begin(), hash.end(), bytes);
Run Code Online (Sandbox Code Playgroud)
你说的是“可变长度”。你的意思是多变?
对于适合 unsigned long 的十六进制字符串,我一直喜欢 C 函数strtoul。要使其转换为十六进制,请传递 16 作为基值。
代码可能如下所示:
#include <cstdlib>
std::string str = "01a1";
unsigned long val = strtoul(str.c_str(), 0, 16);
Run Code Online (Sandbox Code Playgroud)
这可以通过 a 来完成stringstream,您只需将值存储在中间数字类型中,例如 an int:
std::string test = "01A1"; // assuming this is an even length string
char bytes[test.length()/2];
stringstream converter;
for(int i = 0; i < test.length(); i+=2)
{
converter << std::hex << test.substr(i,2);
int byte;
converter >> byte;
bytes[i/2] = byte & 0xFF;
converter.str(std::string());
converter.clear();
}
Run Code Online (Sandbox Code Playgroud)
如果你想使用 OpenSSL 来做到这一点,我发现了一个漂亮的技巧:
BIGNUM *input = BN_new();
int input_length = BN_hex2bn(&input, argv[2]);
input_length = (input_length + 1) / 2; // BN_hex2bn() returns number of hex digits
unsigned char *input_buffer = (unsigned char*)malloc(input_length);
retval = BN_bn2bin(input, input_buffer);
Run Code Online (Sandbox Code Playgroud)
只要确保去掉字符串的任何前导'0x'。