• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Łamanie szyfru Cezara

Object Storage Arubacloud
0 głosów
381 wizyt
pytanie zadane 17 sierpnia 2022 w C i C++ przez Noizz00 Użytkownik (910 p.)
zamknięte 17 sierpnia 2022 przez Noizz00

Cześć, miałem za zadanie napisać program, który odszyfruje kryptogram zaszyfrowany systemem Cezara korzystając z metody badania częstości występowania liter w tekście. Statystycznie litera A jest najczęściej występującą literą w języku polskim, więc przyjmujemy, że litera najczęściej występująca w kryptogramie jest zaszyfrowaną literą A/a.

Poniżej kod programu.

#include <iostream>
#include <fstream>

using namespace std;

const string alf_w = "AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ";
const string alf_m = "aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż";

string Cezar(string s, int k)
{
    int p;
    string odsz;
    for(int i = 0; i<s.size(); i++)
    {
        p = alf_m.find(s[i]);
        if(p>=0&&p<35) odsz = odsz + alf_m[(p+k)%35];
        else
        {
            p = alf_w.find(s[i]);
            if(p>=0&&p<35) odsz = odsz + alf_w[(p+k)%35];
            else odsz = odsz + s[i];
        }
    }
    return odsz;
}

int main()
{
    string szyfrogram;
    ifstream wejscie("tajne.txt");
    ofstream wyjscie("jawny.txt");
    int p;
    int Liczniki[35];
    while(!wejscie.eof())
    {
        getline(wejscie, szyfrogram);
        for(int i = 0; i<szyfrogram.size(); i++)
        {
            p = alf_m.find(szyfrogram[i]);
            if(p>=0&&p<35) Liczniki[p]++;
            else
            {
                p = alf_w.find(szyfrogram[i]);
                if(p>=0&&p<35) Liczniki[p]++;
            }
        }
    }
    wejscie.close();
    int indeks = 0;
    for(int i = 0; i<35; i++)
    {
        if(Liczniki[indeks]<Liczniki[i])
            indeks = i;
    }
    int klucz = 35 - indeks;
    wejscie.open("tajne.txt");
    while(!wejscie.eof())
    {
        getline(wejscie, szyfrogram);
        wyjscie << Cezar(szyfrogram, klucz) << endl;
    }
    wyjscie << alf_w[indeks];
    wejscie.close();
    wyjscie.close();
    cout << "Udalo sie rozszyfrowac tekst!";
    return 0;
}

Problem jest następujący - program wskazuje niepoprawną literę, która występuje najwięcej razy w tekście. Dla pewnego pliku uzyskałem literę Ż, która właściwie nie wystąpiła w nim ani razu. W czym jest błąd?

komentarz zamknięcia: Nie przypisano każdej szufladce tablicy Liczniki wartości 0 - program błędnie zliczał wystąpienia liter.
komentarz 17 sierpnia 2022 przez manjaro Nałogowiec (37,390 p.)
Być może problem polega na tym że w tekście to nie litera "A" występuje najczęściej tylko spacja, która występuje dwukrotnie częściej...
komentarz 17 sierpnia 2022 przez Noizz00 Użytkownik (910 p.)
Program wyłącznie zlicza wystąpienia liter. Spacji nie uwzględnia.

1 odpowiedź

+1 głos
odpowiedź 17 sierpnia 2022 przez overcq Pasjonat (21,710 p.)

Problemem są polskie znaki zapisane w UTF-8. find wyszukuje bajtowo?

komentarz 17 sierpnia 2022 przez Noizz00 Użytkownik (910 p.)
edycja 17 sierpnia 2022 przez Noizz00

Z findem raczej wszystko jest ok. Program szyfruje dobrze, jednak nie tym kluczem, co trzeba. Sprawdziłem zliczanie liter i wskazywanie maksimum w oddzielnym programie:

#include <iostream>
#include <cstring>
#include <fstream>
#include <cctype>

using namespace std;

const string alfabet_w = "AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ";
const string alfabet_m = "aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż";

int main()
{
    int Licznik[35] = {0}, ch, p;
    string zdanie;
    ifstream wejscie("tajne.txt");
    while(!wejscie.eof())
    {
        getline(wejscie, zdanie);
        for(int i = 0; i<zdanie.size(); i++)
        {
            p = alfabet_w.find(zdanie[i]);
            if(p>=0 && p<35)
                Licznik[p]++;
            p = alfabet_m.find(zdanie[i]);
            if(p>=0 && p<35)
                Licznik[p]++;
        }
    }
    wejscie.close();
    int indeks = 0;
    for(int i = 0; i < 35; i++)
    {
        if(Licznik[i]>Licznik[indeks])
        {
            indeks = i;
        }
    }
    ofstream wyjscie("wyniki.txt");
    for(int i = 0; i<35; i++)
    {
        if(Licznik[i]>0)
        {
            wyjscie << alfabet_w[i] << " - " << Licznik[i] << endl;
        }
    }
    wyjscie << endl;
    wyjscie << "Wśród najczęściej występujących liter znajdują się: " << endl;
    wyjscie << alfabet_w[indeks] << " - " << Licznik[indeks] << endl;
    for(int i = 0; i < 35; i++)
    {
        if(Licznik[i]==Licznik[indeks]&&alfabet_w[indeks]!=alfabet_w[i])
        {
            wyjscie << alfabet_w[i] << " - " << Licznik[i] << endl;
        }
    }
    wyjscie.close();
    cout << "Zapisano dane.";
    return 0;
}

tutaj program poprawnie zapisuje do pliku ilości poszczególnych liter i wskazuje literę C (z pozycji 3 w alfabecie) jako tą, która pojawia się najczęściej. Wtedy klucz 32 (35-3) w pełni odszyfrowuje kryptogram. Program niestety (nie wiem czemu) wskazuje literę 'Ż' i używa klucza 1 do deszyfrowania.

Aktualizacja. W szufladce odpowiadającej literze 'Ż' ni stąd ni zowąd pojawiła się magiczna liczba 1 920 468 992. Zorientowałem się, że coś jest nie tak ze zliczaniem w tablicy. Okazało się, że problem tkwił w tym, że nie przypisałem na początku wszystkim szufladkom wartości 0. Program już działa :)

Podobne pytania

0 głosów
1 odpowiedź 88 wizyt
+1 głos
1 odpowiedź 402 wizyt
pytanie zadane 1 marca 2022 w Java przez ptomeccc Użytkownik (800 p.)
0 głosów
1 odpowiedź 328 wizyt

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...