W szyfrze Cezara wykorzystuje się alfabet łaciński. Do szyfrowania lub deszyfrowania potrzebny jest klucz a, który jest liczbą całkowitą. Szyfrując znak szukamy jego pozycji w alfabecie i pobranie znaku a pozycji dalej. W przypadku, gdy wyjdziemy poza zakres alfabetu to wyciągamy z wyliczonej modulo długość alfabetu. Podczas deszyfrowania szyfrujemy ponownie podstawiając za klucz -a.
Przykładowo szyfrujemy wyraz INFORMACJA z kluczem 3. Możemy stworzyć tabelkę, która pozwoli szybciej wykonać szyfrowanie:
Tekst jawny | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
Szyfrogram | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | A | B | C |
Dzięki tabelce bardzo łatwo odczytać jaka litera z tekstu jawnego na jaką przechodzi: I na L, N na Q, ... i w ten sposób odczytujemy, że INFORMACJA przechodzi na LQIRUPDFMD.
Napiszemy funkcję, która będzie przyjmowała dwa argumenty: tekst do zaszyfrowania typu char* oraz klucz typu int. Wynikiem funkcji będzie zaszyfrowany tekst. Zakładamy, że w podanym tekście występują tylko duże litery alfabetu łacińskiego, znaki interpunkcyjne oraz spacje. Przykładowo dla danych:
otrzymamy:
Funkcja przyjmuje dwa argumenty txt - tekst do zaszyfrowania oraz przes - klucz według którego szyfrujemy. Wynikiem funkcji jest tablica znaków typu char*, która będzie zawierać zaszyfrowany tekst.
(2.) Jeśli przesunięcie jest ujemne to dodajemy do niego długość alfabetu. Dzięki temu unikamy rozpatrywania przypadku kiedy wyjdziemy poza alfabet z lewej strony. (3.) Alokujemy pamięć pod tekst wynikowy. (4.) Rozpoczynamy szyfrowanie każde znaku po kolei: jeśli nasz znak jest dużą literą to (5.) wyliczamy jego nową pozycje i pobieramy odpowiedni znak. Korzystamy tutaj z tablicy ASCII. Gdybyśmy w (2.) nie usunęli ujemności przes to trzeba by rozpatrzeć dwa przypadki, albo przesunięcie poprawić podczas wyliczania nowej litery. (7.) Jeśli jednak i-ty znak nie jest literą to (8.) przepisujemy znak bez żadnych dodatkowych zmian. (11.) Na koniec dostawiamy znak \0 i (12.) zwracamy wynik.
Deszyfrowanie polega na zaszyfrowaniu kluczem przeciwnym - czyli jeśli zaszyfrowaliśmy tekst przy pomocy a to deszyfrujemy go szyfrując przy pomocy -a, dlatego deszyfrowanie możemy wywołać przy pomocy funkcji cipher():
Jednak bardziej eleganckim rozwiązaniem jest dopisanie funkcji decipher(), której będziemy podawać ten sam klucz do szyfrowania:
Zamieszczona poniżej funkcja main() pozwala przetestować działanie funkcji poprzez wczytanie tekstu, a następnie wypisaniu szyfrogramu z przesunięciem 3, a potem wypisaniu próby deszyfrowania danych.
Tym razem będziemy chcieli ustalić własny alfabet według, którego będziemy szyfrowali dane: w ten sposób prócz klucz będzie potrzeba ustalenia alfabetu.
otrzymamy:
Dotychczasowy kod potrzebuje drobnej modyfikacji. Podczas szyfrowania nie możemy wyliczać grupy i pozycji na podstawie odległości od litery A. Wyliczymy je na podstawie pozycji znaku w podanym alfabecie. Żeby to osiągnąć dopiszemy funkcję, która dla podanego ciągu i znaku znajdzie jego pozycję i ją zwróci.
Spójrzmy teraz na funkcję szyfrującą:
(1.) Modyfikujemy nagłówek funkcji, który od tej pory będzie przyjmował także alphabet - ciąg znaków alfabetu według którego szyfrujemy. (2.) Długością alfabetu nie jest już 'Z' - 'A' + 1 tylko długość alphabet co też ma wpływ na (3.). (4.) Dla każdego znaku: (5.) deklarujemy zmienną pomocniczą t dla której (5.) sprawdzamy czy występuje w alfabecie. Jeśli tak to (6.) szyfrujemy go. (8.) Jeśli nie występuje w alfabecie to (9.) tylko przepisujemy. (12.) Kończymy wynik znakiem \0 i (13.) zwracamy wynik.
Deszyfrowanie wymaga tylko dodania nowego argumentu, który przekażemy dalej do cipher().
Poniżej znajduje się zaktualizowana funkcja main(), która przetestuje działanie napisanych funkcji.
Na podstawie kodu źródłowego do zadania 1:
Przykładowo dla danych: