IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Nejspíš nějaké chyby

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Matěj Klimeš:13.3.2020 19:53

Chtěl bych se Vás všech zeptat, co mám špatně. Snažil jsem se vytvořit program, který normální zprávu zašifruje do morseovky, jenže při vypsání zakódovaného textu se vypíše jen otazník. Řekne mi někdo, kde mám chybu? Předem díky.

Zkusil jsem: Zkusil jsem různě přepisovat zadaný text k zakódování, ale marně.

Chci docílit: Program na dekódování a zakódování morseovky

 
Odpovědět
13.3.2020 19:53
Avatar
Odpovídá na Matěj Klimeš
Matúš Olejník:13.3.2020 20:44

Ahoj, nabudúce sem namiesto obrázka pošli tvoj kód ako text :)

Správa ktorú chceš zašifrovať je v premennej s = "itnetwork"
Tú si chceš rozsekať zrejme po znakoch čomu naznačuje kód. Avšak s.split(" ") ti rozseká správu v tomto prípade po medzerách. Keďže však itnetwork žiadnu medzeru neobsahuje tak v poli znaky bude jeden reťazec, ktorý bude obsahovať celú pôvodnú správu.

Toto následne spôsobí, že celý cyklus sa vykoná len raz, pretože v tom poli je len jeden prvok. To som len objasnil prečo práve jeden otáznik :D

Chcel som písať ďalej, ale ako pozerám viac ten kód tak to máš celkom zamotané :D Samozrejme nič v zlom, treba nejako začať :) a keďže vidím, že sa snažíš tak nebudem písať riešenie ale spýtam sa ťa aký bol tvoj plán ako by to malo fungovať a môžme to potom dať dokopy spolu :) Napr. čo tam má riešiť ten otáznik atď

Editováno 13.3.2020 20:45
Nahoru Odpovědět
13.3.2020 20:44
/* I am not sure why this works but it fixes the problem */
Avatar
Matěj Klimeš:14.3.2020 9:54

no já zatím tak začínám (a vím, že by to nejspíš šlo jednodušeji, ale s mýma znalostma to zatím nejde a dokud mi to někdo nevysvětlí nebo se to někde nedočtu tak jsem spokojen s tímto :-) ) a napadlo mě že když je v deváté lekci (Základní konstrukce jazyka Java) dekódér morseovky tak že by jsem mohl zkusit udělat program na zakódování...

String s = "itnetwork";
System.out.prin­tf("Původní zpráva: %s\n", s);
// řetězec s zakódovanou zprávou
String zprava = "";

// vzorová pole
String abecedniZnaky = "abcdefghijklmnop­qrstuvwxyz"; //ASCII - 97 až 122
String[] morseovyZnaky = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
"..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-",
"...-", ".--", "-..-", "-.--", "--.."};

// rozbití řetězce na písmena abecedy
String[] znaky = s.split(" ");

// iterace znaky morzeovky
for (String abecedníZnak : znaky) {
char morseuvZnak = '?';

int index = -1;
for (int i = 0; i < abecedniZnaky­.length(); i++) {
if (morseovyZnaky[i]­.equals(morse­uvZnak))
index = i;
}

if (index >= 0) { // znak nalezen
morseuvZnak = morseovyZnaky[-1].charAt(index);
}
zprava += morseuvZnak;
}

System.out.prin­tf("Zakódovaná zpráva: %s\n", zprava);

ten otazník by měl znázorňovat jakože se to neví nebo tak něco a potom to for(int = i, atd...) by ty písmenka mělo najít a zaměnit za morseovku (opět se odkazuji na devátou lekci Základní konstrukce jazyka Java). A k té předešlé odpovědi, měl jsem jenom přidat mezery ke vstupu nebo jsem to špatně pochopil (při přidání mezer se již zobrazil stejný počet otazníků jako písmen ve vstupu, ale morseovka nikde)

 
Nahoru Odpovědět
14.3.2020 9:54
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:14.3.2020 10:28

Zkus příště třetí pokus a dávej ten kód do tagů (tlačítko nahoře nad editorem textu </>). :)

Jinak nebudu teď zasahovat Matúšovi do rad, vysvětluje ti to pěkně, ale mám dojem, že jsi nepochopil, jak funguje pole.

