Sun
Sun

Reputation: 13

convert hexadecimal string to binary and seperate into bits n C++

I need to covert hexadecimal string to binary then pass the bits into different variables.

For example, my input is: std::string hex = "E136";

How do I convert the string into binary output 1110 0001 0011 0110? After that I need to pass the bit 0 to variable A, bits 1-9 to variable B and bits 10-15 to variable C.

Thanks in advance

Upvotes: 0

Views: 1311

Answers (2)

Aconcagua
Aconcagua

Reputation: 25526

How do I convert the string [...]?

Start with result value of null, then for each character (starting at first, indicating most significant one) determine its value (in range of [0:15]), multiply the so far received result by 16 and add the current value to. For your given example, this will result in

(((0 * 16 + v('E')) * 16 + v('1')) * 16 + v('3')) + v('6')

There are standard library functions doing the stuff for you, such as std::strtoul:

char* end;
unsigned long value = strtoul(hex.c_str(), &end, 16);
//                                               ^^ base!

The end pointer useful to check if you have read the entire string:

if(*char == 0)
{
    // end of string reached
}
else
{
    // some part of the string was left, you might consider this
    // as error (could occur if e. g. "f10s12" was passed, then
    // end would point to the 's') 
}

If you don't care for end checking, you can just pass nullptr instead.

Don't convert back to a string afterwards, you can get the required values by masking (&) and bitshifting (>>), e. g getting bits [1-9]:

uint32_t b = value >> 1 & 0x1ffU;

Working on integrals is much more efficient than working on strings. Only when you want to print out the final result, then convert back to string (if using a std::ostream, operator<< already does the work for you...).

Upvotes: 1

Scheff&#39;s Cat
Scheff&#39;s Cat

Reputation: 20141

While playing with this sample, I realized that I gave a wrong recommendation:

std::setbase(2) does not work by standard. Ouch! (SO: Why doesn't std::setbase(2) switch to binary output?)

For conversion of numbers to string with binary digits, something else must be used. I made this small sample. Though, the separation of bits is considered as well, my main focus was on output with different bases (and IMHO worth another answer):

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>

std::string bits(unsigned value, unsigned w)
{
  std::string text;
  for (unsigned i = 0; i < w || value; ++i) {
    text += '0' + (value & 1); // bit -> character '0' or '1'
    value >>= 1; // shift right one bit
  }
  // text is right to left -> must be reversed
  std::reverse(text.begin(), text.end());
  // done
  return text;
}

void print(const char *name, unsigned value)
{
  std::cout
    << name << ": "
    // decimal output
    << std::setbase(10) << std::setw(5) << value
    << " = "
    // binary output
#if 0 // OLD, WRONG:
  // std::setbase(2) is not supported by standard - Ouch!
    << "0b" << std::setw(16) << std::setfill('0') << std::setbase(2) << value
#else // NEW:
    << "0b" << bits(value, 16)
#endif // 0
    << " = "
    // hexadecimal output
    << "0x" << std::setw(4) << std::setfill('0') << std::setbase(16) << value
    << '\n';
}

int main()
{
  std::string hex = "E136";
  unsigned value = strtoul(hex.c_str(), nullptr, 16);
  print("hex", value);
  // bit 0 -> a
  unsigned a = value & 0x0001;
  // bit 1 ... 9 -> b
  unsigned b = (value & 0x03FE) >> 1;
  // bit 10 ... 15 -> c
  unsigned c = (value & 0xFC00) >> 10;
  // report
  print(" a ", a);
  print(" b ", b);
  print(" c ", c);
  // done
  return 0;
}

Output:

hex: 57654 = 0b1110000100110110 = 0xe136
 a : 00000 = 0b0000000000000000 = 0x0000
 b : 00155 = 0b0000000010011011 = 0x009b
 c : 00056 = 0b0000000000111000 = 0x0038

Live Demo on coliru

Concerning, the bit operations:

  • binary bitwise and operator (&) is used to set all unintended bits to 0. The second value can be understood as mask. It would be more obvious if I had used binary numbers but this is not supported in C++. Hex codes do nearly as well as a hex digit represents always the same pattern of 4 bits. (as 16 = 24) After some time of practice, you usually learn to "see" the bits in the hex code.

  • About the right shift (>>), I was not quite sure. OP didn't require that bits have to be moved somewhere – only that they had to be separated into distinct variables. So, these right-shift's might be obsolete.

So, this question which seemed to be trivial leaded to a surprising enlightment (for me).

Upvotes: 0

Related Questions