Diskuze: [Winforms] Playfairova šifra
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 20 zpráv z 20.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
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!
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++];
}
Tak jsem si to zkusil. Něco s toho vyleze. Je to bez chybových hlášení.
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.
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ě <code>prvniNahrada</code> (znak, kterého se potřebuje zbavit), tak prostě zvětší <code>m</code>. Ve druhé podmínce si znovu ověřuje, zda múže <code>m</code> 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š.
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
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)...
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ť
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.
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.
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?
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í
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á?
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?
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
Zobrazeno 20 zpráv z 20.