Jak se naučit překonávat obtíže a zároveň psát smyčky

I když se jedná o jedno z základních témat, tento článek je napsaný pro zkušené odborníky. Cílem je ukázat, jaké mylné představy mají nováčci v programování. Pro praktikující vývojáře jsou tyto problémy dávno vyřešeny, zapomenuty nebo si jich vůbec nevšimli. Článek může být užitečný, pokud budete muset někomu pomoci s tímto tématem. V článku se provádějí paralely s materiálem z různých knih o programování autorství Schildta, Stroustrupa, Okulova.

Téma cyklů bylo vybráno, protože na něm se řada lidí při osvojování programování odfiltruje.

Tato metoda je určena pro slabé studenty. Obvykle silní se na tomto tématu nezastavují a není potřeba pro ně vymýšlet speciální metody. Druhotným cílem článku je převést tuto metodiku z kategorie „funguje na všech studentech, ale pouze u jednoho učitele“ do kategorie „funguje u všech studentů, všech učitelů“. Nehledám naprostou originalitu. Pokud už používáte podobnou metodu pro výuku tohoto tématu, prosím napište, čím se váš variant liší. Pokud se rozhodnete ji aplikovat, podělte se, prosím, o výsledky. Pokud je podobná metoda popsána v nějaké knize, napište, prosím, její název.


Tuto metodiku jsem vypracovával 4 roky, pracoval jsem individuálně se studenty různých úrovní přípravy. Celkem asi padesát studentů a dvě tisíce hodin výuky. Zpočátku se na tomto tématu studenti věčně zasekávali a odcházeli. Po každém studentovi byla metodika a materiály upraveny. Během posledního roku už studenti na tomto tématu nezůstávali, a tak jsem se rozhodl podělit o vypracované materiály.

Proč tolik písmen? Cyklus je přece elementární!

Jak jsem již uvedl výše, pro praktikující vývojáře a silné studenty může být složitost konceptu cyklů podceňována. Například je možné uspořádat dlouhou přednášku, vidět přikyvující hlavy a chytré oči. Ale při pokusu vyřešit nějaký úkol nastává zmatek a nepochopitelné problémy. Po přednášce si studenti jistě vytvořili pouze částečné pochopení. Situaci zhoršuje to, že studenti nedokážou sami vyjádřit, v čem přesně spočívá jejich mylná představa.
Jednou jsem si uvědomil, že studenti vnímají moje příklady jako hieroglyfy. To znamená jako nedělitelné kusy textu, do kterých je třeba doplnit nějaké „magické“ písmeno, a vše se rozběhne.
Někdy jsem si všiml, že studenti si myslí, že k vyřešení konkrétního úkolu potřebují nějakou jinou konstrucci, kterou jsem jim ještě neřekl. Přitom k vyřešení stačilo jen trochu upravit příklad.

Proto jsem došel k myšlence, že je důležité se soustředit nejen na syntaxi výrazů, ale také na myšlenku refaktorizace opakujícího se kódu pomocí smyček. Jakmile studenti ovládnou tuto myšlenku, je jakákoli syntaxe zvládnuta drobnými cvičeními.

Komu a proč učím

Protože nejsou žádné přijímací zkoušky, mohou na lekcích být jak silní, tak velmi slabí studenti. Více o svých studentech se můžete dočíst v článku Portrét posluchačů večerních kurzů
Usiloval jsem o to, aby programování zvládly všechny, kdo chtějí.
Moje lekce probíhají individuálně a student platí své peníze za každou. Zdálo by se, že studenti budou optimalizovat náklady a požadovat minimum. Nicméně lidé navštěvují prezenční lekce se živým učitelem nikoli kvůli samotným znalostem, ale pro pocit jistoty, že toho zvládli hodně, pro pocit pokroku a pro schválení od experta (učitele). Pokud studenti nebudou cítit pokrok ve svém učení, odejdou. Celkově lze lekce uspořádat tak, aby studenti pocítili pokrok v zvyšujícím se počtu známých konstrukcí. To znamená, že nejprve podrobně studujeme while, poté studujeme for, a pak do while, a máme tak připravený kurz na tisíc a jednu noc, ve kterém se po dobu dvou měsíců studují pouze smyčky, a na konci je student, který podle diktátu napsal standardní knihovnu. Nicméně k řešení praktických úkolů je potřeba nejen znalost materiálu, ale i samostatnost v jeho aplikaci a vyhledávání nových informací. Proto považuji za správný princip pro prezenční kurzy naučit minima a povzbuzovat samostatné studium nuancí a příbuzných témat. V tématu o smyčkách považuji za minimum konstrukci while. Na ní je možné pochopit princip. Znaje princip, lze samostatně zvládnout i for a do-while.

Aby slabší studenti zvládli učební materiál, nestačí popsat syntaxi. Je třeba nabídnout více jednoduchých, ale různorodých úkolů a podrobněji vysvětlit příklady. Konečně, rychlost osvojení je omezena schopností studenta transformovat výrazy a hledat vzory. Pro bystré studenty budou většina úkolů nudná. Při práci s nimi se nemusí trvat na vyřešení 100 % úloh. Můj materiál si můžete prohlédnout na mém githubu. Pravda, repozitář spíše připomíná grimář černokněžníka – nikdo kromě mě nepochopí, co kde je, a pokud neprojde kontrolou, může se zbláznit.

Metodika je zaměřena na praxi.

Teorie je vysvětlována na příkladu řešení úlohy. Na lekcích o základech programování, kde se studují větvení a cykly, není možné uspořádat užitečnou přednášku na jedno téma na celou hodinu. 15-20 minut stačí k vysvětlení konceptu. Hlavní obtíže nastávají při plnění praktických úloh.
Začínající učitelé mohou prezentovat operátory, větvení, cykly a pole během jedné lekce. Jenže studenti se setkají s problémem osvojení těchto informací.
Není třeba jen předat materiál, je také nutné se ujistit, že posluchači mu rozumějí.

Skutečnost zvládnutí tématu se určuje podle toho, jak si student poradí s prací na samostatných úkolech.
Pokud se studentovi podařilo vyřešit úlohu na téma bez pomoci učitele, znamená to, že téma bylo zvládnuto. Aby bylo možné zajistit samostatné ověření, každá úloha obsahuje tabulku s testovacími scénáři. Úlohy mají jasně vymezený pořádek. Není doporučeno úkoly přeskočit. Pokud je aktuální úloha příliš složitá, je bezpředmětné přecházet k další. Ta je ještě složitější. Aby student zvládl aktuální složitou úlohu, je mu vysvětleno několik technik na příkladu první úlohy. Vlastně, veškerý obsah tématu se soustředí na techniky překonávání obtíží. Cyklus je spíše vedlejším efektem.

První úloha je vždy příkladem. Druhá se v zásadě mírně liší a je vykonávána „samostatně“ ihned po první pod dohledem učitele. Všechny následující úlohy jsou zaměřeny na to, aby upozornily na různé detaily, které mohou vyvolávat nedorozumění.

Vysvětlení příkladu je dialog, ve kterém student musí využít zpětné šíření a křížovou validaci, aby se ujistil, že zvládl část materiálu.

Budu banální a prohlásím, že první příklad na téma je velmi důležitý. Pokud je k dispozici materiál pro rozsáhlou samostatnou práci, mohou se nedostatky prvního příkladu napravit. Pokud není nic jiného kromě příkladu, student pravděpodobně téma nezvládne.

While nebo for?

Jedna z diskutabilních otázek je výběr konstrukce pro příklad: while nebo for. Jednou mě můj známý zkušený vývojář bez učitelských zkušeností hodinu přesvědčoval, že cyklus for je nejjednodušší na pochopení. Jeho argumenty se soustředily na to, že "je v něm všechno jasné a na svém místě". Avšak skutečný důvod obtíží skutečných nováčků je ve vlastní myšlence cyklu, nikoli v jeho zápisu. Pokud člověk tuto myšlenku nepochopí, bude mít potíže se syntaxí. Jakmile je myšlenka pochopena, problémy s formátováním kódu zmizí samy.

V mých materiálech téma cyklů následuje po tématu větvení. Vnější podobnost if a while umožňuje přímou analogii: "když je podmínka v hlavičce pravdivá, vykoná se tělo". Specifikum cyklu je pouze to, že se tělo vykonává mnohokrát.

Druhý můj argument je ten, že while vyžaduje méně formátování než for. Méně formátování znamená méně hloupých chyb s vynechanými čárkami a závorkami. U nováčků ještě není dostatečně rozvinutá pozornost a důvtip, aby automaticky vyhýbali syntaktickým chybám.
Třetí argument — v mnoha dobrých knihách se while vysvětluje jako první.

Pokud student snadno transformuje výrazy, lze o for mluvit okrajově. Student si pak sám zvolí, co se mu více líbí. Pokud však transformace přinášejí potíže, je lepší nerušit pozornost. Ať se student nejdříve vyrovná se vším pomocí while. Jakmile zvládne téma cyklů, můžeme přepsat řešení, abychom procvičili transformaci while na for.
Cykly s postpodmínkou jsou docela vzácné. Na ně vůbec nestrácím čas. Pokud student zvládl myšlenky odhalování vzorců a transformace výrazů, dokáže to pochopit i bez mé pomoci.

