Битовые манипуляции на символьной строке - PullRequest
0 голосов
/ 24 февраля 2020

Можем ли мы применить битовую манипуляцию к строке символов? Если это так, всегда ли возможно получить обратно символьную строку из измененной строки?

Я надеялся использовать оператор XOR для двух строк, преобразовав их в двоичный файл, а затем обратно в символьную строку .

Я взял код из другого вопроса StackOverflow, но он решает только половину проблемы

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

Я не знаю, как преобразовать эту строку единиц и обнулить обратно строка символов. Я прочитал std :: stio в некоторых результатах поиска Google как решение, но не смог их понять.

Манипуляция, которую я хочу sh сделать, это

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;

Я знаю, что могу жестко закодировать это, выбирая каждую запись и применяя операцию, но это преобразование двоичной строки обратно в символы, которые заставляют меня чесать голову.

* РЕДАКТИРОВАТЬ: * Я пытаюсь реализовать структуру шифра под названием шифр Фейстеля ( SORRY, должен был прояснить это до ), там они используют свойство XOR, что когда вы снова XOR что-то с той же вещи снова, он отменяет ... Например. (А ^ В) ^ В = А. Я хотел вывести зашифрованный jibberi sh в середине. Отсюда и запрос.

Ответы [ 2 ]

3 голосов
/ 24 февраля 2020

Можем ли мы применить битовую манипуляцию к строке символов?

Да.

Символ - это целочисленный тип, поэтому вы можете делать с ним все, что можете к любому другому целому числу. Что случилось, когда вы попытались ?

Если это так, всегда ли можно извлечь строку символов из манипулируемой строки?

Нет. иногда можно восстановить исходную строку, но некоторые манипуляции необратимы.

XOR, конкретная операция, о которой вы спрашивали, является самообращающейся, поэтому в этом случае она работает, но не в общем.

Дрянной пример (зависит от набора символов ASCII, не делайте этого в реальном коде для преобразования регистра, et c. et c.)

#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», а затем использую XOR (каким-то образом) нулевой бит 5, дающий «1000001» а затем преобразовать это обратно в «А». Почему я?

Эта часть вашего вопроса говорит о том, что вы не понимаете разницы между значениями и представлениями: символ всегда хранится в двоичном виде. Вы можете также всегда обращаться с ним так, как если бы он был сохранен в восьмеричном, десятичном или шестнадцатеричном виде - выбор базы влияет только на то, как мы записываем (или печатаем) значение, а не на то, что это значение


Написание шифра Фейстеля, в котором открытый текст и ключ имеют одинаковую длину, является тривиальным:

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

Это не сработает, если ключ короче, хотя - правильное зацикливание клавиши оставляется читателю в качестве упражнения.

О, и печать закодированной строки вряд ли будет работать хорошо (если только ваш ключ не является просто последовательностью пробельных символов, как указано выше) .

1 голос
/ 24 февраля 2020

Вы, вероятно, хотите что-то вроде этого:

#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; и посмотрите, что произойдет .

...