Hoe moeilijkheden te overwinnen en tegelijkertijd loops te schrijven

Hoewel het hier om een van de basis onderwerpen gaat, is dit artikel geschreven voor ervaren professionals. Het doel is om de misverstanden te laten zien die beginners in programmeren kunnen hebben. Voor praktiserende ontwikkelaars zijn deze problemen al lang opgelost, vergeten of worden ze totaal niet opgemerkt. Het artikel kan nuttig zijn als je ooit iemand moet helpen met dit onderwerp. Er worden parallellen getrokken met materiaal uit verschillende boeken over programmeren door auteurs als Schildt, Stroustrup en Okulov.

Het onderwerp over lussen is gekozen omdat veel mensen daarover struikelen bij het leren van programmeren.

Deze methode is gericht op zwakkere studenten. Over het algemeen blijven sterke studenten niet bij dit onderwerp hangen en hoeft er geen speciale methode voor hen te worden ontwikkeld. Een secundair doel van het artikel is om deze methode te vertalen van de categorie 'werkt voor alle studenten, maar alleen bij één docent' naar de categorie 'werkt voor alle studenten, bij alle docenten'. Ik claim niet dat het absoluut origineel is. Als je al een soortgelijke methode toepast om dit onderwerp te onderwijzen, laat dan alsjeblieft weten wat jouw variant anders maakt. Als je besluit het toe te passen, vertel dan als het klaar is hoe het ging. Als een vergelijkbare methode in een boek wordt beschreven, laat dan alsjeblieft de titel weten.


Ik heb deze methode vier jaar lang ontwikkeld, terwijl ik individueel met studenten van verschillende niveaus werkte. In totaal zo'n vijftig studenten en twee duizend uur aan lessen. Aanvankelijk bleven studenten voor altijd vastzitten op dit onderwerp en gingen ze weg. Na elke student werden de methode en de materialen aangepast. In het afgelopen jaar blijven studenten niet meer vastzitten op dit onderwerp, dus besloot ik mijn bevindingen te delen.

Waarom zoveel tekst? Lussen zijn toch simpel!

Zoals ik hierboven al schreef, kan de complexiteit van de concepten van lussen voor praktiserende ontwikkelaars en sterke studenten worden onderschat. Je zou bijvoorbeeld een lange lezing kunnen geven, knikkende hoofden en slimme blikken kunnen zien. Maar bij het proberen om een probleem op te lossen, komt de blokkade en onverklaarbare problemen. Na de lezing hebben studenten vermoedelijk slechts een gedeeltelijk begrip. De situatie wordt verergerd doordat studenten niet in staat zijn om zelf te verwoorden waar precies hun misverstand ligt.
Op een gegeven moment realiseerde ik me dat studenten mijn voorbeelden beschouwen als hiërogliefen. Dat wil zeggen, als ondeelbare stukken tekst waar ze een of ander 'magisch' letterteken aan moeten toevoegen om het te laten werken.
Soms merkte ik op dat studenten dachten dat voor het oplossen van een specifieke taak een bepaalde andere structuur nodig was, die ik gewoon nog niet had besproken. Terwijl voor de oplossing slechts een kleine wijziging van het voorbeeld nodig was.

Daarom kwam ik op het idee dat de focus niet op de syntaxis van de uitdrukkingen moet liggen, maar op het idee van het refactoren van herhalende code met behulp van lussen. Zodra de leerlingen dit idee begrijpen, kan elke syntaxis worden aangeleerd door middel van enkele eenvoudige oefeningen.

Aan wie en waarom geef ik les

Aangezien er geen toelatingsexamens zijn, kunnen er zowel sterke als zeer zwakke studenten in de lessen zitten. Meer over mijn studenten is te lezen in het artikel Het portret van de bezoekers van de avondcursussen
Ik streefde ernaar dat iedereen die het wilde, de kunst van het programmeren zou beheersen.
Mijn lessen zijn individueel en de student betaalt zijn eigen geld voor elke les. Het zou logisch zijn dat studenten hun kosten optimaliseren en het minimum eisen. Echter, mensen komen naar de fysieke lessen met een levende docent niet alleen voor de kennis, maar voor de zekerheid dat ze het goed hebben begrepen, voor het gevoel van vooruitgang en voor de goedkeuring van de expert (docent). Als studenten geen vooruitgang voelen in hun leerproces, zullen ze vertrekken. Over het algemeen kun je lessen structureren zodat studenten vooruitgang voelen in het aantal bekende structuren. Dat wil zeggen, we bestuderen eerst in detail de while-lus, dan leren we de for-lus, en dan de do-while-lus, en zo hebben we een cursus van duizend-en-één nacht, waarin twee maanden alleen de lussen worden bestudeerd, en aan het eind is er een student die de standaardbibliotheek kan schrijven uit dictaat. Maar om praktische taken op te lossen, heb je niet alleen kennis van de stof nodig, maar ook zelfstandigheid in het toepassen ervan en het zoeken naar nieuwe informatie. Daarom beschouw ik het als een goed principe voor fysieke cursussen om het minimum te onderwijzen en zelfstandig leren van nuances en gerelateerde onderwerpen aan te moedigen. Bij het onderwerp van lussen beschouw ik de while-constructie als het minimum. Daarop kan het principe worden begrepen. Als je het principe begrijpt, kun je ook de for-lus en de do-while-lus zelfstandig leren.