Editováno 14.3.2020 10:31
Nahoru Odpovědět
14.3.2020 10:28
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Odpovídá na Lubor Pešek
Matúš Olejník:14.3.2020 13:02

Ďakujem, ale kľudne píš :D som síce zatvorený doma, ale na záhrade je stále čo robiť, takže nie som toľko pri PC :D

Nahoru Odpovědět
14.3.2020 13:02
/* I am not sure why this works but it fixes the problem */
Avatar
Odpovídá na Matěj Klimeš
Matúš Olejník:14.3.2020 13:02

Ahoj, skúsim ti sem dať hint ako dotiahnuť tvoj kód, s tým, že som niektoré premenné nazval anglicky, čo môžeš urobiť aj ty nech si zvykáš :D
Ak to stále nepôjde tak píš kľudne ďalej a ja alebo Lubor alebo niekto iný určite pomôžeme :)

String unencryptedText = "itnetwork";
//rozseká správu po medzerách, takže pole bude obsahovať jednotlivé slová
String[] unencryptedWords = unencryptedText.split(" ");

//prechádzanie jednotlivých slov, nie písmen!!
for (String unencryptedWord : unencryptedWords) {
    //vytvorenie poľa s jednotlivými písmenami daného slova
    char[] letters = unencryptedWord.toCharArray();
    //prechádzanie jednotlivých písmen
    for (char letter : letters) {
        //chápem čo si chcel docieliť vo svojom kóde, ale aj keď by mohlo byť lahšie riešenie
        //tak môžeš dokončiť svoj nápad :)
        //Len treba dávať pozor čo porovnávaš, ty si týmto morseovyZnaky[i].equals(morseuvZnak) porovnával
        //String s char a už to by nefungovalo. Rovnako ako som ti ukázal ako prechádzať písmená v slove
        //môžeš prechádzať tie tvoje abecedniZnaky keď si ich dáš do poľa znakov abecedniZnaky.toCharArray()
        //a budeš pracovať s tým polom
    }
}

Keď sa s tým budeš hrať tak si asi všimneš, že napr. morseovyZnaky[-1] so záporným indexom ti bude hádzať chybu, na ktorú ťa už určite aj editor upozorňuje tým, že je to podsvietené :) A rovnako si myslím, že to dokážeš aj bez toho otazníka :D

Nahoru Odpovědět
14.3.2020 13:02
/* I am not sure why this works but it fixes the problem */
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:14.3.2020 13:03

:) ok

Nahoru Odpovědět
14.3.2020 13:03
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:14.3.2020 15:16

Jak říkal Matúš, je to matoucí text a teď proč...
Uvědom si první věc - ne každý sedí vedle tebe a ne každý přemýšlí stejně jako ty. Neuvažuješ špatně, ale tvoje pojmenování není nejvhodnější (proto si ze sebe my ITáci děláme prdel, že z celého objemu programování jen 5% času vyvíjíme a 95% času vymýšlíme vhodné názvy:) )
Ale teď vážně. Kupříkladu tvůj popis:

String zprava = "";

Ano, dobře jsi k tomu přidal komentář, ale v tomto případě zbytečně.
Neboj se psát delší názvy proměnných (klidně i jednoduché malé věty).
Takže rovnou napiš něco ve smyslu:

String zakodovanaVstupniZpravaProPreklad = "";

Myslím, že u takového pojmenování nikdo nebude čekat, že je to pomocná proměnná či že v tom uvidí výsledek kódu nebo cokoliv jiného.

Teď k tomu poli. Počítač je hloupý stroj (to měj na paměti!. Vždy, když vrátí nějaký výsledek, tak proto, protože jsi mu to tak řekl).
Ty jsi si uložil 1 String a jedno pole.
Bylo by nejlepší, kdybys rovnou na jednom místě měl pole abecedních znaků a pole Morseových znaků. Bylo by to přehlednější a minimalizoval bys tím chybovost.
Nejlepší je i slovo "pole" (v lepším případě field:) ) přidávat i do názvů polí.
Takže by to mohlo vypadat takhle:

