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

question-closed Łamanie szyfru Cezara

VPS Starter Arubacloud
0 głosów
534 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 (22,150 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ź 111 wizyt
+1 głos
1 odpowiedź 546 wizyt
pytanie zadane 1 marca 2022 w Java przez ptomeccc Użytkownik (800 p.)
0 głosów
1 odpowiedź 364 wizyt

93,032 zapytań

141,996 odpowiedzi

321,300 komentarzy

62,379 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

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...