简体   繁体   English

将无符号字符 * 转换为十六进制字符串

[英]Converting unsigned char * to hexstring

Below code takes a hex string(every byte is represented as its corresponidng hex value) converts it to unsigned char * buffer and then converts back to hex string.下面的代码采用一个十六进制字符串(每个字节都表示为其相应的十六进制值)将其转换为 unsigned char * 缓冲区,然后再转换回十六进制字符串。 This code is testing the conversion from unsigned char* buffer to hex string which I need to send over the network to a receiver process.此代码正在测试从 unsigned char* 缓冲区到十六进制字符串的转换,我需要通过网络将其发送到接收器进程。 I chose hex string as unsigned char can be in range of 0 to 255 and there is no printable character after 127. The below code just tells the portion that bugs me.我选择了十六进制字符串,因为 unsigned char 可以在 0 到 255 的范围内,并且在 127 之后没有可打印的字符。下面的代码只是告诉我困扰我的部分。 Its in the comment.它在评论中。

#include <iostream>
#include <sstream>
#include <iomanip>

using namespace std;
// converts a hexstring to corresponding integer. i.e "c0" - > 192
int convertHexStringToInt(const string & hexString)
{
  stringstream geek;
  int x=0;

  geek << std::hex << hexString;
  geek >> x;

  return x;
}

// converts a complete hexstring to unsigned char * buffer
void convertHexStringToUnsignedCharBuffer(string hexString, unsigned char* 
hexBuffer)
{
  int i=0;
  while(hexString.length())
  {
    string hexStringPart = hexString.substr(0,2);
    hexString = hexString.substr(2);
    int hexStringOneByte = convertHexStringToInt (hexStringPart);
    hexBuffer[i] = static_cast<unsigned char>((hexStringOneByte & 0xFF)) ;
    i++;
  }
}

int main()
{
  //below hex string is a hex representation of a unsigned char * buffer.
  //this is generated by an excryption algorithm in unsigned char* format
  //I am converting it to hex string to make it printable for verification pupose.
  //and takes the hexstring as inpuit here to test the conversion logic.
  string inputHexString = "552027e33844dd7b71676b963c0b8e20";
  string outputHexString;
  stringstream geek;

  unsigned char * hexBuffer = new unsigned char[inputHexString.length()/2];
  convertHexStringToUnsignedCharBuffer(inputHexString, hexBuffer);

  for (int i=0;i<inputHexString.length()/2;i++)
  {
    geek <<std::hex << std::setw(2) << std::setfill('0')<<(0xFF&hexBuffer[i]); // this works
    //geek <<std::hex << std::setw(2) << std::setfill('0')<<(hexBuffer[i]); -- > this does not work
    // I am not able to figure out why I need to do the bit wise and operation with unsigned char "0xFF&hexBuffer[i]"
    // without this the conversion does not work for individual bytes having ascii values more than 127.
  }

  geek >> outputHexString;

  cout << "input hex string:  " << inputHexString<<endl;
  cout << "output hex string: " << outputHexString<<endl;
  if(0 == inputHexString.compare(outputHexString))
    cout<<"hex encoding successful"<<endl;
  else
    cout<<"hex encoding failed"<<endl;

  if(NULL != hexBuffer)
      delete[] hexBuffer;

  return 0;
}

// output
// can some one explain ? I am sure its something silly that I am missing.

The output of an unsigned char is like the output of a char which obviously does not what the OP expects. unsigned char的输出就像一个char的输出,这显然不是 OP 所期望的。

I tested the following on coliru:我在coliru上测试了以下内容:

#include <iomanip>
#include <iostream>

int main()
{
  std::cout << "Output of (unsigned char)0xc0: "
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned char)0xc0 << '\n';
  return 0;
}

and got:并得到:

Output of (unsigned char)0xc0: 0�

This is caused by the std::ostream::operator<<() which is chosen out of the available operators.这是由从可用运算符中选择的std::ostream::operator<<()引起的。 I looked on cppreference我查看了 cppreference

and found并发现

template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
                                        unsigned char ch );

in the former (with a little bit help from MM).在前者(在MM的帮助下)。

The OP suggested a fix: bit-wise And with 0xff which seemed to work. OP 提出了一个修复方法:按位和0xff似乎有效。 Checking this in coliru.com:在coliru.com中检查:

#include <iomanip>
#include <iostream>

int main()
{
  std::cout << "Output of (unsigned char)0xc0: "
    << std::hex << std::setw(2) << std::setfill('0') << (0xff & (unsigned char)0xc0) << '\n';
  return 0;
}

Output:输出:

Output of (unsigned char)0xc0: c0

Really, this seems to work.真的,这似乎有效。 Why?为什么?

0xff is an int constant (stricly speaking: an integer literal ) and has type int . 0xff是一个int常量(严格来说:一个整数文字)并且具有int类型。 Hence, the bit-wise And promotes (unsigned char)0xc0 to int as well, yields the result of type int , and hence, the std::ostream::operator<< for int is applied.因此,逐位并促进(unsigned char)0xc0int为好,产生类型的结果int ,并且因此, std::ostream::operator<<int被应用。

This is an option to solve this.这是解决这个问题的一个选项。 I can provide another one – just converting the unsigned char to unsigned .我可以提供另一个 - 只需将unsigned char转换为unsigned

Where the promotion of unsigned char to int introduces a possible sign-bit extension (which is undesired in this case), this doesn't happen when unsigned char is converted to unsigned .unsigned char提升为int引入了可能的符号位扩展(在这种情况下是不希望的),当unsigned char转换为unsigned时不会发生这种情况。 The output stream operator for unsigned provides the intended output as well: unsigned的输出流运算符也提供了预期的输出:

#include <iomanip>
#include <iostream>

int main()
{
  std::cout << "Output of (unsigned char)0xc0: "
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned)(unsigned char)0xc0 << '\n';
  const unsigned char c = 0xc0;
  std::cout << "Output of unsigned char c = 0xc0: "
    << std::hex << std::setw(2) << std::setfill('0') << (unsigned)c << '\n';
  return 0;
}

Output:输出:

Output of (unsigned char)0xc0: c0
Output of unsigned char c = 0xc0: c0

Live Demo on coliru在coliru上进行现场演示

the C++20 way: C++20 方式:

unsigned char* data = new unsigned char[]{ "Hello world\n\t\r\0" };
std::size_t data_size = sizeof("Hello world\n\t\r\0") - 1;

auto sp = std::span(data, data_size );
std::transform( sp.begin(), sp.end(),
                std::ostream_iterator<std::string>(std::cout),
                [](unsigned char c) -> std::string {
                    return std::format("{:02X}", int(c));
                });

or if you want to store result into string:或者如果要将结果存储到字符串中:

std::string result{};
result.reserve(size * 2 + 1);
std::transform( sp.begin(), sp.end(),
                std::back_inserter(result),
                [](unsigned char c) -> std::string {
                    return std::format("{:02X}", int(c));
                });
Output:
48656C6C6F20776F726C640A090D00

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM