字符串的位操作

Bit manipulation on character string

我们可以对字符串进行位操作吗? 如果是这样,是否总是可以从操作的字符串中检索回字符串?

我希望通过将两个字符串转换为二进制然后再转换回 字符串

来对两个字符串使用 XOR 运算符

我从另一个 Whosebug 问题中提取了一些代码,但它只解决了一半问题

std::string TextToBinaryString(string words) 
{
string binaryString = "";
for (char& _char : words) 
    {
        binaryString +=std::bitset<8>(_char).to_string();
    }
return binaryString;
}

我不知道如何将这串 1 和 0 转换回一串字符。 我确实在某些 google 搜索结果中阅读了 std::stio 作为解决方案,但无法理解它们。

我想做的操作是

std::string message("Hello World");
int n = message.size();
bin_string = TextToBinaryString(message)

std::string left,right;
bin_string.copy(left,n/2,0);
bin_string.copy(right,n,n/2);

std::string result = left^right;

我知道我可以通过拾取每个条目并应用操作来对其进行硬编码,但是将二进制字符串转换回字符让我抓狂。

*EDIT: *I am trying to implement a cipher framework called Feistel cipher (SORRY, should had made that clear before) there they use the property of XOR that when you XOR something with the same thing again it cancels out... For eg. (A^B)^B=A. I wanted to output the ciphered jibberish in the middle. Hence, the query.

您可能想要这样的东西:

#include<string>
#include<cassert>

using namespace std;

std::string someBitmanipulation(string words)
{
  std::string manipulatedstring;

  for (char& thechar : words)
  {
    thechar ^= 0x5A;  // xor with 0x5A
  }
  return manipulatedstring;
}

int main()
{
  std::string original{ "ABC" };
  // xor each char of original with 0x5a at put result into manipulated
  auto manipulated = someBitmanipulation(original);

  // check if manipulating the manipulated string is the same as the original string
  assert(original == someBitmanipulation(manipulated));
}

你根本不需要std::bitset

现在将 thechar ^= 0x5A; 改为 thechar |= 0x5A;,看看会发生什么。

Can we apply bit manipulation on a character string?

是的。

字符是整数类型,因此您可以对它们做任何事情,您可以对任何其他整数做任何事情。 您尝试时发生了什么

If so, is it always possible to retrieve back a character string from the manipulated string?

没有。 有时 可以恢复原始字符串,但有些操作是不可逆的。

XOR,您询问的特定运算,是自反转的,因此它在这种情况下有效,但一般情况下无效。

一个俗气的例子(取决于ASCII字符集,不要在转换大小写等的真实代码中这样做)

#include <iostream>
#include <string>

int main() {
    std::string s("a");
    std::cout << "original: " << s << '\n';
    s[0] ^= 0x20;
    std::cout << "modified: " << s << '\n';
    s[0] ^= 0x20;
    std::cout << "restored: " << s << '\n';
}

显示(在 ASCII 兼容的)系统

original: a
modified: A
restored: a

请注意,我并不是先将 "a" 转换为“1100001”,然后使用异或(以某种方式)零位 5 给出“1000001”,然后将其转换回 "A"。我为什么要?

你问题的这一部分表明你不理解值和表示之间的区别:字符总是以二进制形式存储。您可以 始终将其视为以八进制、十进制或十六进制存储 - 基数的选择只会影响我们写入(或打印)值的方式,而不影响本身的价值是什么。


编写明文和密钥长度相同的 Feistel 密码很简单:

std::string feistel(std::string const &text, std::string const &key)
{
    std::string result;
    std::transform(text.begin(), text.end(), key.begin(),
                   std::back_inserter(result),
                   [](char a, char b) { return a^b; }
                   );
    return result;
}

如果密钥较短,这根本不起作用 - 适当地循环密钥作为 reader.

的练习。

哦,打印编码的字符串不太可能很好地工作(除非你的密钥只是一个 space 字符序列,如上所述)。