Om zwakke studenten de stof te laten beheersen, is het niet genoeg om alleen de syntaxis te beschrijven. Het is belangrijk om meer simpele, maar gevarieerde opdrachten te geven en voorbeelden uitgebreider uit te werken. Uiteindelijk wordt de snelheid van het leren beperkt door het vermogen van de student om uitdrukkingen om te zetten en patronen te herkennen. Voor slimme studenten zullen de meeste opdrachten saai zijn. Tijdens lessen met hen kan men zich veroorloven niet op het oplossen van 100% van de opdrachten aan te dringen. Mijn materiaal is te vinden op mijn github. Het is echter meer een grimoire van een tovenaar — niemand, behalve ik, begrijpt waar wat zich bevindt, en als de controle mislukt, kan men gek worden.

De methode is gericht op praktijk

De theorie wordt uitgelegd aan de hand van het oplossen van taken. In de programmeerlessen, waar vertakkingen en lussen worden bestudeerd, is het gewoon niet mogelijk om een nuttige lezing over één onderwerp een uur lang te organiseren. 15-20 minuten is genoeg om het concept uit te leggen. De belangrijkste moeilijkheden ontstaan bij het uitvoeren van praktische opdrachten.
Startende docenten kunnen operators, vertakkingen, lussen en arrays in één lezing behandelen. Maar studenten zullen dan tegen de uitdaging aanlopen deze informatie te begrijpen.
Het is immers niet alleen belangrijk om de stof te vertellen, maar ook om te zorgen dat de luisteraars het begrijpen.

Het feit dat de student het onderwerp heeft begrepen, blijkt uit hoe hij het zelfstandig werk aanpakt.
Als de student erin geslaagd is de taak over het onderwerp zonder hulp van de docent op te lossen, betekent dat dat het onderwerp is begrepen. Om zelfevaluatie mogelijk te maken, heeft elke taak een tabel met testscripts. De taken hebben een duidelijk gedefinieerde volgorde. Het is niet aan te raden om taken over te slaan. Als de huidige taak te moeilijk is, is het zinloos om naar de volgende over te gaan. Deze is namelijk nog moeilijker. Om de student te helpen de huidige moeilijke taak te begrijpen, worden enkele technieken uitgelegd aan de hand van de eerste taak. Eigenlijk komt alle inhoud van het onderwerp neer op technieken om moeilijkheden te overwinnen. Lussen zijn eerder een bijeffect.

De eerste taak is altijd een voorbeeld. De tweede verschilt niet significant en wordt 'zelfstandig' uitgevoerd direct na de eerste, onder toezicht van de docent. Alle daaropvolgende taken zijn gericht op het attenderen op verschillende details die misverstanden kunnen veroorzaken.

De uitleg van het voorbeeld is een dialoog waarin de student backpropagation en cross-validatie moet aanroepen om te bevestigen dat een deel van het materiaal is begrepen.

Ik zal banaal zijn en zeggen dat het eerste voorbeeld over het onderwerp heel belangrijk is. Als er materiaal is voor uitgebreide zelfstandige studie, kunnen eventuele tekortkomingen in het eerste voorbeeld worden hersteld. Als er verder niets is dan het voorbeeld, zal de student waarschijnlijk het onderwerp niet begrijpen.

While of for?

Een van de discutabele vragen is de keuze van de constructie voor het voorbeeld: while of for. Een keer probeerde een vriend van mij, een praktijkontwikkelaar zonder onderwijservaring, me een uur lang ervan te overtuigen dat de for-lus de eenvoudigste is om te begrijpen. De argumenten kwamen neer op 'alles is duidelijk en goed gestructureerd'. Echter, de echte oorzaak van de moeilijkheden voor echte beginners ligt in het idee van de lus zelf, en niet in de syntaxis. Als iemand dit idee niet begrijpt, zal hij moeite hebben met de syntaxis. Zodra het idee duidelijk is, verdwijnen de problemen met de codering vanzelf.

In mijn materialen volgt het onderwerp lussen na het onderwerp vertakkingen. De uiterlijke gelijkenis tussen if en while maakt een directe analogie mogelijk: 'wanneer de voorwaarde in de kop waar is, wordt de body uitgevoerd'. Het enige specialiteit van de lus is dat de body meerdere keren wordt uitgevoerd.

