Geek tričko zdarma Python týden
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde
Pouze tento sleva až 80% na kurzy Python

Diskuze: [Winforms] Playfairova šifra

Aktivity (4)
Avatar
Lolindir
Člen
Avatar
Lolindir:12. ledna 17:44
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Playfair
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        string OT = string.Empty;
        string osetrenyOT = string.Empty;
        string jazyk = "CZ";
        char prvniNahrada = new char();
        char druhaNahrada = new char();
        char[] vysledek = new char[25];
        char[] sDiakritikou = "ĚŠČŘŽÝÁÍÉÚŮŤĎŇ".ToCharArray();
        char[] bezDiakritiky = "ESCRZYAIEUUTDN".ToCharArray();
        char[] abeceda = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
        char[,] tabulka = new char[5,5];
        int m = new int();

        public static string OdstranDiakritiku(string Text)
        {
            string stringFormD = Text.Normalize(System.Text.NormalizationForm.FormD);
            System.Text.StringBuilder retVal = new System.Text.StringBuilder();
            for (int index = 0; index < stringFormD.Length; index++)
            {
                if (System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stringFormD[index]) != System.Globalization.UnicodeCategory.NonSpacingMark)
                    retVal.Append(stringFormD[index]);
            }
            return retVal.ToString().Normalize(System.Text.NormalizationForm.FormC);
        }

        private void tB_vstupniKlic_TextChanged(object sender, EventArgs e)
        {
        }
        private void buttonPrevod_Click(object sender, EventArgs e)
        {
            bool OTprazdny = string.IsNullOrEmpty(OT);
            if (OTprazdny == false)
            {

            }
            OT = tB_vstupniKlic.Text;
        //tabulka = new char[5,5];

            if (jazyk == "CZ")
            {
                prvniNahrada = 'W';
                druhaNahrada = 'V';
            }
            if (jazyk == "EN")
            {
                prvniNahrada = 'J';
                druhaNahrada = 'I';
            }
            osetrenyOT = OdstranDiakritiku(OT).ToUpper();
            /*
            if (osetrenyOT.ToUpper().ToCharArray().Except(abeceda).Count() > 0)
            {
                tB_vstupniKlic.Text = String.Empty;
                OT = String.Empty;
                System.Diagnostics.Process.Start(Application.ExecutablePath); // to start new instance of application
                this.Close(); //to turn off current app
                return;
            }
            */
            string bezDuplikatu = string.Join("", osetrenyOT.ToCharArray().Distinct());

            if (bezDuplikatu.Contains('W') && jazyk == "CZ")
            {
                bezDuplikatu = bezDuplikatu.Replace(prvniNahrada, druhaNahrada);
                bezDuplikatu = string.Join("", bezDuplikatu.ToCharArray().Distinct());
            }
            if (bezDuplikatu.Contains('J') && jazyk == "EN")
            {
                bezDuplikatu = bezDuplikatu.ToString().Replace(prvniNahrada, druhaNahrada);
                bezDuplikatu = string.Join("",bezDuplikatu.ToCharArray().Distinct());
            }

            abeceda = new string(abeceda).Replace(prvniNahrada, druhaNahrada).ToCharArray();
            vysledek = bezDuplikatu.Union(abeceda.Except(bezDuplikatu).ToArray()).ToArray(); //ošetřená klíčová tabulka formou Array
            m = 0;
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    if (m < 24 && vysledek[m] == prvniNahrada)
                    {
                        m++;
                    }
                    if (m < 25)
                    {
                        tabulka[i, j] = vysledek[m++];
                    }
                }
            }

            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    tB_vyslednyText.AppendText("" + tabulka[j, 0]+ " | " + tabulka[j, 1] + " | " + tabulka[j, 2] + " | " + tabulka[j, 3]+ " | " + tabulka[j, 4]);
                    tB_vyslednyText.AppendText(Environment.NewLine);
                    tB_vyslednyText.Font = new Font(FontFamily.GenericMonospace, tB_vyslednyText.Font.Size);
                }
            }
        }

        private void tB_vyslednyText_TextChanged(object sender, EventArgs e)
        {

        }

        private void rB_JazykCZ_CheckedChanged(object sender, EventArgs e)
        {
            if (rB_JazykCZ.Checked == true)
            {
                jazyk = "CZ";
                /*
                prvniNahrada = 'W';
                druhaNahrada = 'V';
                */
            }
        }

        private void rB_JazykEN_CheckedChanged(object sender, EventArgs e)
        {
            if (rB_JazykEN.Checked == true)
            {
                jazyk = "EN";
                /*
                prvniNahrada = 'J';
                druhaNahrada = 'I';
                */
            }
        }
    }
}

Při přepnutí jazyka z jednoho na druhý jde proměnná m mimo hranice pole