String abecedniZnaky = "abcdefghijklmnopqrstuvwxyz"; //ASCII - 97 až 122
String[] poleAbecednichZnaku = abecedniZnaky.split("");
String[] poleMorseovychZnaku = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
                "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-",
                "...-", ".--", "-..-", "-.--", "--.."};

Pak nastává ta tvoje chyba, o které už mluvil Matúš.
metoda split() skutečně rozdělí textový řetěz na pole, ale do uvozovek zadáváš znak, který má být ten rozdělovač.
Takže když máš třeba slovo bbbabbb a rozdělovač bude "a", tak budeš mít [bbb] a [bbb].
No a tys řekl počítači:
Rozděl slovo "abcdefghijklmnop­qrstuvwxyz" na bloky pomocí mezer.
No a počítač ti řekl: tak fajn, mezera tam není, tak mám jeden blok.
Proto ty jsi pracoval sice se dvěma poli. Jedno pole mělo jedno slovo (a-z) a druhé pole mělo 26 prvků.
A to už ti Matúš poradil, jak to napravit.

Ten tvůj znak na ten otazník je správné uvažování. Jestli už teď připouštíš možnost, že může nastat varianta, kterou jsi nepředpokládal, tak je to velmi dobrá cesta k tomu, aby ses stal dobrým programátorem.

Teď ti dám radu, jak příštím problémům čelit a jak jsme třeba postupovali my (já nebo Matúš). Samozřejmě, ber to s nadhledem, my už nějakou tu dobu programujeme, takže nám se to odehrává v palici, ale ukážu ti, jak postupovat při tzv. debuggování.
Samozřejmě nejlepší je debugger - to se tu také naučíš, ale třeba teď můžeš začít se Systémovkou. Nyní už sice tohle až tak moc nedoporučuju, protože z vlastní zkušenosti musím přiznat, že mě osobně dlouho trvalo, než jsem přešel plnohodnotně na debugger v IDEčkách, protože jsem si hodně zvykl na systémovky, ale frameworky to naučí každého:)

Tvůj kód vracel nesmysl - konkrétně otazník.
Postup uvažování je ptát se. (proč proč proč) a ověřování (funguje to tady? dostanu se sem? mám se sem dostat? Proč se sem nedostanu) :)
Neboj se klidně mluvit nahlas. Jednak se naučíš mluvit a hlavně když budeš mluvit nahlas, tak tím, že to uslyšíš a neřekneš si to jen v duchu, tak ti to mnohdy i docvakne (on ten mozek asi vážně jinak reaguje na to, co uslyší, než jen na to, co si myslí:) )
Takže bys mohl postupovat takto:
Proč to vrací otazník a co to má vlastně vracet?
A můžeš si procházet ten kód od main metody. Takže budeš ověřovat:

  1. vkládám nějaký text do proměnné s. To je sice kravina ověřovat, ale tak v rámci objektivnosti a ať to vypadá drsně, tak si za něj napíšeš na nový řádek:

System.out.prin­tln(s);
spustíš kód - fajn, vypíše se to

  1. to samé se zprávou (je to už hodně zbytečná blbost, ale beru to globálně, že je dobré ověřovat i v budoucnu každý řádek:) )
  2. abecedníZnaky. Je to string, se kterým budu pracovat. Je v něm uloženo to, co tam má být? Je
  3. To samé morzeovyZnaky. A vypíšu si to hezky cyklem a ověřím, že je to správné pole i se správným typem)

for(String znak:morseovyZnaky) {
System.out.prin­tln(znak);
}
Možná už tady by tě trklo... že by se sem hodilo, abych rovnou ověřil, že bude i ten předchozí seznam v poli. A třeba bych si s tím pohrál a ověřil, že je vše na správné cestě, když bych měl dvě pole o stejné velikosti, tak že bych si vytvořil jen tak z prdele takovou překládací tabulku.
Takže něco v tomhle smyslu:

String abecedniZnaky = "abcdefghijklmnopqrstuvwxyz"; //ASCII - 97 až 122
        String[] poleAbecednichZnaku = abecedniZnaky.split("");
        String[] poleMorseovychZnaku = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
                "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-",
                "...-", ".--", "-..-", "-.--", "--.."};
        for (int i = 0; i < poleAbecednichZnaku.length; i++) {
            System.out.printf("%s = %s\n", poleAbecednichZnaku[i], poleMorseovychZnaku[i]);
        }