Mijn tweede argument is dat while minder opmaak vereist dan for. Minder opmaak betekent dat er minder domme fouten zijn door gemiste komma's en haakjes. Beginners hebben nog niet voldoende aandacht en nauwgezetheid ontwikkeld om automatisch syntactische fouten te vermijden.
Het derde argument is dat in veel goede boeken while als eerste wordt uitgelegd.

Als de student gemakkelijk uitdrukkingen kan omzetten, kan ik while in het voorbijgaan uitleggen. De student zal zelf kiezen wat hij het leukst vindt. Als de omzettingen echter moeilijk zijn, is het beter om de aandacht niet te verspreiden. Laat de student eerst alles met while oplossen. Zodra het onderwerp lussen is begrepen, kan hij de oplossingen herschrijven om de omzetting van while naar for te oefenen.
Lussen met een post-condition zijn een vrij zeldzaam fenomeen. Ik besteed daar helemaal geen tijd aan. Als de student de ideeën van patroonherkenning en uitdrukkingstransformaties beheerst, zal hij zonder mijn hulp in staat zijn om het te begrijpen.

Bij het demonstreren van het eerste voorbeeld aan sterke studenten, wijs ik erop dat het in dit voorbeeld belangrijk is om niet alleen de oplossing vast te leggen, maar ook de gehele reeks acties die leidde tot het resultaat. Luie studenten kunnen zich beperken tot een eindalgoritme en de uitwerking negeren. Ze moeten overtuigd worden dat ze ooit een complexe taak zullen tegenkomen. Om deze op te lossen, moeten ze stappen volgen zoals in dit voorbeeld. Daarom is het belangrijk om alle stappen vast te leggen. In de volgende taken kan alleen de definitieve oplossing worden gepresenteerd.

Het hoofddoel van automatisering is dat we computers de routinematige taken van mensen laten uitvoeren. Een van de basisprincipes is het schrijven van lussen. Dit wordt toegepast wanneer in het programma verschillende gelijke herhalende handelingen achter elkaar worden geschreven.

Expliciet is beter dan impliciet

Het kan een goed idee lijken om in de eerste lusopdracht een bepaalde zin meerdere keren op het scherm te tonen. Bijvoorbeeld:

Hoera, het werkt!
Hoera, het werkt!
Hoera, het werkt!
Hoera, het werkt!
Hoera, het werkt!
Hoera, het werkt!
Hoera, het werkt!
Hoera, het werkt!

Deze optie is slecht omdat de waarde van de teller niet zichtbaar is in de uitvoer. Dit is een probleem voor beginners. Dit moet niet worden onderschat. Aanvankelijk was deze taak de eerste, en de taak over het weergeven van een rij getallen in oplopende volgorde was de tweede. Het was nodig om extra termen in te voeren zoals 'lus N keer' en 'lus van A tot B', die in feite hetzelfde zijn. Om overbodige entiteiten te vermijden, heb ik besloten alleen het voorbeeld van het weergeven van de rij getallen te tonen. Niet veel mensen slagen erin om zonder voorbereiding het tellen in hun hoofd te houden en het gedrag van het programma in hun hoofd te modelleren. Sommige studenten worden voor het eerst geconfronteerd met 'denken in' op het onderwerp van lussen.
Na enige oefening geef ik de taak om een gelijke tekst te herhalen als zelfstandig probleemoplossing. Als ik eerst een zichtbare teller geef en daarna een onzichtbare, hebben studenten minder problemen. Soms is een aanwijzing als 'schrijf de teller niet naar het scherm' voldoende.

Hoe wordt het uitgelegd door anderen?

In de meeste lesmaterialen op internet wordt de syntaxis van de loop gepresenteerd in de vorm van een 'lezing'. Bijvoorbeeld op developer.mozilla.org (op dit moment) worden samen met de while-lus nog enkele andere constructies beschreven. Daarbij worden uitsluitend de constructies zelf als sjablonen gegeven. Het resultaat van hun uitvoering wordt in woorden beschreven, maar er ontbreekt een illustratie. Naar mijn mening reduceert zo'n presentatie de bruikbaarheid van dergelijke materialen tot nul. Een leerling kan de code overtypen en zelf uitvoeren, maar er is wel een referentie nodig om te vergelijken. Hoe kan je begrijpen dat het voorbeeld goed is herschreven als er niets is om het resultaat mee te vergelijken?
Wanneer alleen een sjabloon wordt gegeven, zonder voorbeeld, wordt het nog moeilijker voor de student. Hoe moet je begrijpen dat de codefragmenten goed in het sjabloon zijn geplaatst? Je kunt proberen om ergens, dit later uit te voeren. Maar als er geen referentie is om het resultaat mee te vergelijken, helpt de uitvoering ook niet.

