Преобразование без знака char * в hexstring - PullRequest
0 голосов
/ 22 мая 2018

Ниже код принимает шестнадцатеричную строку (каждый байт представлен как соответствующее шестнадцатеричное значение) преобразует его в беззнаковый буфер char *, а затем преобразует обратно в шестнадцатеричную строку.Этот код тестирует преобразование из беззнакового буфера 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.

1 Ответ

0 голосов
/ 22 мая 2018

Выход 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).

ОП предложил исправление: побитовое И с 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)0xc0 до int, дает результат типа 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

Live Demo на coliru

...