A máš jistotu, že máš dvě připravená pole (a že každý znak bude správně přirovnaný).
Samozřejmě, až budeš po letech koukat na ten kód, tak zjistíš, že ještě lepší je třeba na tohle vytvořit si mapu<String, String>, kde první String bude abecední znak a druhý morseový. No a pak zase zjistíš, že bude ještě větší sranda načítat to ze souboru či databáze:) Ale to jen poznámka k motivaci:)

No a takhle bys došel na to, že ti třeba ten tvůj split(" ") nevrací to, co by sis přál. Protože místo hezkého seznamu prvků ti to vrátí:

abcdefghijklmnopqrstuvwxyz = .-

A to je divné, že?

No a to samé, když budeme pokračovat dál
Takže 5) by sis opět cyklem ověřil, že String[] znaky = s.split(" "); ti vrátí pole znaků (v tomhle případě bys očekával výstup:
i
t
n
e
t
w
o
r
k

No a ty dostaneš
itnetwork
Což by mohlo být i matoucí, protože by sis myslel, že na jednom řádku je to v pořádku. Proto je dobré si to pole projít a ke každému znaku i něco přidat. Příklad:

String[] znaky = s.split(" ");
        for (int i = 0; i < znaky.length; i++) {
            System.out.println(i + ": " + znaky[i]);
        }

A tady bys zjistil, že je něco divného, protože bys očekával už určitě 9 řádků a ono ti to vrátí jen jeden. A to už je hodně zvláštní.

  1. klidně i v tom průchodu, kdy procházíš jednotlivé znaky (neboli to, cos udělal v bodě pět), tak hned pod hlavičku cyklu si pro kontrolu ty znaky vypiš. V podstatě bys tím provedl kontrolu, co byla v bodě pět
  2. Ten char morseuvZnak = '?'; bych určitě necpal do cyklu. Zbytečně takhle vytváříš a zahazuješ proměnné. Ono se to nezdá, ale každé vytváření proměnné znamená několik operací (vytvoř místo v paměti pro proměnnou, proměnné přiřaď znak, proměnnou ulož a na konci interace tuto proměnou zahoď a v další interaci vytvoř novou proměnnou... atd. atd. Pochybuju, že bys to dělal jako člověk, tak proč k tomu nutíš počítač?:) )

Takže tohle bych určitě přesunul třeba na začátek metody, pokud ji budeš využívat jen tady.
Není to podstatná chyba, ale nauč se takhle uvažovat;)
Jinak zase pojmenování - morseuvZnak... Ano, v takovém lehkém kódu je to tolerovatelné, ale teď si představ, že pracuješ kupříkladu v jiné třídě a teď dostaneš tohle:

MorseovaAbeceda morseovaAbeceda = new MorseovaAbeceda();
morseovaAbeceda.znak();

No a jaký znak to asi vrátí? Vůbec to není intuitivní.
Jo kdyby tam bylo něco v tomhle smyslu:

MorseovaAbeceda morseovaAbeceda = new MorseovaAbeceda();
morseovaAbeceda.getOznaceniNeznamehoZnaku();

(get se budeš učit později, když se budeš učit metody)
Tak už můžu tušit, že tato metoda vrátí něco (podle datového typu, jestli číslo nebo String nebo char, prostě něco), čím označuje znak, který nezná. To už je jiné kafe.
Proto bych to takhle nějak nazval i u tebe, třeba právě tím označeníNezna­mehoZnaku. Právě tímto jsi nachytal Matúše, mě a kohokoliv jiného, protože nebylo patrné, co ten otazník znamená. Jestli to měl být tvůj nový vymyšlený znak, nebo právě takové označení, atd.
Neboj se proměnné popisovat delšími názvy. Furt lepší je názvy zkracovat, než po druhém luštit, co vlastně ta proměnná má znamenat.

  1. zase - index... Ok, toto označení se používá, ale v samostatných metodách, kde je patrné, že se skutečně pracuje se specifickým indexem a označuje to nějakou hodnotu potřebnou pro výpočet nebo iteraci nějakého průběhu. Tady procházíš znaky foreachem a najednou narazím na nějaký index. Nevím, jestli je to index pole, index znaku index počtu králíků, které má soused v kotcích. Takže pojmenovávat to lépe.
  2. No a tady těmi systémovky a otázky bys přišel i na to, že tam máš chybu právě kvůli tomu tvému morseovuZnaku. Blbé pojmenování a tak ti to ani hned tak nedojde, ale ty se v podstatě ptáš neustále, dokola, jestli je v tom vloženém znaku otazník. No a samozřejmě, že ti to nevrátí žádný index, protože není a i kdyby byl, tak ti to žádný index nevrátí, protože ho nemáš v těch tabulkách.