In de C++-cursus op Intuit, wordt de syntaxis van de loop begraven op de derde pagina van lezing 4 over het onderwerp 'operatoren'. Bij de uitleg van de syntaxis van loops wordt er extra nadruk gelegd op de term 'operator'. De term wordt gepresenteerd als een reeks feiten zoals 'symbool; dit is een operator', '{} is een samengestelde operator', 'de body van de loop moet een operator zijn'. Ik hou niet van deze benadering omdat hij belangrijke verbanden achter één term verbergt. Het ontleden van de broncode van een programma op dat niveau is nodig voor compilers, maar zeker niet voor studenten in het begin. Beginners in programmeren hebben zelden de nodige nauwkeurigheid om zo zorgvuldig met termen om te gaan. Bijna niemand onthoudt en begrijpt nieuwe woorden bij de eerste keer. Vrijwel niemand kan een term correct toepassen die hij net heeft geleerd. Daarom ontstaat er bij studenten een hoop fouten zoals 'ik heb while(a<7);{ geschreven, maar het programma werkt niet'.
Naar mijn mening is het beter om in het begin de syntaxis van de constructie meteen met haakjes te geven. Een variant zonder haakjes moet alleen worden uitgelegd als de leerling een specifieke vraag heeft als 'waarom werken we hier zonder haakjes'.

In het boek van Okulov "Basisprincipes van programmeren" uit 2012 begint de kennismaking met loops met het for-sjabloon, gevolgd door aanbevelingen voor gebruik, en daarna volgt onmiddellijk een experimenteel gedeelte van de les. Ik begrijp dat het boek is geschreven voor die minderheid van zeer bekwame leerlingen die zelden op mijn lessen verschijnen.

In populaire boeken wordt altijd het resultaat van codefragmenten vermeld. Bijvoorbeeld in het boek van Schildt "Java 8. Volledige gids" uit 2015. Eerst wordt er een sjabloon gegeven, dan een voorbeeldprogramma en direct daarna het resultaat van de uitvoering.

Als voorbeeld nemen we de while-lus, waarin een terugteldfunctie wordt uitgevoerd,
beginnende bij 10, en precies 10 regels "beats" worden weergegeven:

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

Na het starten geeft dit programma tien "beats" als volgt weer:
tak 10
tak 9
tak 8
tak 7
tak 6
tak 5
tak 4
tak 3
tak 2
tak 1

De aanpak met het beschrijven van een sjabloon, voorbeeldprogramma en het resultaat van dat programma wordt ook gebruikt in het boek "Javascript voor kinderen" en in de js-cursus op w3schools.com. Het formaat van de webpagina maakt het zelfs mogelijk om dit voorbeeld interactief te maken.

In het boek van Stroustrup "Principes en praktijk met C++" uit 2016 gaat de auteur nog verder. Eerst wordt uitgelegd welk resultaat moet worden behaald, en pas daarna wordt de programmatext getoond. Bovendien nemen ze als voorbeeld niet zomaar een willekeurig programma, maar geven ze een excursie in de geschiedenis. Dit helpt om aandacht te vestigen op: "Kijk, dit is geen nutteloze tekst. Je ziet iets betekenisvols."

Als voorbeeld van iteratie beschouwen we het eerste programma dat is uitgevoerd op een machine met opgeslagen programma's (EDSAC). Het werd geschreven door David Wheeler in het computerlaboratorium van de Universiteit van Cambridge (Cambridge University, Engeland) op 6 mei 1949. Dit programma berekent en print een eenvoudige lijst van kwadraten.
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

Hierin bevat elke regel een getal, gevolgd door een tabteken (‘t’) en het kwadraat van dat getal. De versie van dit programma in C++ ziet er als volgt uit:

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

Het is opmerkelijk dat het syntaxis-sjabloon in dit boek niet wordt beschreven. Stroustrup benadrukt in de instructeurhandleiding (vertaling) dat hij het intellect van zijn studenten respecteert. Misschien wordt de vaardigheid om het sjabloon in verschillende voorbeelden te herkennen beschouwd als een uiting van dat intellect.

Zoals ik het zelf uitleg

De aanpak van Stroustrup: eerst de beschrijving van het resultaat, dan de oplossing van de taak, en tenslotte de zelfstandige analyse door de student — lijkt de meest doordachte te zijn. Daarom heb ik besloten om zijn aanpak als basis te nemen, maar dan te vertellen over een minder historisch voorbeeld — de taak om een ‘inhoudsopgave’ weer te geven. Dit creëert een herkenbaar anker, zodat we later kunnen zeggen ‘vergeet de taak over de inhoudsopgave niet’ en de studenten dit voorbeeld ook daadwerkelijk kunnen herinneren. In mijn voorbeeld heb ik geprobeerd nog twee van de meest voorkomende misvattingen te vermijden. Daarover zal ik verderop meer schrijven.

