преобразовать шестнадцатеричную строку в двоичную и разделить на биты n C ++ - PullRequest
0 голосов
/ 25 августа 2018

Мне нужно преобразовать шестнадцатеричную строку в двоичную, а затем передать биты в различные переменные.

Например, мой ввод: std :: string hex = "E136";

Как преобразовать строку в двоичный вывод 1110 0001 0011 0110? После этого мне нужно передать бит 0 в переменную A, биты 1-9 в переменную B и биты 10-15 в переменную C.

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Играя с этим образцом, я понял, что дал неправильную рекомендацию:

std::setbase(2) не работает по умолчанию.Ой!( SO: Почему std :: setbase (2) не переключается на двоичный вывод? )

Для преобразования чисел в строку с двоичными цифрами необходимо использовать что-то еще.Я сделал этот маленький образец.Хотя разделение битов также рассматривается, мой основной фокус был на выводе с разными базами (и ИМХО стоит другого ответа):

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

Вывод:

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

Live Demo на coliru

Касательно битовых операций:

  • двоичный бит и оператор (&) используется для установки всех непреднамеренных битов на 0. Второе значение можно понимать как маску.Было бы более очевидно, если бы я использовал двоичные числа, но это не поддерживается в C ++.Шестнадцатеричные коды работают почти так же хорошо, как шестнадцатеричная цифра всегда представляет один и тот же шаблон из 4 бит(как 16 = 2 4 ) После некоторого времени практики вы обычно учитесь «видеть» биты в шестнадцатеричном коде.

  • О сдвиге вправо (>>), я был не совсем уверен.OP не требовал, чтобы биты были куда-то перемещены - только то, что они должны были быть разделены на отдельные переменные.Таким образом, эти сдвиги вправо могут быть устаревшими.

Итак, этот вопрос, который казался тривиальным, привел к неожиданному просветлению (для меня).

0 голосов
/ 25 августа 2018

Как преобразовать строку [...]?

Начните со значения результата, равного нулю, затем для каждого символа (начиная с первого, указывая наиболее значимый) определите егозначение (в диапазоне [0:15]), умножьте полученный результат на 16 и добавьте текущее значение к.Для вашего приведенного примера это приведет к

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

Существуют стандартные библиотечные функции, выполняющие эту работу за вас, такие как std::strtoul:

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

Указатель конца полезен для проверки того, прочитали ли вы всю строку:

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

Если вам не нужна проверка конца, вы можете просто вместо этого передать nullptr.

Don 't затем преобразовать обратно в строку, вы можете получить требуемые значения, маскируя (&) и сдвигая биты (>>), e.g получение битов [1-9]:

uint32_t b = value >> 1 & 0x1ffU;

Работа с интегралами намного эффективнее, чем работа со строками.Только если вы хотите напечатать из результата final , затем преобразовать обратно в строку (если вы используете std::ostream, operator<< уже выполняет работу длявы...).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...