Zkusil jsem: Resetovat program při změně jazyka
Měnit jazyk jinde v programu

Chci docílit: Naprogramovat playfairovu šifru dle tohoto návodu
Návod

Je velice možné že některé pasáže v mém kódu jsou zbytečné, či přehnaně složité. Programování mi zatím moc nejde, momentálně se snažím přežít druhý ročník studia Softwarového Inženýrství

Editováno 12. ledna 17:47
 
Odpovědět 12. ledna 17:44
Avatar
HONZ4
Člen
Avatar
HONZ4:13. ledna 13:52

Zběžně jsem se díval na ten kód, tady jsem našel místo, kde hrozí riziko:

if (m < 25) //pokud tady bude 24
{
 tabulka[i, j] = vysledek[m++]; //tady se bude přistupovat k  vysledek[25];
}

To pole vysledek má pouze 25 prvků, takže max. index je 24!

Editováno 13. ledna 13:54
 
Nahoru Odpovědět 13. ledna 13:52
Avatar
Lolindir
Člen
Avatar
Odpovídá na HONZ4
Lolindir:13. ledna 13:57

Velice děkuji. Můžu se zeptat, jak bych to mohl opravit?

 
Nahoru Odpovědět 13. ledna 13:57
Avatar
HONZ4
Člen
Avatar
Odpovídá na Lolindir
HONZ4:13. ledna 14:13

Mě se ta šifra nechce studovat. Takže nevím co to má dělat.
Buďto zvětši pole,

char[] vysledek = new char[26];

nebo zmenši rozsah.:

if (m < 24)
{
 tabulka[i, j] = vysledek[m++];
}
Editováno 13. ledna 14:13
 
Nahoru Odpovědět 13. ledna 14:13
Avatar
HONZ4
Člen
Avatar
HONZ4:13. ledna 14:21

Omlouvám se. Kecám. Ty to máš vlastně dobře. Nejprve se načte a až pak přiřadí..

 
Nahoru Odpovědět 13. ledna 14:21
Avatar
HONZ4
Člen
Avatar
Odpovídá na Lolindir
HONZ4:13. ledna 14:43

Tak jsem si to zkusil. Něco s toho vyleze. Je to bez chybových hlášení.

 
Nahoru Odpovědět 13. ledna 14:43
Avatar
Odpovídá na Lolindir
Matúš Olejník:13. ledna 14:46
m = 0;
for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        if (m < 24 && vysledek[m] == prvniNahrada)
        {
            m++;
        }
        if (m < 25)
        {
            tabulka[i, j] = vysledek[m++];
        }
    }
}

Tu keď ti bude platiť prvá podmienka if (m < 24 && vysledek[m] == prvniNahrada) v ktorej dávaš m++ tak ti určite (skoro vždy) bude platiť aj druhá podmienka if (m < 25) v ktorej tiež inkrementuješ m takže hodnota v m môže byť ďaleko väčšia ako 24 a v tom prípade ideš mimo hranice pola vysledek. Takže tam sa zameraj na opravu.

Editováno 13. ledna 14:48
Nahoru Odpovědět 13. ledna 14:46
/* I am not sure why this works but it fixes the problem */
Avatar
Odpovídá na Matúš Olejník
Andy Scheuchzer:13. ledna 16:38

Tu keď ti bude platiť prvá podmienka if (m < 24 && vysledek[m] == prvniNahrada) v ktorej dávaš m++ tak ti určite (skoro vždy) bude platiť aj druhá podmienka if (m < 25) v ktorej tiež inkrementuješ m takže hodnota v m môže byť ďaleko väčšia ako 24 a v tom prípade ideš mimo hranice pola vysledek. Takže tam sa zameraj na opravu.

Počkej, můžeš mi vysvětlit, co na tom má špatně? Pokud jsem ten kód pochopil dobře, tak v případě, že je na daném místě prvniNahrada (znak, kterého se potřebuje zbavit), tak prostě zvětší m. Ve druhé podmínce si znovu ověřuje, zda múže m použít (i když zrovna pevná hodnota není nejšťastnější řešení).

Lolindir když jsem to procházel, zdálo se mi, že je to v naprostém pořádku (teda až na přehlednost). Btw. řekl bych, že v první podmínce v kódu, co zmiňoval Matúš, ani tu 24 nepotřebuješ.

Nahoru Odpovědět  +1 13. ledna 16:38
Člověk, co si myslí, že snědl všechnu moudrost světa, i když tomu tak není.
Avatar
Odpovídá na Andy Scheuchzer
Matúš Olejník:14. ledna 9:37

