Szyfr cezara

0

Chciałem stworzyć program, który będzie szyfrował wprowadzony ciąg znaków za pomocą szyfru cezara (czyli przesuwał litery o n pozycji). Jednakże mój program ma problem przy wracaniu do początku alfabetu, kiedy przekroczy się ich ilość.
main.cpp:

#include "headers.hpp"

using namespace std;

int przesuniecie, wszyfr;
string word;
int main()
{
    cout << "Wprowadz slowo:" << endl;
    cin >> word;
    cout << endl;
    cout << "O ile miejsc przesunac?" << endl;
    cin >> przesuniecie;
    cout << endl;
    cout << word << endl;
    cout << "Zaszyfrowac czy deszyrowac?" << endl;
    cout << "1 - zaszyfrowac" << endl
         << "2 - deszyfrowac" << endl;
    cin >> wszyfr;
    cout << endl;
    switch (wszyfr) {
    case 1:
        szyfr(przesuniecie, word);
        break;
    case 2:
        deszyfr(przesuniecie, word);
        break;
    default:
        cout << "Nie wybrano prawidlowej opcji" << endl;
    }

    //getch();
    system("pause");
    return (0);
}

headres.hpp:

#ifndef HEADERS_HPP
#define HEADERS_HPP

#include <iostream>
#include <conio.h>
#include <string>
using namespace std;

void szyfr(int przesuniecie,string word);
void deszyfr(int przesuniecie,string word);
#endif

funckcje.cpp:

#include "headers.hpp"
#include <iostream>
#include <math.h>

void szyfr(int przesuniecie, string word)
{
    int iloscliter = 'z' - ('a' - 1);
    //cout<<word<<endl;//wyswietlanie slowa przed deszyfrowaniem
    int rozmiar = word.length();
    //szyfrowanie
    for (int i = 0; i < rozmiar; i++) {
        word[i] = word[i] + przesuniecie;
        //przejscie do poczatku alfabetu
        while (word[i] > 'z') { //<-to nie działa
            word[i] = word[i] - iloscliter;
        }
    }

    cout << word << endl;
}
void deszyfr(int przesuniecie, string word)
{
    int iloscliter = 'z' - ('a' - 1);
    cout << word << endl; //wyswietlanie slowa przed deszyfrowaniem
    int rozmiar = word.length();
    //deszyfrowanie
    for (int i = 0; i < rozmiar; i++) {
        word[i] = word[i] - przesuniecie;
        //przejscie do poczatku alfabetu
        while (word[i] < 'a')
            word[i] = word[i] + iloscliter;
    } //<- to działa

    cout << word << endl;
}

W pierwszej funkcji "szyfr" nie działa mi (wg moich obserwacji) prawidłowo pętla while. Gdy wprowadzam ilość przesunięć, które wymagają więcej niż 1 raz zmniejszenia word[i], to pokazuje mi dziwne znaczki z tablicy ASCII czyli prawdopodobnie dodaje dobrze przesunięcie, ale nie chce powrócić do alfabetu. Co jeszcze bardziej mnie dziwi to fakt, że przy funkcji "deszyfr" wszystko ładnie działa.
Gdzie zatem jest błąd?

6

Błąd jest w sposobie za pomocą które chcesz osiągnąć to co robisz. Lekcja na dziś: operator modulo i reszta z dzielenia.

0

Pokazuje Ci dziwne znaczki, ponieważ w tablicy ASCII przed wartością 97 lub po wartości 122 (dla małych liter) nie powtarza się alfabet od nowa tylko występują tam pozostałe znaki. http://www.klcconsulting.net/images/ascii-full.gif

3
int przesuniecie,wszyfr;
string word;
int main()

Nie używaj zmiennych globalnych.

// headres.hpp
using namespace std;

Nie używaj using w pliku nagłówkowym.

Stosuj jakiś formatter np. http://prettyprinter.de/index.php, bo te wcięcia bardzo utrudniają czytanie.

