繁体   English   中英

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

[英]Converting unsigned char * to hexstring

下面的代码采用一个十六进制字符串(每个字节都表示为其相应的十六进制值)将其转换为 unsigned char * 缓冲区,然后再转换回十六进制字符串。 此代码正在测试从 unsigned char* 缓冲区到十六进制字符串的转换,我需要通过网络将其发送到接收器进程。 我选择了十六进制字符串,因为 unsigned char 可以在 0 到 255 的范围内,并且在 127 之后没有可打印的字符。下面的代码只是告诉我困扰我的部分。 它在评论中。

#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.

unsigned char的输出就像一个char的输出,这显然不是 OP 所期望的。

我在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;
}

并得到:

Output of (unsigned char)0xc0: 0�

这是由从可用运算符中选择的std::ostream::operator<<()引起的。 我查看了 cppreference

并发现

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

在前者(在MM的帮助下)。

OP 提出了一个修复方法:按位和0xff似乎有效。 在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 of (unsigned char)0xc0: c0

真的,这似乎有效。 为什么?

0xff是一个int常量(严格来说:一个整数文字)并且具有int类型。 因此,逐位并促进(unsigned char)0xc0int为好,产生类型的结果int ,并且因此, std::ostream::operator<<int被应用。

这是解决这个问题的一个选项。 我可以提供另一个 - 只需将unsigned char转换为unsigned

unsigned char提升为int引入了可能的符号位扩展(在这种情况下是不希望的),当unsigned char转换为unsigned时不会发生这种情况。 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 of (unsigned char)0xc0: c0
Output of unsigned char c = 0xc0: c0

在coliru上进行现场演示

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));
                });

或者如果要将结果存储到字符串中:

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