Ahoj, keď som to pozeral cez mobil tak som si veľmi nevšimol, že pred tým cyklom nahrádza nejaké písmená za iné takže táto podmienka vysledek[m] == prvniNahrada v tomto prípade nikdy nebude platiť , čiže sa tam nikdy neinkrementuje m až o 2 v jednom cykle. Ďakujem za pripomienku :)

Nahoru Odpovědět  +1 14. ledna 9:37
/* I am not sure why this works but it fixes the problem */
Avatar
Odpovídá na Andy Scheuchzer
Michal Štěpánek:14. ledna 12:17

Nevím přesně, co by to mělo dělat, ale podle mě se povedou skoro vždy obě ty podmínky, tzn., že v té druhé se bude znovu inkrementovat to již jednou navýšené "m" z předchozí podmínky. Myslím, že by tam mělo být "else if", tedy v případě, že se m=24 spustit druhou podmínku.
Pokud to ovšem nemá být účelem (ta dvojitá inkrementace)...

Nahoru Odpovědět 14. ledna 12:17
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Odpovídá na Michal Štěpánek
Matúš Olejník:14. ledna 12:37

Na to som narážal pôvodne aj ja, ale ešte pred tým cyklom má

abeceda = new string(abeceda).Replace(prvniNahrada, druhaNahrada).ToCharArray();
vysledek = bezDuplikatu.Union(abeceda.Except(bezDuplikatu).ToArray()).ToArray();

čím vlastne z vysledek vymaže znak z prvniNahrada a teda tá prvá podmienka nikdy nebude platiť :D

Nahoru Odpovědět  +1 14. ledna 12:37
/* I am not sure why this works but it fixes the problem */
Avatar
Odpovídá na Michal Štěpánek
Andy Scheuchzer:14. ledna 18:38

Možná by ještě bylo přece jen dobré si ten článek přečíst. Pak to budeš chápat naprosto bez problému.
Ve zkratce: máš heslo, za něj přidáš abecedu, odstraníš duplikáty, a protože z toho potřebuješ čtverec (5 × 5), musíš jedno písmeno „vyrazit“. V originále je to J (místo něj I), ale v češtině je logičtější W a V.

Matúš Olejník Tak toho jsem si přes všechen ten kód ani nevšiml (teda zapomněl jsem na to), díky.

Nahoru Odpovědět  +1 14. ledna 18:38
Člověk, co si myslí, že snědl všechnu moudrost světa, i když tomu tak není.
Avatar
Lolindir
Člen
Avatar
Lolindir:14. ledna 21:23

Proč tedy můj kód funguje jak má, ale pouze do chvíle než přepnu jazyk?

Pokud na začátku zvolím jazyk EN, a teprve potom zadám slovo, tak program funguje jak má.
Pokud na začátku zvolím jazyk CZ, a pak zadám slovo, tak program také funguje jak by měl.
Problém nastává, když už je jeden jazyk zvolený, a chci zvolit jiný. Do jeho abecedy už se totiž nedostanou písmena, které mají vypadnout v abecedě v případě druhého jazyka.

 
Nahoru Odpovědět 14. ledna 21:23
Avatar
HONZ4
Člen
Avatar
Odpovídá na Lolindir
HONZ4:15. ledna 17:37

co si přesně myslíš že dělá toto:

vysledek = bezDuplikatu.Union(abeceda.Except(bezDuplikatu).ToArray()).ToArray();
a co od toho čekáš?

použij přesně toto a uvidíš, že to bude fungovat:

private void buttonPrevod_Click(object sender, EventArgs e)
{
    tB_vyslednyText.Clear();
    bool OTprazdny = string.IsNullOrEmpty(OT);
    if (OTprazdny == false)
    {

    }
    OT = tB_vstupniKlic.Text;
    //tabulka = new char[5,5];
    string bezDuplikatu = string.Join("", osetrenyOT.ToCharArray().Distinct());



    if(jazyk == "CZ")
    {
        prvniNahrada = 'W';
        druhaNahrada = 'V';
        if (bezDuplikatu.Contains('W'))
        {
            bezDuplikatu = bezDuplikatu.Replace(prvniNahrada, druhaNahrada);
            bezDuplikatu = string.Join("", bezDuplikatu.ToCharArray().Distinct());
        }
    }
    else//jazyk EN
    {
        prvniNahrada = 'J';
        druhaNahrada = 'I';
        if (bezDuplikatu.Contains('J'))
        {
            bezDuplikatu = bezDuplikatu.ToString().Replace(prvniNahrada, druhaNahrada);
            bezDuplikatu = string.Join("", bezDuplikatu.ToCharArray().Distinct());
        }
    }


    abeceda = new string(abeceda).Replace(prvniNahrada, druhaNahrada).ToCharArray();
    vysledek = bezDuplikatu.Union(abeceda.Except(bezDuplikatu).ToArray()).ToArray(); //ošetřená klíčová tabulka formou Array
    m = 0;
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            if (m < vysledek.Length-1 && vysledek[m] == prvniNahrada)
            {
                m++;
            }
            if (m < vysledek.Length)
            {
                tabulka[i, j] = vysledek[m++];
            }
        }
    }

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            tB_vyslednyText.AppendText("" + tabulka[j, 0] + " | " + tabulka[j, 1] + " | " + tabulka[j, 2] + " | " + tabulka[j, 3] + " | " + tabulka[j, 4]);
            tB_vyslednyText.AppendText(Environment.NewLine);
            tB_vyslednyText.Font = new Font(FontFamily.GenericMonospace, tB_vyslednyText.Font.Size);
        }
    }
}