A tu masz link to bardzo przyjaznego i krótkiego tutoriala GDB, dzięki któremu możesz przejść po funkcji szyfr() i sprawdzić dlaczego nie działa jak trzeba: http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html

0

No tak, tylko, że ja w tej pętli zmniejszam wartość o ilość liter w alfabecie, czyli powinno wrócić kiedyś(dlatego pętla while) do alfabetu. Przykładowo nam literę 'z' i chcę przesunąć o 1. Wtedy mam wartość 123. Teraz zmniejszając ją o ilość liter w alfabecie, czyli wartość wraca mi do litery 'a', czyli krzaczków być nie powinno.

0

Kluczem jest wbicie się w odpowiedni zakres kodów ASCII przy operacjach szyfrowania oraz deszyfrowania:

#include<iostream>
#include<string>
using namespace std;

string szyfruj(const string& tekstJawny, unsigned przesuniecie){
	string szyfrogram = "";
	for(unsigned i = 0; i < tekstJawny.length(); i++)
		szyfrogram = szyfrogram + static_cast<char>(97 + (static_cast<int>(tekstJawny[i]) - (97 - przesuniecie)) % 26 );		
	return szyfrogram;
}

string deszyfruj(const string& szyfrogram, unsigned przesuniecie){
	string tekstJawny = "";
	for(unsigned i = 0; i < szyfrogram.length(); i++)
		tekstJawny = tekstJawny + static_cast<char>(97 + (static_cast<int>(szyfrogram[i]) - (71 + przesuniecie)) % 26 );
	return tekstJawny;
}

int main(){	
	string szyfr = szyfruj("abcdefxyz", 3);
	cout << szyfr << endl;
	cout << deszyfruj(szyfr, 3) << endl;
	return 0;
}
0

@grzesiek51114 -1 za copy-paste. Operacja szyfrowania i deszyfrowania jest praktycznie taka sama.

0

@pingwindyktator Nie wiem... może tak będzie lepiej:

#include<string>
using namespace std;

enum Operacja{
	szyfrowanie,
	deszyfrowanie
};

string cezaruj(const string& tekst, unsigned przesuniecie, Operacja oper){
	int czynnik = (oper == szyfrowanie) ? ('a' - przesuniecie) :  ('G' + przesuniecie);
	string wynik = "";
	for(unsigned i = 0; i < tekst.length(); i++)
        wynik = wynik + static_cast<char>('a' + (static_cast<int>(tekst[i]) - czynnik) % 26 ); 
	return wynik;
}

 
int main(){    
    string szyfr = cezaruj("grzegorz", 3, szyfrowanie);
    cout << "Szyfrogram:  " << szyfr << endl;
    cout << "Tekst jawny: " << cezaruj(szyfr, 3, deszyfrowanie) << endl;
	system("pause");
    return 0;
}

Już się nie czepiajcie co? ;)

1

Chodziło o coś takiego:

#include<iostream>
#include<string>
using namespace std;
 
string szyfruj(const string& tekstJawny, unsigned przesuniecie) {
	przesuniecie %= 26;
    string szyfrogram;
    
    for(unsigned i = 0; i < tekstJawny.length(); i++)
        szyfrogram = szyfrogram + static_cast<char>('a' + (static_cast<int>(tekstJawny[i]) - ('a' - przesuniecie)) % 26 );  
     
    return szyfrogram;
}
 
string deszyfruj(const string& szyfrogram, unsigned przesuniecie) {
	przesuniecie %= 26;
	return szyfruj (szyfrogram, 26 - przesuniecie);
}
 
int main() {    
    string szyfr = szyfruj("abcdefxyz", 3);
    cout << szyfr << endl;
    cout << deszyfruj(szyfr, 3) << endl;
    return 0;
}
0

Jak mógłbym zamienić w funkcji zmienną typu string (tutaj 'word') na tablicę unsigned char?

1 użytkowników online, w tym zalogowanych: 0, gości: 1