Bij deze taak maken we kennis met technieken voor het oplossen van complexe problemen. De eerste oplossing moet primitief en eenvoudig zijn. Vervolgens kunnen we nadenken over hoe we deze oplossing kunnen verbeteren.
Inleiding
Hoofdstuk 1
Hoofdstuk 2
Hoofdstuk 3
Hoofdstuk 4
Hoofdstuk 5
Hoofdstuk 6
Hoofdstuk 7
Conclusie

Uit mijn observaties blijkt dat de aanpak ‘sjabloon-voorbeeld-resultaat’ in verschillende combinaties er nog steeds toe leidt dat studenten de lus als een hieroglief beschouwen. Dit kwam tot uiting in het feit dat ze niet begrepen waarom ze een voorwaarde moesten schrijven, hoe te kiezen tussen i++ en i-- en andere schijnbaar voor de hand liggende dingen. Om deze misvattingen te voorkomen, moet de manier van vertellen over lussen de betekenis van herhaling van dezelfde handelingen benadrukken en pas daarna — het formaliseren ervan met behulp van de constructie. Daarom moet, voordat we de syntaxis van de lus geven, de taak ‘in één keer’ worden opgelost. De primitieve oplossing voor de taak over de inhoudsopgave ziet er als volgt uit:

Console.WriteLine("Inleiding");
Console.WriteLine("Hoofdstuk 1");
Console.WriteLine("Hoofdstuk 2");
Console.WriteLine("Hoofdstuk 3");
Console.WriteLine("Hoofdstuk 4");
Console.WriteLine("Hoofdstuk 5");
Console.WriteLine("Hoofdstuk 6");
Console.WriteLine("Hoofdstuk 7");
Console.WriteLine("Conclusie");

Hoe kan dit worden verbeterd?
Vervang eentonige handelingen door een lus.
Welke handelingen worden hier achtereenvolgens herhaald zonder wijzigingen?
In dit fragment zijn er geen. De commando's voor het weergeven van het woord ‘Hoofdstuk’ met het nummer zijn echter zeer vergelijkbaar.
Daarom is de volgende stap het zoeken naar verschillen tussen de fragmenten. Dit is alleen duidelijk in deze taak; later zullen niet enkele commando's zich herhalen, maar blokken code van 5 regels of meer. Je zult moeten zoeken, niet alleen in de lijst van commando's, maar in vertakkingen of lussen.
In het voorbeeld ligt het verschil tussen de commando's in het getal na het woord ‘Hoofdstuk’.
Zodra het verschil is gevonden, moet je de patroon van verandering begrijpen. Is het afwijkende fragment een nummer? Verhoogt of vermindert het constant? Hoe verandert de waarde van het nummer tussen twee commando's naast elkaar?
In the example, the number after the word "Hoofdstuk" increases by increments of 1. The difference has been found, and the pattern has been identified. Now the differing fragment can be replaced with a variable.
Such a variable should be declared before the first of the repeated fragments. This variable is usually called i or j or something more descriptive. Its initial value must be equal to the first value output on the screen. In the example, the first value is 1.
What initial value should be taken to display the series of numbers "100, 101, 102, 103, 104, 105"?
In this series, the first number is 100.
After each output command, the value of this variable needs to be incremented by 1. This unit represents the step of change.
What step will there be in the series of numbers "100, 102, 104, 106"?
In this series, the step is 2.
After replacing the differing fragment with a variable, the code will look like this:

Console.WriteLine("Inleiding");
int i;
i = 0;
Console.WriteLine("Hoofdstuk " + i);
i = i + 1;
Console.WriteLine("Hoofdstuk " + i);
i = i + 1;
Console.WriteLine("Hoofdstuk " + i);
i = i + 1;
Console.WriteLine("Hoofdstuk " + i);
i = i + 1;
Console.WriteLine("Hoofdstuk " + i);
i = i + 1;
Console.WriteLine("Hoofdstuk " + i);
i = i + 1;
Console.WriteLine("Hoofdstuk " + i);
i = i + 1;
Console.WriteLine("Conclusie");

After applying the method "express the pattern as a variable," the code results in several groups of identical actions that occur consecutively. Now, the repeated actions can be replaced with a loop.

The sequence for solving the problem where loops need to be used consists of the following stages:

  1. Solve "directly" with a multitude of separate commands
  2. Find the pattern
  3. Express the pattern as a variable
  4. Format as a loop

