如何将二进制字符串转换回字符

9

例子

注意:我只关心字母。所以bitset 000001会是aA

我有一个名为sstring,值为"abc"。 我取出string中的每个char,并通过使用bitset将其转换为二进制值。

例如

bitset <6> b1 = s[0];   //a
bitset <6> b2 = s[1];   //b
bitset <6> b3 = s[2];   //c

我希望将结果放入一个字符串数组中,数组的名称为arr(每个string代表一个char的二进制值)。

例如:

arr[0]   //will hold the value of char 'a' in binary form which is 000001
arr[1]   //will hold the value of char 'b' in binary form which is 000010
arr[2]   //will hold the value of char 'c' in binary form which is 000011

我将字符串中的每个char转换为二进制的方法是:

arr[0] = b1.to_string();    //arr[0] is now 000001
arr[1] = b2.to_string();    //arr[1] is now 000010
arr[2] = b3.to_string();    //arr[2] is now 000011

现在我的问题在于,如何将它们转换回char

例如:

//I want each char to take back the each corresponding letter from the binary values

char c1;   //How do i make the arr[0] value of 000001 to become 'a' again?
char c2;   //Same here
char c3;   //And here

一个常见的问题,你确定找不到吗? - 2785528
如果您已经有了二进制值的字符串表示,并且想要返回到char,为什么不直接删除bitset中间人并执行类似于static_cast<char>(std::stoi(arr[i]) + 64)的操作呢?但是,我不知道您是否需要在代码中稍后进行进一步操作。 - Alejandro
谢谢。我不需要进一步使用它。那么,像你说的那样,没有位集合也可以工作吗(我现在无法尝试,但我回家后会尝试)? - George
刚刚测试了一下,它可以工作,但是我在之前的评论中忘记了一些东西,现在已经无法编辑了。这里是一个实时演示:http://coliru.stacked-crooked.com/a/ae972e7c3985608b。 - Alejandro
谢谢@Alejandro。你能解释一下代码中的0,2部分吗?再次感谢:)。 - George
3个回答

5
假设您想从ASCII代码64开始,并且在该情况下,'a'(或'A')仅为000001,那么您可以简单地执行以下操作:
c1 = static_cast<char>(std::bitset<6>(arr[0]).to_ulong() + 64); // 

在十进制中,'A'的值为65,在二进制中为0b01000001'a'的值为97,在二进制中为0b01100001。在您的代码中,您使用一个bitset<6>来存储'a'(或'A')。bitset<6>只能表示2^6个符号,即64个,所以您会遇到截断。基本上,最高的2位将被截断。在这种情况下,bitset<6>('A')变为0b000001,即十进制中的1bitset<6>('a')变为0b1000001,即十进制中的33。您现在可以自己确认加回64会产生正确的结果。

编辑

请注意,您还可以使用std::stoi(仅限C++11)将二进制字符串转换为十进制,如其他答案中所述:

char c1 = static_cast<char>(std::stoi(arr[0], nullptr, 2) + 64);

谢谢老兄,你能解释一下你的代码吗?然后我会选择它作为最佳答案。 - George
谢谢,那很有道理。 - George
@George,添加64(XOR)有点不必要,我已经删除了它。我的意思是说,64在二进制中是0b01000000,将其加到aA的6位表示中可以得到正确的结果。虽然用十进制做更容易,就像我在主答案中所做的那样。 - vsoftco
为什么不使用 std::bitset<8> 呢?这样的话,它将具有与 char 相同数量的位,因此您不会有任何截断,并且您不需要添加像 64 这样的所有这些 mumbo-jumbo。实际上,即使是 7 位也足以表示所有 ASCII 字符。 - vsoftco
点赞。我使用6位的原因是我想要一个像000001这样的存在,而不是0b01100001(因为我只使用字母)用于加密算法。让用户输入0b01100001而不是000001会很麻烦,基本上就是这样:P - George
显示剩余2条评论

1
考虑以下内容:
 std::cout << "abc" << std::endl;

 std::cout << 'a' << 'b' << 'c' << std::endl;

 std::cout << std::dec
           << static_cast<int>('a') << " "
           << static_cast<int>('b') << " "
           << static_cast<int>('c')  << " "<< std::endl;

 std::cout << std::hex
           << static_cast<int>('a') << " "
           << static_cast<int>('b') << " "
           << static_cast<int>('c')  << " "<< std::endl;

带输出

abc

abc

97 98 99

61 62 63