Navíc stačil by ti jeden for a index máš přehledně v něm:)

Tady ti to posílám funkčně, tak si to porovnej

String vstupniZpravaProPreklad = "test";
        String zakodovanaVystupniZpravaProPreklad = "";
        char oznaceniNeznamehoZnaku = '?';

        String abecedniZnaky = "abcdefghijklmnopqrstuvwxyz"; //ASCII - 97 až 122
        String[] poleAbecednichZnaku = abecedniZnaky.split("");
        String[] poleMorseovychZnaku = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
                "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-",
                "...-", ".--", "-..-", "-.--", "--.."};

        //Následující podmínka je jenom taková kontrola proti tomu, když bys nevyplnil nic:)
        if (vstupniZpravaProPreklad != null && !vstupniZpravaProPreklad.equals("")) {
            for (String znakVlozenehoSlova : vstupniZpravaProPreklad.split("")) {
                for (int i = 0; i < poleAbecednichZnaku.length; i++) {
                    //následující podmínku by sis mohl vyložit slovy: Pokud najdu znak, tak ho přidám do
                    // výstupní textu a ukončím smyčku (slovem break)
                    if (poleAbecednichZnaku[i].equals(znakVlozenehoSlova)) {
                        zakodovanaVystupniZpravaProPreklad += poleMorseovychZnaku[i];
                        break;
                    }
                    //do následující podmínky se dostaneš pouze za předpokladu, že jsi nenašel znak v poli.
                    // Tato podmínka platí pouze pro poslední průchod. Kdyby se v posledním průchodu ještě
                    // vyskytoval požadovaný znak, tak se zapíše a smyčka se ukončí (pomocí break).
                    // Takže tato podmínka skutečně projde pouze v jednom případě. Když se jedná o poslední znak z pole
                    // abecedy (čili "z") a pokud ani ten neprojde.
                    if (i == poleAbecednichZnaku.length - 1) {
                        zakodovanaVystupniZpravaProPreklad += oznaceniNeznamehoZnaku;
                    }
                }
                zakodovanaVystupniZpravaProPreklad += " | ";
            }
        }
        System.out.printf("Původní zpráva: %s\n", vstupniZpravaProPreklad);
        System.out.printf("Zakódovaná zpráva: %s\n", zakodovanaVystupniZpravaProPreklad);
Nahoru Odpovědět
14.3.2020 15:16
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:14.3.2020 15:16

Ach jo... proč mě vždycky z malé rady vyjde slohová práce?-.-

Nahoru Odpovědět
14.3.2020 15:16
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Odpovídá na Lubor Pešek
Matěj Klimeš:14.3.2020 18:29

To možná moc ne, myslel jsem si, že to pochopím za běhu, ale jak vidíš :-)

 
Nahoru Odpovědět
14.3.2020 18:29
Avatar
Matěj Klimeš:14.3.2020 18:32

Díky moc, asi nějak takhle jsem to potřeboval vysvětlit. Je mi 15 a teprve letos půjdu ne střední školu, obor IT. Myslím si, že po tomhle skvělém podrobném vysvětlení jsem to pochopil.

 
Nahoru Odpovědět
14.3.2020 18:32
Avatar
Odpovídá na Lubor Pešek
Matúš Olejník:14.3.2020 22:08

Myslím, že to sme všetci očakávali po tej krátkej správe "ok" :D

Nahoru Odpovědět
14.3.2020 22:08
/* I am not sure why this works but it fixes the problem */
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 12 zpráv z 12.