Next, new terms are introduced so that the student does not find themselves in a situation of "I understand everything, but cannot express it":
— counter — always a variable needed to track the number of steps in the loop. Usually an integer that is compared with a limit.
— counter step — a description of the pattern of the counter's change.
— limit — a number or variable with which the counter is compared, so that the algorithm is finite. The value of the counter changes to approach the limit.
— body of the loop — a set of commands that will be repeated. When it is said that "a command is written inside the loop," it refers specifically to the body.
— loop iteration — a single execution of the body of the loop.
— de voorwaarde van de lus — een logische uitdrukking waarvan afhankelijk is of er nog een iteratie zal worden uitgevoerd. (Hier kan verwarring ontstaan met vertakkingstructuren)
Wees voorbereid op het feit dat studenten in het begin termen verkeerd zullen gebruiken. Dit geldt voor zowel sterke als zwakke studenten. Het opbouwen van een gedeelde taal is een ware kunst. Hier volgt een korte samenvatting: stel de opdracht "markeer het codefragment met " en gebruik deze termen zelf correct in gesprekken.
Na de transformatie met de lus ontstaat het fragment:

Console.WriteLine("Inleiding");
int i = 0;
while (i < 7) {
    Console.WriteLine("Hoofdstuk " + i);
    i = i + 1;
}
Console.WriteLine("Conclusie");

De belangrijkste misvatting

Een populaire misvatting onder studenten is dat ze binnen de lus constructies plaatsen voor handelingen die maar één keer moeten worden uitgevoerd. Bijvoorbeeld zo:

;
int i = 0;
while (i < 7) {
    Console.WriteLine("Inleiding")
    Console.WriteLine("Hoofdstuk " + i);
    i = i + 1;
    Console.WriteLine("Conclusie");
}

Leerlingen stuiten voortdurend op dit probleem, zowel in het begin als bij complexere taken.
De gouden tip in dit geval:

Hoe vaak moet de uitvoeringsopdracht worden herhaald: één keer of veel?

De uitvoeringsopdrachten voor de woorden "Inleiding" en "Conclusie", evenals de declaratie en initialisatie van de variabele i, verschillen van andere herhalende acties. Ze worden slechts één keer uitgevoerd, dus ze moeten buiten de lichaam van de lus worden geschreven.

In de code moeten alle drie de fasen van de oplossing blijven, zodat we er later naar kunnen verwijzen bij moeilijkheden. De eerste twee versies kunnen gewoon worden gecommentarieerd zodat ze niet in de weg zitten.
De aandacht van de student moet worden gevestigd op de volgende feiten:
— In de voorwaarde van de lus wordt meestal de teller vergeleken met de limiet. De teller kan binnen de lus veranderen, maar de limiet niet. Om deze regel te schenden, moeten er goede redenen worden gegeven.
— De opdrachten voor de uitvoer van de woorden "Inleiding" en "Conclusie" bevinden zich buiten de lichaam van de lus. Deze moet eenmaal worden uitgevoerd. "Inleiding" — vóór de herhaling van acties, "Conclusie" — erna.
Tijdens het verankeren van dit onderwerp, het beheersen van de volgende, en het oplossen van moeilijkheden, is het zelfs voor sterke studenten nuttig om de vraag te stellen: "Hoe vaak moet deze actie worden uitgevoerd? Eén of veel?".

Ontwikkeling van aanvullende vaardigheden

Tijdens het bestuderen van loops ontwikkelen studenten ook hun vaardigheden in diagnose en probleemoplossing. Voor de diagnose moet de student het gewenste resultaat voorstellen en dit vergelijken met het feitelijke resultaat. De acties die nodig zijn om dit te corrigeren, hangen af van het verschil tussen deze twee.
Aangezien studenten zich in dit stadium nog onvoldoende een 'geweldig' resultaat kunnen voorstellen, kunnen ze zich baseren op testgegevens. Over het algemeen begrijpt niemand in deze fase wat er fout kan gaan en hoe hiermee om te gaan. Daarom geef ik een beschrijving van typische problemen en enkele oplossingen om op te schrijven in hun schrift. Het kiezen van de meest geschikte oplossing is de taak van de student zelf.
De notities zijn nodig om te vragen: 'is het resultaat dat ik verwachtte bereikt?', 'Wat is de huidige situatie?', 'Heeft de toegepaste oplossing geholpen?'.

  1. Het aantal acties is 1 minder of meer dan verwacht. Oplossingen:
    — verhoog de beginwaarde van de teller met 1.
    — vervang de strikte vergelijkingsoperator (< of >) door een niet-strikte (<= of >=).
    — wijzig de waarde van de beperking met 1.
  2. De acties in de loop worden eindeloos uitgevoerd. Oplossingen:
    — voeg een wijzigingsopdracht voor de teller toe, indien deze ontbreekt.
    — corrigeer de wijzigingsopdracht voor de teller zodat de waarde dichter bij de beperking komt.
    — verwijder de wijzigingsopdracht voor de beperking, als deze in de loop is.
  3. Het aantal acties in de loop is meer dan 1 minder of meer dan verwacht. De actie in de loop is geen enkele keer uitgevoerd. Eerst moet je de feitelijke waarden van de variabelen achterhalen net voor de start van de loop. Oplossingen:
    — wijzig de beginwaarde van de beperking.
    — wijzig de beginwaarde van de teller.