ten kód jsem schválně moc neměnil, abys se vtom vyznal.

Není náhodou problém i v tom, že před spuštění nové akce nevymažeš výstupní textbox?

Editováno 15. ledna 17:39
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět  +2 15. ledna 17:37
Avatar
Lolindir
Člen
Avatar
Odpovídá na HONZ4
Lolindir:19. ledna 15:08

Velice děkuji, pravděpodobně to vyřešilo všechny mé problémy. Přidal jsem už i vymazání vstupního textboxu na začátku, čehož jsem si dřív nevšiml.

Dále nahrazení m < 24 za m < vysledek.Length i o pár řádků níž vyřešilo můj druhý problém, což jsem si dřív neuvědomil.

Velice děkuji za čas a ochotu všech kteří mi nabídli pomoc. Těší mě, že přispíváte k zlepšování mých programovacích schopností :)

 
Nahoru Odpovědět 19. ledna 15:08
Avatar
Lolindir
Člen
Avatar
Odpovídá na Lolindir
Lolindir:19. ledna 15:11

Narazil jsem však ještě na jeden problém:

V případě kdy zadám tento náhodný řetězec jako klíč, uqiweuwo (proměnná OT):
vygenerovaná tabulka pak vypadá takto:
U | Q | I | V | E
O | A | B | C | D
F | G | H | K | L
M | N | P | R | S
T | X | Y | Z | Z

Což je problém. Tabulka nesmí obsahovat stejné znaky, a musí být vždy rozměru 5x5, se znaky klíče které se neopakují jinde v tabulce + se zbytkem abecedy. Mohu se zeptat co mi zde uniká?

Editováno 19. ledna 15:12
 
Nahoru Odpovědět 19. ledna 15:11
Avatar
Lolindir
Člen
Avatar
Lolindir:19. ledna 15:28

Oprava: Tato tabulka vznikne při přepnutí jazyka z CZ na EN a poté zpět na CZ. Při prvním vygenerování jen CZ jazyka a poté i EN jazyka, vznikne tabulka jak má.

 
Nahoru Odpovědět 19. ledna 15:28
Avatar
Lolindir
Člen
Avatar
Odpovídá na Lolindir
Lolindir:19. ledna 16:55

Zjistil jsem že problém je v tom, když z CZ jazyka přepnu na EN a poté zpět na CZ, program začne brát v úvahu obě pravidla náhrady písmen, které ale nesmí platit současně.

Český jazyk:
W -> V

Anglický jazyk
J -> I

Při přepnutí jazyka v pořadí CZ -> EN -> CZ se na písmena ve Vysledek[] aplikují pravidla jak z CZ jazyka tak EN. Ve výsledku je tedy nakonec o jedno písmeno méně, jelikož ho odstranilo pravidlo z druhého jazyka, které se ale v tomto případě nemělo aplikovat.

Dokázal by mi někdo poradit, jak bych toto mohl vyřešit?

Editováno 19. ledna 16:56
 
Nahoru Odpovědět 19. ledna 16:55
Avatar
Odpovídá na Lolindir
Matúš Olejník:19. ledna 17:36
abeceda = new string(abeceda).Replace(prvniNahrada, druhaNahrada).ToCharArray();

Premennú abeceda máš ako globálnu premennú. Najprv máš celú abecedu, keď je jazyk CZ vyradíš z nej W keď prepneš na EN tak z tej abecedy kde už chýba W vyradíš ešte I. Daj ju ako lokálnu premennú alebo nejako resetuj do pôvodného stavu. Ak nepomôže hoď sem aktuálny kód už sa v tom strácam keďže je to tu poskladané z viacerých príspevkov :)

Nahoru Odpovědět  +1 19. ledna 17:36
/* I am not sure why this works but it fixes the problem */
Avatar
Lolindir
Člen
Avatar
Lolindir:19. ledna 17:38

Ano, to vyřešilo můj problém. Velice děkuji :)

Editováno 19. ledna 17:41
 
Nahoru Odpovědět  +1 19. ledna 17:38
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 20 zpráv z 20.