Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将十六进制字符串转换为字节数组_C++_String_Hex - Fatal编程技术网

C++ 将十六进制字符串转换为字节数组

C++ 将十六进制字符串转换为字节数组,c++,string,hex,C++,String,Hex,将可变长度十六进制字符串(例如,“01A1”转换为包含该数据的字节数组的最佳方式是什么 i、 e将此转换为: std::string = "01A1"; 进入这个 char* hexArray; int hexLength; 还是这个 std::vector<char> hexArray; std::向量六边形; 因此,当我将其写入一个文件并hextump-C它时,我会得到包含01A1的二进制数据,这应该可以工作: int char2int(char input) { i

将可变长度十六进制字符串(例如,
“01A1”
转换为包含该数据的字节数组的最佳方式是什么

i、 e将此转换为:

std::string = "01A1";
进入这个

char* hexArray;
int hexLength;
还是这个

std::vector<char> hexArray;
std::向量六边形;
因此,当我将其写入一个文件并
hextump-C
它时,我会得到包含
01A1

的二进制数据,这应该可以工作:

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;
  }
}
int char2int(字符输入)
{

如果(input>='0'&&input='A'&&input='A'&&input,我会使用标准函数,如
sscanf
,将字符串读入无符号整数,那么内存中就已经有了所需的字节。如果您使用的是big-endian机器,您可以直接写出(
memcpy
)从第一个非零字节开始的整数的内存。但是,通常不能安全地假设这一点,因此可以使用一些位屏蔽和移位来取出字节

const char* src = "01A1";
char hexArray[256] = {0};
int hexLength = 0;

// read in the string
unsigned int hex = 0;
sscanf(src, "%x", &hex);

// write it out
for (unsigned int mask = 0xff000000, bitPos=24; mask; mask>>=8, bitPos-=8) {
    unsigned int currByte = hex & mask;
    if (currByte || hexLength) {
        hexArray[hexLength++] = currByte>>bitPos;
    }
}

如果您可以使数据看起来像这样,例如“0x01”、“0xA1”数组 然后可以迭代数组并使用sscanf创建值数组

unsigned int result;
sscanf(data, "%x", &result);         

<>我发现了这个问题,但被接受的答案看起来不像是C++解决任务的方法(这并不意味着它是一个糟糕的答案或任何事情,只是解释了添加这一个的动机)。我回忆起并决定实现类似的事情。这里是我最后的代码。(它也适用于
std::wstring
):

/hex2bytes 6a062a063 | hexdump-C
(注意奇数字符):


十六进制到字符转换的困难在于十六进制数字是成对工作的,f.ex:3132或A0FF。因此,假设十六进制数字为偶数。但是,奇数数字可能完全有效,如:332和AFF,应理解为0332和0AFF

我建议对Niels Keurentjes hex2bin()函数进行改进。 首先,我们计算有效十六进制数字的数量。由于我们必须计算,我们还需要控制缓冲区大小:

void hex2bin(const char* src, char* target, size_t size_target)
{
    int countdgts=0;    // count hex digits
    for (const char *p=src; *p && isxdigit(*p); p++) 
        countdgts++;                            
    if ((countdgts+1)/2+1>size_target)
        throw exception("Risk of buffer overflow"); 
顺便说一下,要使用
isxdigit()
,您必须
#包括

一旦我们知道有多少个数字,我们就可以确定第一个数字是较高的数字(仅成对)还是不较高的数字(第一个数字不是成对的)

然后我们可以逐位循环,使用bin shift组合每一对。你说的“可变长度”。你的意思是什么

对于适合无符号长字符串的十六进制字符串,我一直喜欢C函数
strtoul
。使其将十六进制pass 16转换为基数值

代码可能如下所示:

#include <cstdlib>
std::string str = "01a1";
unsigned long val = strtoul(str.c_str(), 0, 16);
#包括
std::string str=“01a1”;
无符号长val=strtoul(str.c_str(),0,16);

如果您想使用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);

只需确保去掉字符串的任何前导“0x”。

此实现使用内置的
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;
}
std::vector HexToBytes(const std::string&hex){
std::向量字节;
for(无符号整数i=0;i
为了好玩,我很好奇是否可以在编译时进行这种转换。它没有太多的错误检查,是在VS2015中完成的,VS2015还不支持C++14 constexpr函数(HexChartPoint看起来就是这样)。它采用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");
#包括
#包括
#包括
#包括
/*从单个字符到其十六进制等效字符的快速脏转换*/
constexpr std::uint8_t hexChartPoint(字符输入)
{
返回
((输入>='a')&&(输入='a')&&&(输入='0')&&(输入C++11变量(使用gcc 4.7-小端格式):

#包括
#包括
标准::矢量解码十六进制(常量标准::字符串和源)
{
if(std::string::npos!=source.find_first_not_of(“0123456789abcdefabcddef”))
{
//您可以在这里抛出异常
返回{};
}
联盟
{
uint64_t二进制;
字符字节[8];
}值{};
自动大小=source.size(),偏移量=(大小%16);
std::向量二进制{};
二进制。保留((大小+1)/2);
如果(偏移)
{
value.binary=std::stoull(source.substr(0,偏移量),nullptr,16);
对于(自动索引=(偏移量+1)/2;索引--;)
{
binary.emplace_back(value.byte[index]);
}
}
对于(;偏移量<大小;偏移量+=16)
{
value.binary=std::stoull(source.substr(偏移量,16),nullptr,16);
对于(自动索引=8;索引--;)
{
binary.emplace_back(value.byte[index]);
}
}
返回二进制;
}
Crypto++变体(带有gcc 4.7):

#包括
#包括
#包括
#包括
标准::矢量解码十六进制(常量标准::字符串和源)
{
字符串十六进制码;
CryptoPP::StringSource(
来源,对,,
新的CryptoPP::HexDecoder(新的CryptoPP::StringSink(hexCode));
返回std::vector(hexCode.begin(),hexCode.end());
}
请注意,第一个变体的速度大约是第二个变体的两倍,同时处理奇数和偶数个半字节(“a56ac”的结果是{0x0a,0x56,0xac})。如果存在奇数个半字节(“a56ac”的结果是{0xa5,0x6a}),Crypto++将丢弃最后一个变体,并静默地跳过无效的十六进制字符(a5sac的结果是{0xa5,0xac})

'1'==0x31等。

输入:“303132”,输出:“012”。输入字符串可以是奇数或偶数长度
    for (*target=0; *src; ishi = !ishi)  {    
        char tmp = char2int(*src++);    // hex digit on 4 lower bits
        if (ishi)
            *target = (tmp << 4);   // high:  shift by 4
        else *target++ |= tmp;      // low:  complete previous  
    } 
  *target=0;    // null terminated target (if desired)
}
#include <cstdlib>
std::string str = "01a1";
unsigned long val = strtoul(str.c_str(), 0, 16);
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);
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;
}
#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");
    #include <string>
    #include <vector>

    std::vector<uint8_t> decodeHex(const std::string & source)
    {
        if ( std::string::npos != source.find_first_not_of("0123456789ABCDEFabcdef") )
        {
            // you can throw exception here
            return {};
        }

        union
        {
            uint64_t binary;
            char byte[8];
        } value{};

        auto size = source.size(), offset = (size % 16);
        std::vector<uint8_t> binary{};
        binary.reserve((size + 1) / 2);

        if ( offset )
        {
            value.binary = std::stoull(source.substr(0, offset), nullptr, 16);

            for ( auto index = (offset + 1) / 2; index--; )
            {
                binary.emplace_back(value.byte[index]);
            }
        }

        for ( ; offset < size; offset += 16 )
        {
            value.binary = std::stoull(source.substr(offset, 16), nullptr, 16);
            for ( auto index = 8; index--; )
            {
                binary.emplace_back(value.byte[index]);
            }
        }

        return binary;
    }
#include <string>
#include <vector>

#include <crypto++/filters.h>
#include <crypto++/hex.h>

std::vector<unsigned char> decodeHex(const std::string & source)
{
    std::string hexCode;
    CryptoPP::StringSource(
              source, true,
              new CryptoPP::HexDecoder(new CryptoPP::StringSink(hexCode)));

    return std::vector<unsigned char>(hexCode.begin(), hexCode.end());
}
#include <iostream>
#include <sstream>
#include <vector>

int main() {
    std::string s("313233");
    char delim = ',';
    int len = s.size();
    for(int i = 2; i < len; i += 3, ++len) s.insert(i, 1, delim);
    std::istringstream is(s);
    std::ostringstream os;
    is >> std::hex;
    int n;
    while (is >> n) {
        char c = (char)n;
        os << std::string(&c, 1);
        if(is.peek() == delim) is.ignore();
    }

    // std::string form
    std::string byte_string = os.str();
    std::cout << byte_string << std::endl;
    printf("%s\n", byte_string.c_str());

    // std::vector form
    std::vector<char> byte_vector(byte_string.begin(), byte_string.end());
    byte_vector.push_back('\0'); // needed for a c-string
    printf("%s\n", byte_vector.data());
}
123
123
123
char 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::runtime_error("Incorrect symbol in hex string");
};

string hex2str(string &hex)
{
    string out;
    out.resize(hex.size() / 2 + hex.size() % 2);

    string::iterator it = hex.begin();
    string::iterator out_it = out.begin();
    if (hex.size() % 2 != 0) {
        *out_it++ = char(char2int(*it++));
    }

    for (; it < hex.end() - 1; it++) {
        *out_it++ = char2int(*it++) << 4 | char2int(*it);
    };

    return out;
}
  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();
  }
#include <iostream>

using byte = unsigned char;

static int charToInt(char c) {
    if (c >= '0' && c <= '9') {
        return c - '0';
    }
    if (c >= 'A' && c <= 'F') {
        return c - 'A' + 10;
    }
    if (c >= 'a' && c <= 'f') {
        return c - 'a' + 10;
    }
    return -1;
}

// Decodes specified HEX string to bytes array. Specified nBytes is length of bytes
// array. Returns -1 if fails to decode any of bytes. Returns number of bytes decoded
// on success. Maximum number of bytes decoded will be equal to nBytes. It is assumed
// that specified string is '\0' terminated.
int hexStringToBytes(const char* str, byte* bytes, int nBytes) {
    int nDecoded {0};
    for (int i {0}; str[i] != '\0' && nDecoded < nBytes; i += 2, nDecoded += 1) {
        if (str[i + 1] != '\0') {
            int m {charToInt(str[i])};
            int n {charToInt(str[i + 1])};
            if (m != -1 && n != -1) {
                bytes[nDecoded] = (m << 4) | n;
            } else {
                return -1;
            }
        } else {
            return -1;
        }
    }
    return nDecoded;
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        return 1;
    }

    byte bytes[0x100];
    int ret {hexStringToBytes(argv[1], bytes, 0x100)};
    if (ret < 0) {
        return 1;
    }
    std::cout << "number of bytes: " << ret << "\n" << std::hex;
    for (int i {0}; i < ret; ++i) {
        if (bytes[i] < 0x10) {
            std::cout << "0";
        }
        std::cout << (bytes[i] & 0xff);
    }
    std::cout << "\n";

    return 0;
}
typedef uint8_t BYTE;

BYTE* ByteUtils::HexStringToBytes(BYTE* HexString, int ArrayLength)
{
  BYTE* returnBytes;
  returnBytes = (BYTE*) malloc(ArrayLength/2);
  int j=0;

  for(int i = 0; i < ArrayLength; i++)
  {
    if(i % 2 == 0)
    {
      int valueHigh = (int)(*(HexString+i));
      int valueLow =  (int)(*(HexString+i+1));

      valueHigh = ByteUtils::HexAsciiToDec(valueHigh);
      valueLow =  ByteUtils::HexAsciiToDec(valueLow);

      valueHigh *= 16;
      int total = valueHigh + valueLow;
      *(returnBytes+j++) = (BYTE)total;
    }
  }
  return returnBytes;
}

int ByteUtils::HexAsciiToDec(int value)
{
  if(value > 47 && value < 59)
  {
    value -= 48;
  }
  else if(value > 96 && value < 103)
  {
    value -= 97;
    value += 10;
  }
  else if(value > 64 && value < 71)
  {
    value -= 65;
    value += 10;
  }
  else
  {
    value = 0;
  }
  return value;
}
uint8_t buf[32] = {};
std::string hex = "0123";
while (hex.length() % 2)
    hex = "0" + hex;
std::stringstream stream;
stream << std::hex << hex;

for (size_t i= 0; i <sizeof(buf); i++)
    stream >> buf[i];
#include <stdio.h>
int main ()
{
    char hexdata[] = "48656c6c6f20746865726521";
    char bytedata[20]{};
    for(int j = 0; j < sizeof(hexdata) / 2; j++) {
        sscanf(hexdata + j * 2, "%02hhX", bytedata + j);
    }
    printf ("%s -> %s\n", hexdata, bytedata);
    return 0;
}
#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);
#pragma once

#include <memory>
#include <iostream>
#include <string>
#include <array>

#define DELIMITING_WILDCARD ' '

//  @sean :)
constexpr int _char_to_int( char ch )
{
    if( ch >= '0' && ch <= '9' )
        return ch - '0';

    if( ch >= 'A' && ch <= 'F' )
        return ch - 'A' + 10;

    return ch - 'a' + 10;
};

template <char wildcard, typename T, size_t N = sizeof( T )>
constexpr size_t _count_wildcard( T &&str )
{
    size_t count = 1u;
    for( const auto &character : str )
    {
        if( character == wildcard )
        {
            ++count;
        }
    }

    return count;
}

//  construct a base16 hex and emplace it at make_count
//  change 16 to 256 if u want the result to be when:
//  sig[0] == 0xA && sig[1] == 0xB = 0xA0B
//  or leave as is for the scenario to return 0xAB
#define CONCATE_HEX_FACTOR 16
#define CONCATE_HEX(a, b) ( CONCATE_HEX_FACTOR * ( a ) + ( b ) )

template
<   char skip_wildcard,
    //  How many occurances of a delimiting wildcard do we find in sig
    size_t delimiter_count,
    typename T, size_t N = sizeof( T )>
    constexpr auto _make_array( T &&sig )
{
    static_assert( delimiter_count > 0, "this is a logical error, delimiter count can't be of size 0" );
    static_assert( N > 1, "sig length must be bigger than 1" );

    //  Resulting byte array, for delimiter_count skips we should have delimiter_count integers
    std::array<int, delimiter_count> ret{};

    //  List of skips that point to the position of the delimiter wildcard in skip
    std::array<size_t, delimiter_count> skips{};

    //  Current skip
    size_t skip_count = 0u;

    //  Character count, traversed for skip
    size_t skip_traversed_character_count = 0u;
    for( size_t i = 0u; i < N; ++i )
    {
        if( sig[i] == DELIMITING_WILDCARD )
        {
            skips[skip_count] = skip_traversed_character_count;
            ++skip_count;
        }

        ++skip_traversed_character_count;
    }

    //  Finally traversed character count
    size_t traversed_character_count = 0u;

    //  Make count (we will supposedly have at least an instance in our return array)
    size_t make_count = 1u;

    //  Traverse signature
    for( size_t i = 0u; i < N; ++i )
    {
        //  Read before
        if( i == 0u )
        {
            //  We don't care about this, and we don't want to use 0
            if( sig[0u] == skip_wildcard )
            {
                ret[0u] = -1;
                continue;
            }

            ret[0u] = CONCATE_HEX( _char_to_int( sig[0u] ), _char_to_int( sig[1u] ) );
            continue;
        }

        //  Make result by skip data
        for( const auto &skip : skips )
        {
            if( ( skip == i ) && skip < N - 1u )
            {
                //  We don't care about this, and we don't want to use 0
                if( sig[i + 1u] == skip_wildcard )
                {
                    ret[make_count] = -1;
                    ++make_count;
                    continue;
                }

                ret[make_count] = CONCATE_HEX( _char_to_int( sig[i + 1u] ), _char_to_int( sig[i + 2u] ) );
                ++make_count;
            }
        }
    }

    return ret;
}

#define SKIP_WILDCARD '?'
#define BUILD_ARRAY(a) _make_array<SKIP_WILDCARD, _count_wildcard<DELIMITING_WILDCARD>( a )>( a )
#define BUILD_ARRAY_MV(a) _make_array<SKIP_WILDCARD, _count_wildcard<DELIMITING_WILDCARD>( std::move( a ) )>( std::move( a ) )

//  -----
//  usage
//  -----
template <int n>
constexpr int combine_two()
{
    constexpr auto numbers = BUILD_ARRAY( "55 8B EC 83 E4 F8 8B 4D 08 BA ? ? ? ? E8 ? ? ? ? 85 C0 75 12 ?" );
    constexpr int number = numbers[0];
    constexpr int number_now = n + number;
    return number_now;
}

int main()
{
    constexpr auto shit = BUILD_ARRAY( "?? AA BB CC DD ? ? ? 02 31 32" );
    for( const auto &hex : shit )
    {
        printf( "%x ", hex );
    }

    combine_two<3>();
    constexpr auto saaahhah = combine_two<3>();
    static_assert( combine_two<3>() == 88 );
    static_assert( combine_two<3>() == saaahhah );
    printf( "\n%d", saaahhah );
}