Gewoonlijk is probleem 3 verbonden met het gebruik van de verkeerde variabele of het niet resetten van de teller.

Na deze uitleg kunnen studenten nog steeds verschillende misvattingen hebben over hoe loops werken.
Om de meest voorkomende te ontkrachten, geef ik de volgende taken:

  1. Waarbij de beperking, beginwaarde van de teller of stapgrootte door de gebruiker wordt ingevoerd.
  2. Waarbij de waarde van de teller in een wiskundige uitdrukking moet worden gebruikt. Bij voorkeur met de teller in een worteluitdrukking of in de noemer, zodat het verschil niet-lineair is.
  3. Waar de waarde van de teller niet op het scherm wordt weergegeven tijdens de uitvoering van de lus. Bijvoorbeeld het weergeven van het benodigde aantal gelijke tekstfragmenten of het tekenen van een figuur met schildpadgrafiek.
  4. Waar je eerst bepaalde herhalende acties moet uitvoeren, en daarna andere.
  5. Waar je andere acties moet uitvoeren voor en na de herhalende acties.

Voor elke taak moeten testgegevens en het verwachte resultaat worden opgegeven.

Om te begrijpen hoe snel je kunt bewegen, moet je de voorwaarden van deze taken laten lezen en vragen: "Hoe verschillen ze van het voorbeeld?", "Wat moet er in het voorbeeld worden veranderd om ze op te lossen?". Als de student begrijpend antwoordt, laat hem dan in ieder geval één op de les oplossen, terwijl de anderen thuis zelfstandig worden gemaakt. Als de oplossing succesvol is, kunnen we beginnen met uitleggen over de voorwaarden binnen lussen.
Als er problemen zijn met de zelfoplossing, moeten we alles op de les oefenen. Om te voorkomen dat het oplossen van de taak lijkt op het tekenen van een uil, raad ik aan om de taak eerst niet universeel op te lossen. Dat wil zeggen, zodat de oplossing de eerste test doorstaat en geen lusconstructie gebruikt. En pas daarna aan te passen om universaliteit in de oplossing te bereiken.

Lussen en takken

Mijns inziens is het nuttig om het onderwerp "lussen binnen takken" apart aan te bieden. Zodat het vervolgens duidelijk is wat het verschil is tussen meervoudige voorwaardecontroles en enkele.
De opdrachten voor consolidatie zullen over het weergeven van getallen van A tot B gaan, die door de gebruiker worden ingevoerd:
— altijd in oplopende volgorde.
— in oplopende of aflopende volgorde, afhankelijk van de waarden van A en B.

Je moet pas overstappen naar het onderwerp "takken binnen lussen" nadat de student de technieken heeft beheerd: "patronen vervangen door variabelen" en "herhalende acties vervangen door een lus".
De belangrijkste reden voor het toepassen van takken binnen lussen is anomalieën in het patroon. Het wordt in het midden geschonden afhankelijk van de oorspronkelijke gegevens.
Voor studenten die in staat zijn om door combinaties van eenvoudige technieken naar oplossingen te zoeken, is het voldoende om te zeggen "takken kunnen binnen lussen worden geschreven" en geef hen de taak "voorbeeld" volledig zelf op te lossen.
Taak voor een voorbeeld:

De gebruiker voert een getal X in. Geef de getallen van 0 tot 9 in een kolom weer en zet een ‘+’ teken naast het getal dat gelijk is aan X.

Als 0 is ingevoerd0+
1
2
3
4
5
6
7
8
9

Als er 6 is ingevoerd0
1
2
3
4
5
6+
7
8
9

Als er 9 is ingevoerd0
1
2
3
4
5
6
7
8
9+

Als er 777 is ingevoerd0
1
2
3
4
5
6
7
8
9

Als een korte uitleg niet voldoende is om met een lus te schrijven, dan moet je een universele oplossing voor dezelfde taak zonder lus vinden.
Er komen twee mogelijkheden:
Gewenst

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);
}

Mogelijk

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+");
}