这表明每个字符都是二进制的,97十进制等于0x61十六进制。

转换(通过位集从/到二进制)不是必需的。

(或许我没有理解为什么要以相当复杂的方式什么都不做)。

请注意,static_cast<>不会生成代码。 请注意,std::dec和std::hex对数据没有任何更改,只是改变了基数。

编辑--- 对于仅有8位的情况,您可以考虑这个...没有大小端问题。

 std::cout << ((('a' >> 7) & 1) ? '1' : '0')
           << ((('a' >> 6) & 1) ? '1' : '0')
           << ((('a' >> 5) & 1) ? '1' : '0')
           << ((('a' >> 4) & 1) ? '1' : '0')
           << ((('a' >> 3) & 1) ? '1' : '0')
           << ((('a' >> 2) & 1) ? '1' : '0')
           << ((('a' >> 1) & 1) ? '1' : '0')
           << ((('a' >> 0) & 1) ? '1' : '0') << "  "
           << ((('b' >> 7) & 1) ? '1' : '0')
           << ((('b' >> 6) & 1) ? '1' : '0')
           << ((('b' >> 5) & 1) ? '1' : '0')
           << ((('b' >> 4) & 1) ? '1' : '0')
           << ((('b' >> 3) & 1) ? '1' : '0')
           << ((('b' >> 2) & 1) ? '1' : '0')
           << ((('b' >> 1) & 1) ? '1' : '0')
           << ((('b' >> 0) & 1) ? '1' : '0') << "  "
           << ((('c' >> 7) & 1) ? '1' : '0')
           << ((('c' >> 6) & 1) ? '1' : '0')
           << ((('c' >> 5) & 1) ? '1' : '0')
           << ((('c' >> 4) & 1) ? '1' : '0')
           << ((('c' >> 3) & 1) ? '1' : '0')
           << ((('c' >> 2) & 1) ? '1' : '0')
           << ((('c' >> 1) & 1) ? '1' : '0')
           << ((('c' >> 0) & 1) ? '1' : '0') << "  "
           << std::endl;


 std::cout << std::dec << std::endl;


 // with variable
 char zulu = 'A';

 std::cout << std::dec
           << "NOTE: in this cout, every use of zulu is a 'read' \n"
           << "   zulu: " << zulu                               << "  \n"

           << "   dec : " << std::dec << static_cast<int>(zulu) << "  \n"
           << "   --- : " << zulu                               << "  \n" // zulu not changed

           << "   hex : " << std::hex << static_cast<int>(zulu) << "  \n"
           << "   --- : " << zulu                               << "  \n" // zulu not changed

           << "   bin : "
           << (((zulu >> 7) & 1) ? '1' : '0')
           << (((zulu >> 6) & 1) ? '1' : '0')
           << (((zulu >> 5) & 1) ? '1' : '0')
           << (((zulu >> 4) & 1) ? '1' : '0')
           << (((zulu >> 3) & 1) ? '1' : '0')
           << (((zulu >> 2) & 1) ? '1' : '0')
           << (((zulu >> 1) & 1) ? '1' : '0')
           << (((zulu >> 0) & 1) ? '1' : '0')    << "  \n"
           << "   --- : " << zulu                               << "  \n" // zulu not changed

           << " bitset: " << std::bitset<8>(zulu)               << "  \n"
           << "   zulu: " << zulu                               << "  \n\nzulu not changed!" // zulu not changed

           << std::endl;

我需要一些输出的二进制值来展示。你的例子让我有点迷惑,哈哈,等我回家后再仔细理解。谢谢。 - George

1

既然您在将二进制转换回char表示后不再需要std::bitset,因此可以避免使用它进行转换。

static_cast<char>(std::stoi(arr[i],0,2) + 64);

将原始二进制表示解释为2进制数字,并加上64。由于在arr数组中以二进制格式存储了原始char,因此可以将它们传递给std::stoi函数,并在第3个参数中指定值为2。 std::stoi需要3个参数:要转换的字符串,将存储第一个未转换字符的索引的int指针(这里不需要,可以保留为0),以及字符串参数的基数。 在这里可以获得更多信息std::stoi调用的结果是二进制值的10进制等价值。 vsoftco的答案解释了在获取十进制表示后为什么要添加64是恰当的操作。 这个结果作为char返回。
如果您能够使用更大的std :: bitset,甚至可以放弃添加64。
以下是一个实时演示:

演示


你能解释一下这部分吗?(arr[i],0,2) 还有,谢谢你的代码 :) - George

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接