Как использовать арифметику по модулю для реализации шифра Цезаря - PullRequest
0 голосов
/ 21 декабря 2018

Я пытаюсь выполнить обтекание символов алфавита ASCII, чтобы выполнить переход от клавиши.Например, если ключ равен 2, то сдвиньте букву A, чтобы она стала C.Но как мне обернуть Z, чтобы добраться до B с использованием арифметики модуля?

Я пытаюсь реализовать следующую формулу:

ci = (pi + key) % 26;

Где cii является зашифрованной буквой, а pi является i буквой, которую необходимо зашифровать.

Ответы [ 3 ]

0 голосов
/ 21 декабря 2018

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

#include <stdio.h>

#define ASCII_CAP_LETTER_OFFS 65
#define ASCII_LETTER_OFFS 97
#define NUM_OF_LETTERS 26

char shift_letter (char letter, short shift)
{
  char ci;
  short shift_lcl = shift % NUM_OF_LETTERS;
  if (shift_lcl >= 0)
  { // shift in positive direction
  }
  else
  { // shift in negative direction 
   shift_lcl = NUM_OF_LETTERS + shift_lcl;
  }

  if (letter >= ASCII_CAP_LETTER_OFFS && letter < ASCII_CAP_LETTER_OFFS + NUM_OF_LETTERS)  
    {// its a capital letter
      ci =
    (letter + shift_lcl - ASCII_CAP_LETTER_OFFS) % NUM_OF_LETTERS +
    ASCII_CAP_LETTER_OFFS;
    }
  else if (letter >= ASCII_LETTER_OFFS && letter < ASCII_LETTER_OFFS + NUM_OF_LETTERS) 
    {// its a non capital letter
      ci =
    (letter + shift_lcl - ASCII_LETTER_OFFS) % NUM_OF_LETTERS +
    ASCII_LETTER_OFFS;
    }
  else
    {
      printf ("This was not a letter!\n");
      ci = 0;
    }
  return ci;
}

int main ()
{
  char test_letter = 'a';
  short test_shift = -53;
  char shifted_letter = 0;
  shifted_letter = shift_letter (test_letter, test_shift);
  printf("%c +  %d = %c", test_letter, test_shift, shifted_letter);
}
0 голосов
/ 21 декабря 2018

Глубже

 ci = ((pi - 'A' + key) % 26) + 'A';

, а также @ Sourav Ghosh генерирует ожидаемый закодированный AZ, когда key неотрицательно и не слишком велико.Он уменьшает pi на - 'A', поэтому значение находится в диапазоне [0...25] и сбрасывает его после вычисления %.

Для работы при full int диапазон key занимает немного больше кода.

  • Уменьшите key диапазон [INT_MIN...INT_MAX] с функциональным эквивалентным диапазоном [-25 ... 25] с key % 26.Этот шаг важен для предотвращения переполнения int с помощью pi - 'A' + key.Это можно сделать один раз, если нужно закодировать несколько букв.

  • Add 26. Это гарантирует, что отрицательные ключи будут перемещены в положительные.

    ci = ((pi - 'A' + key%26 + 26) % 26 ) + 'A';
    

Примечание: В C, % это не оператор mod , а оператор Остаток .Функциональные различия возникают при a%b, когда a и / или b отрицательны. ссылка

0 голосов
/ 21 декабря 2018

Я считаю, что вам нужно работать с «относительными» значениями, а не с абсолютными значениями.

Использовать что-то вроде

ci = ((pi - 'A' + key) % 26 ) + 'A';

Символьные целочисленные константы хранят закодированные значения, в данном случае, ASCII .Здесь 'A' начинается со смещения (десятичное значение 65), а не с 0. Итак, прежде чем вы сможете обернуть результат с помощью операции % 26, вам нужно вывести это смещение.После завершения вычисления добавьте смещение назад, чтобы получить правильное представление ASCII.

...