Een soortgelijke taak geef ik van tevoren tijdens het bestuderen van het onderwerp over takken.
Als de student een "mogelijke" optie heeft, moet hij uitleggen dat er meerdere oplossingen voor dezelfde taak kunnen zijn. Echter, ze verschillen in stabiliteit tegenover veranderingen in de vereisten. Stel de vraag: "Hoeveel plekken in de code moeten worden aangepast als er nog een getal bij moet worden gevoegd?" In de "mogelijke" variant moet er nog een tak worden toegevoegd en dit bij 10 andere plekken het nieuwe getal worden geschreven. In de "gewilde" variant hoeft er slechts één tak te worden toegevoegd.
Stel de taak om de "gewilde" variant te reproduceren, vind vervolgens de regulariteit in de code, vervang de variabele en schrijf een lus.
Als je een idee hebt om deze taak zonder lus op een andere manier op te lossen, schrijf het dan alstublieft in de reacties.

Lussen binnen lussen

In dit onderwerp moet je aandacht besteden aan het feit dat:
— de tellers voor de binnenste en buitenste lus verschillende variabelen moeten zijn.
— de teller voor de binnenste lus moet vaak worden gereset (dat wil zeggen binnen het lichaam van de buitenste lus).
In de tekstuitvoertaken kan je niet eerst één letter op meerdere regels schrijven en dan de tweede. Je moet eerst alle letters van de eerste regel weergeven, daarna alle letters van de tweede regel, enzovoort.

De uitleg van het onderwerp over lussen in lussen begint het beste met het belang van het resetten van de teller.
Taak voor een voorbeeld:

De gebruiker voert twee getallen in: R en T. Geef twee regels van het karakter "#" weer. In de eerste regel moeten R symbolen staan. In de tweede regel T symbolen. Als een van de getallen negatief is, geef dan een foutmelding weer.

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

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

R=-1, T=6De waarde van R moet niet-negatief zijn.

R=6, T=-2De waarde van T moet niet-negatief zijn.

Het is duidelijk dat deze taak ook minstens twee mogelijke oplossingen heeft.
Gewenst

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;
}

Mogelijk №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;
}

Het verschil is dat in de "mogelijke" oplossing voor het weergeven van de tweede regel een tweede variabele wordt gebruikt. Het is nodig om vast te houden aan het gebruik van dezelfde variabele voor beide lussen. Dit argument kan worden onderbouwd met het idee dat een oplossing met één teller voor twee lussen een illustratie van de term "resetten van de teller" zal zijn. Het begrijpen van deze term is nodig bij het oplossen van volgende taken. Als compromis kunnen beide oplossingen van de taak worden behouden.

Een typisch probleem met het gebruik van één teller voor twee lussen manifesteert zich als volgt:
R=5, T=11#####
######

Het aantal symbolen in de tweede regel komt niet overeen met de waarde van T. Als hulp nodig is met dit probleem, moet men "de neus drukken" in het aantekeningenboekje over typische problemen met lussen. Dit is symptoom №3. Het kan worden gediagnosticeerd door de waarde van de teller direct voor de tweede lus weer te geven. Het kan worden verholpen door deze te resetten. Maar dit moet je beter niet meteen vertellen. De student moet proberen ten minste één hypothese te formuleren.

Er is natuurlijk nog een oplossing mogelijk. Maar ik heb het nooit bij studenten gezien. Tijdens de studie van lussen zou het bespreken ervan de aandacht kunnen afleiden. We kunnen later terugkomen op deze oplossing bij het bestuderen van functies voor tekstbewerking.
Mogelijk №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));

De volgende verplichte taak:

Geef de cijfers van 0 tot 9 weer. Elk cijfer moet op een aparte regel staan. Het aantal cijfers per regel (W) wordt via de toetsenbord ingevoerd.

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

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

Als de student de techniek met het vervangen van variabelen beheerst, zal hij dit vrij snel kunnen doen. Een mogelijk probleem zal opnieuw zijn om de variabele te resetten. Als je niet in staat bent om om te zetten, heb je je waarschijnlijk gehaast en moet je eenvoudigere taken oplossen.

Bedankt voor je aandacht. Geef een duim omhoog en abonneer je op het kanaal.

P.S. Als je typfouten of fouten in de tekst hebt gevonden, laat het me dan weten. Dit kan door een deel van de tekst te markeren en op Mac "⌘ + Enter" te drukken, of op klassieke toetsenborden "Ctrl / Enter", of via persoonlijke berichten. Als deze opties niet beschikbaar zijn, schrijf dan over de fouten in de reacties. Bedankt!

Alleen geregistreerde gebruikers kunnen deelnemen aan de enquête. Log in, alstublieft.

Peiling voor lezers zonder karma

  • 20,0%Ik geef professioneel les, +12

  • 10,0%Ik geef professioneel les, -11

  • 70,0%Ik geef geen les, +17

  • 0,0%Ik geef geen les, -10

  • 0,0%Anders0

10 gebruikers hebben gestemd. 5 gebruikers hebben zich onthouden.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster