将十六进制字符串转换为二进制并分离为n C ++

时间:2018-08-25 07:53:01

标签: c++ visual-c++

我需要将十六进制字符串转换为二进制,然后将这些位传递给不同的变量。

例如,我的输入是: std :: string hex =“ E136”;

如何将字符串转换为二进制输出1110 0001 0011 0110? 之后,我需要将位0传递给变量A,将位1-9传递给变量B,将位10-15传递给变量C。

预先感谢

2 个答案:

答案 0 :(得分:1)

  

如何转换字符串[...]?

以结果值null开头,然后为每个字符(首先开始,表示最高有效)确定其值(在[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

以后不要转换回字符串,可以通过屏蔽(&)和移位(>>)来获得所需的值,例如。 g获得位[1-9]:

uint32_t b = value >> 1 & 0x1ffU;

处理整数要比处理字符串有效得多。仅当您要打印最终结果 时, then 才转换回字符串(如果使用std::ostream,{{1 }}已经为您完成工作...)。

答案 1 :(得分:0)

在处理此示例时,我意识到我提出了错误的建议:

std::setbase(2) 不起作用。哎哟! (SO: Why doesn't std::setbase(2) switch to binary output?

要将数字转换为带有二进制数字的字符串,必须使用其他方法。我做了这个小样本。尽管也考虑了位的分离,但我的主要重点是基于不同基数的输出(恕我直言,这是另一个答案):

#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 on coliru

关于位操作:

  • 二进制按位和运算符(&)用于将所有意外位设置为0。第二个值可以理解为掩码。如果我使用了二进制数,则将更加明显,但是C ++不支持此功能。十六进制代码几乎与十六进制数字一样好,它始终表示相同的4位模式。 (因为16 = 2 4 )经过一段时间的练习,您通常会学会“查看”十六进制代码中的位。

  • 关于右移(>>),我不太确定。 OP不需要将位移动到某个位置–只是必须将它们分成不同的变量。因此,这些右移可能已过时。

因此,这个似乎微不足道的问题(对我而言)带来了令人惊讶的启示。