Při demonstraci prvního příkladu silným studentům upozorňuji na to, že v prvním příkladu je důležité zdokumentovat nejen řešení, ale i celou řadu kroků, které vedly k výsledku. Líným studentům se může zdát, že stačí napsat jen konečný algoritmus. Jejich je třeba přesvědčit, že jednoho dne narazí na náročný úkol. K jeho vyřešení bude potřeba projít jednotlivými kroky, jak je uvedeno v tomto příkladu. Právě proto je důležité zaznamenat všechny fáze. U dalších úkolů pak lze uvést pouze konečnou variantu řešení.

Hlavní myšlenkou automatizace je, že přidělujeme počítači vykonávání rutinní práce za člověka. Jedním ze základních triků je psaní cyklů. To se používá, když se v programu provádí několik stejných opakujících se činností po sobě.

Jasné je lepší než nejasné

Na první úkol o cyklech se může zdát dobrý nápad vypsat na obrazovku nějakou stejnou frázi několikrát. Například:

Hurá, funguje to!
Hurá, funguje to!
Hurá, funguje to!
Hurá, funguje to!
Hurá, funguje to!
Hurá, funguje to!
Hurá, funguje to!
Hurá, funguje to!

Tato varianta je špatná, protože v výstupu není vidět hodnota čítače. To je problém pro začátečníky. Není dobré ho podceňovat. Na začátku byla tato úloha první a úloha o výpisu řady čísel vzestupně byla druhá. Bylo třeba zavést další termíny jako "cyklus Nkrát" a "cyklus od A do B", které v podstatě znamenají totéž. Abychom nezakládali zbytečné entity, rozhodl jsem se ukázat jen příklad s výpisem řady čísel. Jen málo lidí se dokáže bez přípravy naučit mít v hlavě čítač a modelovat chování programu v mysli. Někteří studenti se poprvé setkávají s modelováním "v mysli" právě na téma cyklů.
Po nějaké praxi dám úkol na opakování stejného textu k samostatnému řešení. Pokud dám nejdříve viditelný čítač a pak neviditelný, mají studenti méně problémů. Někdy stačí nápověda "nepiš čítač na obrazovku".

Jak to vysvětlují jinde?

Ve většině vzdělávacích materiálů na internetu je syntaxe cyklu uváděna v rámci "přednášky". Například na developer.mozilla.org (v současnosti) je spolu s cyklem while popsáno několik dalších konstrukcí. Přitom jsou uvedeny pouze samotné konstrukce ve formě šablon. Výsledek jejich spuštění je popsán slovy, a ilustrace chybí. Podle mého názoru taková prezentace tématu snižuje užitečnost těchto materiálů na nulu. Student může přepsat kód a spustit ho sám, ale přesto potřebuje etalon pro srovnání. Jak pochopit, že je příklad přepsán správně, pokud není co srovnávat s výsledkem?
Když je poskytnuta pouze šablona, bez příkladu, studentovi se to ještě ztěžuje. Jak pochopit, že jsou kódové fragmenty ve šabloně správně umístěny? Můžete se pokusit napsat nějak, a pak to spustit. Ale pokud není etalon pro srovnání výsledku, tak spuštění také nepomůže.

V kurzu C++ na Intuitu je syntaxe cyklu zakopána na třetí stránce přednášky 4 na téma „operátory“. Při vysvětlování syntaxe cyklů je kladen zvláštní důraz na termín „operátor“. Termín je podáván jako soubor faktů jako „symbol; to je operátor“, "{} je složený operátor", „tělo cyklu musí být operátorem“. Tento přístup mi nelíbí, protože jakoby skrývá důležité souvislosti za jedním termínem. Rozbor zdrojového kódu programu na termíny na takové úrovni potřebují vývojáři kompilátorů pro implementaci specifikace jazyka, ale rozhodně ne studenti na prvním přiblížení. Nováčci v programování zřídka mají dostatečnou pečlivost, aby se takto důkladně věnovali termínům. Málokdo si zapamatuje a pochopí nová slova napoprvé. Prakticky nikdo nemůže správně použít termín, který se právě dozvěděl. Proto studentům vzniká spousta chyb jako „napsal jsem while(a<7);{, a program nefunguje“.
Podle mě by na začátku mělo být dáno syntaxe konstrukce hned se závorkami. Variant bez závorek by se měl vysvětlovat pouze v případě, že student má konkrétní otázku „proč je zde bez závorek a funguje to“.

V knize Okulova „Základy programování“ z roku 2012 začíná seznámení s cykly šablonou for, poté následně poskytuje doporučení k jejímu použití a pak hned následuje experimentální část výuky. Chápu, že kniha byla napsána pro to menšinové, velmi nadané žactvo, které se na moje kurzy málokdy dostává.

V populárních knihách je vždy uveden výsledek úryvků kódu. Například u Šildtova díla „Java 8. Kompletní průvodce“ z roku 2015. Nejprve je uvedena šablona, pak příklad programu a hned za ním — výsledek provedení.

Jako příklad si vezměme cyklus while, ve kterém se provádí zpětný
odpočet, počínaje číslem 10, a vychází přesně 10 řádků „takty“:

//Продемонстрировать применение оператора цикла while
class While {
    public static void main(String args []) {
        int n = 10;
        while (n > 0) {
            System.out.println("такт " + n);
            n--;
        }
    }
}

Po spuštění tento program vypíše deset „takty“ následujícím způsobem:
takt 10
takt 9
takt 8
takt 7
takt 6
takt 5
takt 4
takt 3
takt 2
takt 1

Přístup s popisem šablony, příkladu programu a výsledku jeho práce se používá také v knize „Javascript pro děti“ a v kurzu js na w3schools.com. Formát webové stránky dokonce umožňuje udělat tento příklad interaktivním.

V knize Stroustrupa „Principy a praxe používání C++“ z roku 2016 autor zašel ještě dál. Nejdříve se vysvětlí, jaký výsledek by měl být, a teprve potom se ukazuje text programu. Navíc jako příklad se nebere jen tak náhodná program, ale je zde dána exkurze do historie. To pomáhá zaměřit pozornost na to „Podívej, to není obyčejný bezcenný text. Vidíš něco významného“.

Jako příklad iterace si vezměme první program, který byl proveden na stroji se stored program (EDSAC). Napsal ho David Wheeler v počítačové laboratoři Cambridge University v Anglii 6. května 1949. Tento program vypočítává a tiskne jednoduchý seznam čtverců.
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

Zde v každém řádku je číslo, za ním následuje tabulátor (‘t’) a čtverec tohoto čísla. Verze tohoto programu v jazyce C++ vypadá takto:

//Вычисляем и распечатываем таблицу квадратов чисел 0-99
int main()
{
    int i = 0; // Начинаем с нуля
    while(i < 100){
        cout << i << 't' << square(i) << 'n';
        ++i;
    }
}

Zajímavé je, že vzor syntaktického zápisu v této knize není popsán. Stroustrup v učitelském průvodci (překlad) zdůrazňuje, že respektuje inteligenci svých studentů. Možná, že umění odhalit vzor ve více příkladech se považuje za projev takové inteligence.

Jak to vysvětluji já sám

Přístup Stroustrupa: nejprve popis výsledku, poté řešení úkolu a pak samostatná analýza studentem — vypadá jako nejpromyšlenější. Rozhodl jsem se na tomto základu postavit, ale popisovat na méně historickém příkladu — úkolu týkajícím se výstupu „obsahu“. Ten vytváří rozpoznatelný odkaz, abych pak mohl říci „vzpomínej na úkol o obsahu“, a studenti si jej skutečně vybavili. Ve svém příkladu jsem se pokusil varovat před ještě dvěma z nejběžnějších omylů. O nich budu psát podrobněji.

Na tomto úkolu se seznamujeme s metodami řešení složitějších problémů. Původní řešení by mělo být primitivní a jednoduché. Poté můžeme přemýšlet o tom, jak toto řešení zlepšit.
Úvod
Kapitola 1
Kapitola 2
Kapitola 3
Kapitola 4
Kapitola 5
Hlava 6
Hlava 7
Závěr

Podle mých pozorování přístup „šablona-příklad-výsledek“ v různých kombinacích stejně vede k tomu, že studenti vnímají cyklus jako hieroglyf. Projevovalo se to tím, že nechápali, proč tam psát podmínku, jak vybírat mezi i++ a i— a dalšími na první pohled zřejmými věcmi. Abychom se vyhnuli těmto omylům, přístup k vyprávění o cyklech by měl zdůraznit smysl opakování stejných činností a teprve poté — jejich formátování pomocí konstrukce. Proto je třeba před tím, než dáme syntaxi cyklu, vyřešit úkol „přímo“. Primitivní řešení úkolu o obsahu vypadá takto:

Console.WriteLine("Úvod");
Console.WriteLine("Kapitola 1");
Console.WriteLine("Kapitola 2");
Console.WriteLine("Kapitola 3");
Console.WriteLine("Kapitola 4");
Console.WriteLine("Kapitola 5");
Console.WriteLine("Kapitola 6");
Console.WriteLine("Kapitola 7");
Console.WriteLine("Závěr");

Jak ho lze zlepšit?
Nahradit jednotvárné úkony cyklem.
Jaké úkoly se zde opakují za sebou bez změn?
V tomto úryvku takové nejsou. Nicméně příkazy pro výstup slova „Kapitola“ s číslem si jsou velmi podobné.
Proto je dalším krokem hledání rozdílu mezi úryvky. To právě v tomto úkolu je všechno zřejmé, později se budou opakovat nikoli jednotlivé příkazy, ale bloky kódu o 5 řádcích a více. Hledat bude nutné nejen v seznamu příkazů, ale také ve větvení nebo cyklech.
V příkladu je rozdíl mezi příkazy v čísle za slovem „Kapitola“.
Jakmile je rozdíl nalezen, je třeba pochopit pravidlo změny. Je rozdílný úryvek číslo? Pravidelně se zvyšuje nebo snižuje? Jak se mění hodnota čísla mezi dvěma příkazy vedle sebe?
V příkladu se číslo za slovem „Hlava“ zvyšuje o 1. Rozdíl byl nalezen, byla odhalena zákonitost. Nyní můžeme nahradit odlišující fragment proměnnou.
Tuto proměnnou je třeba deklarovat před prvním z opakujících se fragmentů. Takové proměnné se obvykle říká i nebo j nebo nějakým rozšířenějším způsobem. Její počáteční hodnota by měla být rovna prvnímu hodnotě, která se zobrazí na obrazovce. V příkladu je první hodnota 1.
Jakou počáteční hodnotu je třeba vzít pro zobrazení řady čísel „100, 101, 102, 103, 104, 105“?
V této řadě je prvním číslem 100.
Po každém příkazu pro výstup je potřeba zvýšit hodnotu této proměnné o 1. Tato jednička je krok změny.
Jaký krok bude v řadě čísel „100, 102, 104, 106“?
V této řadě je krok 2.
Po nahrazení odlišujícího fragmentu proměnnou bude kód vypadat takto:

Console.WriteLine("Úvod");
int i;
i = 0;
Console.WriteLine("Hlava " + i);
i = i + 1;
Console.WriteLine("Hlava " + i);
i = i + 1;
Console.WriteLine("Hlava " + i);
i = i + 1;
Console.WriteLine("Hlava " + i);
i = i + 1;
Console.WriteLine("Hlava " + i);
i = i + 1;
Console.WriteLine("Hlava " + i);
i = i + 1;
Console.WriteLine("Hlava " + i);
i = i + 1;
Console.WriteLine("Závěr");

Po použití přístupu „vyjádřit zákonitost proměnnou“ získáme v kódu několik skupin stejných akcí, které jdou za sebou. Nyní lze opakující se akce nahradit cyklem.

Postup řešení úkolu, kde je potřeba použít cykly, se skládá z etap:

  1. Řešit „hlavou“ pomocí mnoha jednotlivých příkazů
  2. Najít zákonitost
  3. Vyjádřit zákonitost proměnnou
  4. Upravit do podoby cyklu

Dále se zavádějí nové termíny, aby student nebyl v situaci „všechno rozumím, ale říct nemohu“:
— čítač — vždy proměnná, která je potřebná pro sledování počtu kroků cyklu. Obvykle celé číslo, které se porovnává s omezením.
— krok čítače — popis zákonitosti změny čítače.
— omezení — číslo nebo proměnná, se kterou se čítač porovnává, aby algoritmus byl konečný. Hodnota čítače se mění tak, aby se přibližovala k omezení.
— tělo cyklu — soubor příkazů, které se budou opakovat. Když se říká „příkaz napsán uvnitř cyklu“, míní se právě tělo.
— iterace cyklu — jednorázové provedení těla cyklu.
— podmínka cyklu — logický výraz, od kterého závisí, zda bude provedena další iterace. (Zde může dojít k záměně s větvovacími konstrukcemi)
Je potřeba být připraven na to, že v prvních chvílích studenti nebudou používat termíny správně. To platí jak pro silné, tak pro slabé. Vytvoření společného jazyka je celé umění. Teď to napíšu stručně: je potřeba stanovit úkol „vyber fragment kódu s “ a sám tyto termíny správně používat v konverzaci.
Po transformaci s cyklem dostáváme fragment:

Console.WriteLine("Úvod");
int i = 0;
while (i < 7) {
    Console.WriteLine("Kapitola " + i);
    i = i + 1;
}
Console.WriteLine("Závěr");

Hlavní omyl

Jedno z populárních omylů studentů je, že do konstrukce cyklu umísťují akce, které je potřeba provést jen jednou. Například takto:

;
int i = 0;
while (i < 7) {
    Console.WriteLine("Úvod")
    Console.WriteLine("Kapitola " + i);
    i = i + 1;
    Console.WriteLine("Závěr");
}

Žáci se neustále s touto problémou setkávají jak na začátku, tak v složitějších úlohách.
Klíčová rada v tomto případě:

Kolikrát je potřeba psát příkaz: jednou nebo mnohokrát?

Příkazy pro výstup slov "Úvod" a "Závěr", stejně jako deklarace a inicializace proměnné i, se neliší od ostatních opakovaných akcí. Provedou se jednou, takže je potřeba je napsat mimo tělo cyklu.

V kódu by měly zůstat všechny tři fáze řešení, abychom se na ně mohli později odvolávat v případě potíží. První dvě varianty stačí okomentovat, aby nepřekážely.
Pozornost studenta by měla být zaměřena na následující fakta:
— V podmínce cyklu se obvykle porovnává čítač a omezení. Čítač se může měnit v těle cyklu, ale omezení ne. K porušení tohoto pravidla je potřeba mít pádné důvody.
— Příkazy pro výstup slov "Úvod" a "Závěr" jsou mimo tělo cyklu. Tyto musíme vykonat jednou. "Úvod" — před opakováním akce, "Závěr" — po něm.
V procesu upevňování této tématiky, osvojování následujících a také při objasňování obtíží je i silným studentům prospěšné klást otázku: „A kolikrát je potřeba tuto akci vykonat? Jednou nebo mnohokrát?“

Rozvoj dalších dovedností

Při studiu cyklů si studenti stále procvičují dovednosti diagnostiky a řešení problémů. Pro provedení diagnostiky musí student představit požadovaný výsledek a porovnat ho se skutečným výsledkem. Od rozdílu mezi nimi závisí kroky k nápravě.
Jelikož si studenti v této fázi ještě špatně představují „požadovaný“ výsledek, mohou se řídit testovacími daty. Obvykle nikdo v této fázi ještě nechápe, co se může pokazit a jak s tím bojovat. Proto píšu do sešitu popis typických problémů a několik způsobů jejich řešení. Výběr nejvhodnějšího z nich je úkolem samotného studenta.
Zaznamenání je důležité, abychom se mohli ptát „dosáhli jsme toho, co jsme očekávali?“, „Jaká z těchto situací se nyní stala?“, „Pomohlo přijaté řešení?“.

  1. Počet akcí je o 1 menší nebo větší, než se očekávalo. Způsoby řešení:
    — zvýšit počáteční hodnotu čítače o 1.
    — nahradit přísný operátor porovnání () na uvolněný (=).
    — změnit hodnotu limitu na 1.
  2. Akce v cyklu se provádějí bez zastavení, nekonečně. Způsoby řešení:
    — přidat příkaz ke změně čítače, pokud chybí.
    — opravit příkaz ke změně čítače tak, aby se jeho hodnota přibližovala k limitu.
    — odstranit příkaz ke změně limitu, pokud je v těle cyklu.
  3. Počet akcí v cyklu je o více než 1 menší nebo větší, než se očekávalo. Akce v cyklu nebyla provedena ani jednou. Nejprve je třeba zjistit skutečné hodnoty proměnných těsně před začátkem cyklu. Způsoby řešení:
    — změnit počáteční hodnotu limitu
    — změnit počáteční hodnotu čítače

Obvykle je problém 3 spojen s použitím špatné proměnné nebo nezresetováním čítače.

Po tomto vysvětlení mohou mít studenti stále různá mylná přesvědčení ohledně funkce cyklů.
Abych vyvrátil nejběžnější, dávám úkoly:

  1. V které limit, počáteční hodnota čítače nebo krok čítače je zadán uživatelem.
  2. V které je třeba použít hodnotu čítače v nějakém aritmetickém výrazu. Je žádoucí, aby čítač byl v područním výrazu nebo ve jmenovateli, aby byla rozdíl neliniární.
  3. Kde se hodnota čítače nezobrazuje na obrazovce během běhu cyklu. Například k výstupu potřebného počtu stejných fragmentů textu nebo k nakreslení figura pomocí želví grafiky.
  4. Kde je třeba nejprve provést některé opakující se akce a poté jiné.
  5. Kde je třeba provést další akce před a po opakujících se.

Pro každý úkol je třeba poskytnout testovací data a očekávaný výsledek.

Abychom pochopili, jak rychle můžeme postoupit, musíme nechat přečíst podmínky těchto úkolů a zeptat se: „Čím se liší od příkladu?“, „Co je třeba změnit v příkladu, abychom je vyřešili?“. Pokud student smysluplně odpoví, pak ať vyřeší alespoň jeden na hodině, ostatní ať dělá doma sám. Pokud bude řešení úspěšné, můžeme začít vysvětlovat podmínky uvnitř cyklů.
Pokud se studentům obtížně hledá samostatné řešení, je třeba vše procvičit na hodině. Aby řešení úkolu nepřipomínalo kreslení sovy, doporučuji nejprve vyřešit úkol neuniversálně. To znamená tak, aby řešení prošlo prvním testem a nepoužívalo konstrukci cyklu. A poté již aplikovat transformace, aby bylo dosaženo univerzálnosti řešení.

Cyklus a větvení

Podle mého názoru je užitečné dát téma „cykly uvnitř větvení“ zvlášť. Aby bylo následně vidět rozdíl mezi vícenásobnou kontrolou podmínky a jednorázovou.
Úkoly pro upevnění budou o výstupu čísel od A do B, které zadává uživatel:
— vždy v rostoucím pořadí.
— v rostoucím nebo klesajícím pořadí v závislosti na hodnotách A a B.

Na téma „větvení uvnitř cyklů“ by se mělo přecházet pouze poté, co student ovládne techniky: „nahrazení pravidelnosti proměnnou“ a „nahrazení opakujících se akcí cyklem“.
Hlavní důvod pro použití větvení uvnitř cyklů je anomálie v pravidelnosti. Uprostřed se rozrušuje v závislosti na vstupních datech.
Těm studentům, kteří jsou schopni hledat řešení kombinováním jednoduchých technik, stačí říct „větvení lze psát uvnitř cyklů“ a dát úkol „pro příklad“ zcela k samostatnému řešení.
Příklad úkolu:

Uživatel zadá číslo X. Vypsat ve sloupci čísla od 0 do 9 a umístit znak ‘+’ vedle toho čísla, které se rovná X.

Pokud bylo zadáno 00+
1
2
3
4
5
6
7
8
9

Pokud bylo zadáno 60
1
2
3
4
5
6+
7
8
9

Pokud bylo zadáno 90
1
2
3
4
5
6
7
8
9+

Pokud bylo zadáno 7770
1
2
3
4
5
6
7
8
9

Pokud není dostatečné krátké vysvětlení, jak napsat s cyklem, je nutné dosáhnout univerzálního řešení této úlohy bez cyklu.
Bude existovat jedna ze dvou možností:
Požadované

string temp;
temp = Console.ReadLine();
int x;
x = int.Parse(temp);
if (x==0) {
    Console.WriteLine(0 + "+");
} else {
    Console.WriteLine(0);
}
if (x==1) {
    Console.WriteLine(1 + "+");
} else {
    Console.WriteLine(1);
}
if (x==2) {
    Console.WriteLine(2 + "+");
} else {
    Console.WriteLine(2);
}
if (x==3) {
    Console.WriteLine(3 + "+");
} else {
    Console.WriteLine(3);
}
if (x==4) {
    Console.WriteLine(4 + "+");
} else {
    Console.WriteLine(4);
}
if (x==5) {
    Console.WriteLine(5 + "+");
} else {
    Console.WriteLine(5);
}
if (x==6) {
    Console.WriteLine(6 + "+");
} else {
    Console.WriteLine(6);
}
if (x==7) {
    Console.WriteLine(7 + "+");
} else {
    Console.WriteLine(7);
}
if (x==8) {
    Console.WriteLine(8 + "+");
} else {
    Console.WriteLine(8);
}
if (x==9) {
    Console.WriteLine(9 + "+");
} else {
    Console.WriteLine(9);
}

Možný

string temp;
temp = Console.ReadLine();
int x;
x = int.Parse(temp);
if (x==0) {
    Console.WriteLine("0+n1n2n3n4n5n6n7n8n9");
}
if (x==1) {
    Console.WriteLine("0n1+n2n3n4n5n6n7n8n9");
}
if (x==2) {
    Console.WriteLine("0n1n2+n3n4n5n6n7n8n9");
}
if (x==3) {
    Console.WriteLine("0n1n2n3+n4n5n6n7n8n9");
}
if (x==4) {
    Console.WriteLine("0n1n2n3n4+n5n6n7n8n9");
}
if (x==5) {
    Console.WriteLine("0n1n2n3n4n5+n6n7n8n9");
}
if (x==6) {
    Console.WriteLine("0n1n2n3n4n5n6+n7n8n9");
}
if (x==7) {
    Console.WriteLine("0n1n2n3n4n5n6n7+n8n9");
}
if (x==8) {
    Console.WriteLine("0n1n2n3n4n5n6n7n8+n9");
}
if (x==9) {
    Console.WriteLine("0n1n2n3n4n5n6n7n8n9+");
}

Podobnou úlohu dávám dopředu během studia tématu o větvení.
Pokud student dosáhl "možného" výsledku, měl by vědět, že pro stejnou úlohu může existovat více řešení. Nicméně se liší odolností vůči změnám požadavků. Zeptejte se: „Kolikrát v kódu bude potřeba upravit, pokud přidáme další číslo?“ V "možné" variantě bude nutné přidat další větvení a napsat nové číslo na 10 jiných místech. V "požadovaném" stačí přidat jen jedno větvení.
Stanovte úkol reprodukovat "požadovanou" variantu, poté najděte v kódu vzorec, proveďte výměnu proměnné a napište cyklus.
Pokud máte nápad, jak tuto úlohu vyřešit bez cyklu nějakým jiným způsobem, prosím, napište to do komentářů.

Cykly uvnitř cyklů

V tomto tématu je třeba věnovat pozornost tomu, že:
— počitadla pro vnitřní a vnější cyklus by měla být odlišnými proměnnými.
— Počítadlo pro vnitřní cyklus je třeba nulovat mnohokrát (tedy v těle vnějšího cyklu).
V úlohách pro výstup textu není možné nejprve napsat jedno písmeno na několik řádků a poté druhé. Nejprve je nutné vypsat všechna písmena z prvního řádku, poté všechna písmena z druhého a tak dále.

Vysvětlení tématu o cyklech uvnitř cyklů je nejlepší začít vysvětlením důležitosti nulování čítače.
Příklad úkolu:

Uživatel zadá dvě čísla: R a T. Vypište dva řádky symbolů "#". V prvním řádku by mělo být R kusů symbolů. Ve druhém řádku T kusů. Pokud bude některé číslo záporné, vypište chybové hlášení.

R=5, T=11#####
###########

R=20, T=3####################
###

R=-1, T=6Hodnota R musí být nezáporná

R=6, T=-2Hodnota T musí být nezáporná

Je zřejmé, že tato úloha má také minimálně dvě varianty řešení.
Požadované

string temp;
int R;
int T;
temp = Console.ReadLine();
R = int.Parse(temp);
temp = Console.ReadLine();
T = int.Parse(temp);
int i = 0;
while (i < R)
{
    Console.Write("#");
    i = i + 1;
}
Console.WriteLine();
i = 0;
while (i < T)
{
    Console.Write("#");
    i = i + 1;
}

Varianta č. 1

string temp;
int R;
int T;
temp = Console.ReadLine();
R = int.Parse(temp);
temp = Console.ReadLine();
T = int.Parse(temp);
int i = 0;
while (i < R)
{
    Console.Write("#");
    i = i + 1;
}
Console.WriteLine();
int j = 0;
j = 0;
while (j < T)
{
    Console.Write("#");
    j = j + 1;
}

Rozdíl spočívá v tom, že v "možném" řešení pro výstup druhého řádku byla použita druhá proměnná. Je třeba prosazovat použití stejné proměnné pro oba cykly. Takové omezení lze odůvodnit tím, že řešení s jedním čítačem pro dva cykly bude ilustrací termínu "nulování čítače". Porozumění tomuto termínu je nutné při řešení následujících úloh. Jako kompromis je možné uchovat obě řešení úlohy.

Typický problém s použitím jedné proměnné-čitače pro dva cykly se projevuje takto:
R=5, T=11#####
######

Počet symbolů ve druhém řádku neodpovídá hodnotě T. Pokud potřebujete pomoc s tímto problémem, je nutné "ukázat nos" do náčrtu o typických problémech s cykly. To je symptom č. 3. Diagnostikuje se, pokud přidáte výstup hodnoty čítače těsně před druhým cyklem. Opraveno nulováním. Ale to je lepší hned neříkat. Student by se měl pokusit formulovat alespoň jednu hypotézu.

Existuje samozřejmě také taková varianta řešení. Ale já ji u studentů nikdy neviděl. V fázi studia cyklů by vyprávění o ní rozptylovalo pozornost. K tomu se můžeme vrátit později, při studiu funkcí práce se řetězci.
Varianta č. 2

string temp;
int R;
int T;
temp = Console.ReadLine();
R = int.Parse(temp);
temp = Console.ReadLine();
T = int.Parse(temp);
Console.WriteLine(new String('#', R));
Console.WriteLine(new String('#', T));

Následující povinný úkol:

Na obrazovku vypište číslice od 0 do 9. Každá číslice by měla být na svém řádku. Počet číslic na řádku (W) se zadává z klávesnice.

W=10
1
2
3
4
5
6
7
8
9

W=100000000000
1111111111
2222222222
3333333333
4444444444
5555555555
6666666666
7777777777
8888888888
9999999999

Pokud student ovládl přístup s nahrazením proměnné, zvládne to docela rychle. Možný problém znovu bude s nulováním proměnné. Pokud si neporadíte s převodem, znamená to, že jste spěchali a je potřeba vyřešit jednodušší úkoly.

Děkuji za pozornost. Dejte like, přihlaste se k kanálu.

P.S. Pokud jste našli překlepy nebo chyby v textu, prosím, dejte mi vědět. To lze udělat zvýrazněním části textu a stisknutím na Macu „⌘ + Enter“, nebo na klasických klávesnicích „Ctrl / Enter“, případně prostřednictvím soukromých zpráv. Pokud tyto možnosti nejsou k dispozici, napište o chybách do komentářů. Děkuji!

Pouze registrovaní uživatelé se mohou účastnit ankety. Přihlaste se, prosím.

Anketa pro čtenáře bez karmy

  • 20,0%Učím profesionálně, +12

  • 10,0%Učím profesionálně, -11

  • 70,0%Neučím, +17

  • 0,0%Neučím, -10

  • 0,0%Jiné0

Hlasovalo 10 uživatelů. Zdrželo se 5 uživatelů.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster