Hvordan lære å overvinne vanskeligheter, og samtidig skrive sykluser

Til tross for at vi vil snakke om et av de grunnleggende emnene, er denne artikkelen skrevet for erfarne fagfolk. Målet er å vise hvilke misoppfatninger nybegynnere har innen programmering. For praktiserende utviklere har disse problemene lenge vært løst, glemt eller ikke lagt merke til i det hele tatt. Artikkelen kan være nyttig hvis du plutselig trenger å hjelpe noen med dette emnet. Artikkelen trekker paralleller med materiale fra ulike bøker om programmering av Schildt, Stroustrup, Okulov.

Emnet om sykluser ble valgt fordi ganske mange mennesker blir ekskludert fra det når de mestrer programmering.

Denne teknikken er designet for svake elever. Som regel setter sterke mennesker seg ikke fast i dette emnet, og det er ikke nødvendig å komme opp med spesielle teknikker for dem. Det sekundære målet med artikkelen er å flytte denne teknikken fra klassen "fungerer for alle elever, men bare én lærer" til klassen "fungerer for alle elever, alle lærere". Jeg påstår ikke absolutt originalitet. Hvis du allerede bruker en lignende metodikk for å undervise i dette emnet, vennligst skriv hvordan versjonen din er forskjellig. Hvis du bestemmer deg for å bruke det, fortell oss hvordan det gikk. Hvis en lignende teknikk er beskrevet i en bok, vennligst skriv navnet.


Jeg jobbet med denne teknikken i 4 år, og studerte individuelt med elever på ulike treningsnivåer. Totalt er det rundt femti elever og to tusen timer med undervisning. Til å begynne med ble elevene alltid sittende fast på dette emnet og dro. Etter hver elev ble metodikk og materiell justert. I løpet av det siste året har ikke elevene lenger vært fast på dette emnet, så jeg bestemte meg for å dele funnene mine.

Hvorfor så mange bokstaver? Sykluser er så elementære!

Som jeg skrev ovenfor, for praktiserende utviklere og for sterke studenter, kan kompleksiteten til konseptet med looper undervurderes. Du kan for eksempel holde et langt foredrag, se nikkende hoder og intelligente øyne. Men når du prøver å løse ethvert problem, begynner stupor og uforklarlige problemer. Etter forelesningen hadde studentene trolig bare en delvis forståelse. Situasjonen forverres av det faktum at studentene selv ikke kan gi uttrykk for hva deres vrangforestilling er.
En dag skjønte jeg at elevene oppfattet eksemplene mine som hieroglyfer. Det vil si som udelelige tekststykker der du må legge til en "magisk" bokstav, og det vil fungere.
Noen ganger la jeg merke til at elevene tror at for å løse et spesifikt problem trenger du noe annet et design som jeg bare ikke har dekket ennå. Selv om løsningen bare krevde en liten modifikasjon av eksemplet.

Så jeg kom på ideen om at fokus ikke skulle være på syntaksen til uttrykk, men på ideen om å refaktorere repeterende kode ved hjelp av loops. Når elevene har mestret denne ideen, kan enhver syntaks forbedres med lite øvelse.

Hvem og hvorfor underviser jeg?

Siden det ikke er opptaksprøver, kan klasser inneholde både sterke og veldig svake elever. Du kan lese mer om elevene mine i artikkelen Portrett av kveldskursstudenter
Jeg forsøkte å sikre at alle som ønsker å lære programmering kan lære det.
Mine timer holdes individuelt og studenten betaler sine egne penger for hver. Det ser ut til at studentene vil optimalisere kostnadene og kreve minimum. Imidlertid går folk til ansikt-til-ansikt klasser med en levende lærer, ikke for kunnskapen i seg selv, men for tilliten til det de har lært, for en følelse av fremgang og for godkjenning fra eksperten (læreren). Hvis elevene ikke føler fremgang i læringen, vil de gå. Generelt kan klassene struktureres slik at elevene føler fremgang i å øke antallet kjente strukturer. Det vil si, først studerer vi mens i detalj, så studerer vi for, så gjør vi mens, og nå har vi et tusen og en natt kurs klart, der sykluser alene studeres i to måneder, og til slutt - en student som skrev et standardbibliotek under diktat. For å løse praktiske problemer trenger du imidlertid ikke bare kunnskap om materialet, men også uavhengighet i dets anvendelse og i å søke etter ny informasjon. Derfor, for ansikt-til-ansikt-kurs, tror jeg det riktige prinsippet er å undervise i minimum og oppmuntre til uavhengige studier av nyanser og relaterte emner. I temaet løkker anser jeg while-konstruksjonen som minimum. Du kan forstå prinsippet fra det. Når du kjenner prinsippet, kan du mestre både for og gjøre-mens selv.

For å oppnå mestring av stoffet av svake elever, er det ikke nok å beskrive syntaksen. Det er nødvendig å gi enklere, men varierte oppgaver og beskrive eksempler mer detaljert. Til syvende og sist begrenses utviklingshastigheten av studentens evne til å transformere uttrykk og søke etter mønstre. For smarte studenter vil de fleste oppgaver være kjedelige. Når du studerer med dem, trenger du ikke å insistere på å løse 100% av problemene. Materialet mitt kan sees på min github. Riktignok er depotet mer som en warlocks grimoire - ingen andre enn meg vil forstå hva som er hvor, og hvis du mislykkes i sjekken, kan du bli gal

Metodikken er praksisorientert

Teorien forklares ved å bruke eksempelet på å løse et problem. I en grunnleggende programmeringstime hvor det undervises i grener og looper, er det rett og slett ikke mulig å holde en nyttig forelesning om ett emne i en hel time. 15-20 minutter er nok til å forklare konseptet. De viktigste vanskelighetene oppstår når du utfører praktiske oppgaver.
Begynnende lærere kan rasle av operatører, grener, løkker og matriser i én forelesning. Men elevene deres vil møte problemet med å assimilere denne informasjonen.
Det er nødvendig ikke bare å fortelle materialet, men også å sørge for at lytterne forstår det.

Det å mestre et emne bestemmes av hvordan studenten takler selvstendig arbeid.
Hvis en elev klarte å løse et problem om et emne uten hjelp fra en lærer, så har emnet blitt mestret. For å sikre selvtesting er hver oppgave beskrevet i en tabell med testscenarier. Oppgavene har en klar rekkefølge. Det anbefales ikke å hoppe over oppgaver. Hvis den nåværende oppgaven er for vanskelig, er det ubrukelig å gå videre til neste. Det er enda mer komplisert. For at eleven skal kunne mestre den aktuelle komplekse oppgaven, blir flere teknikker forklart for ham ved å bruke eksemplet på den første oppgaven. Faktisk kommer hele innholdet i emnet ned til teknikker for å overvinne vanskeligheter. Sykluser er mer en bivirkning.

Den første oppgaven er alltid et eksempel. Den andre avviker litt og utføres "uavhengig" umiddelbart etter den første under tilsyn av en lærer. Alle påfølgende oppgaver er rettet mot å ta hensyn til ulike småting som kan forårsake misoppfatninger.

Forklaringen på eksempelet er en dialog der studenten må ringe tilbake forplantning og kryssvalidering for å være sikker på at han mestrer en del av materialet.

Jeg vil være banal og si at det første eksemplet på temaet er veldig viktig. Hvis du har materialet for omfattende selvstendig arbeid, kan utelatelsene i det første eksemplet rettes. Hvis det ikke er noe annet enn eksemplet, vil studenten mest sannsynlig ikke mestre emnet.

Mens eller for?

En av de kontroversielle spørsmålene er valget av konstruksjon for eksempelet: mens eller for. En gang brukte en praktiserende utviklervenn av meg uten undervisningserfaring en time på å overbevise meg om at for-løkken var den enkleste å forstå. Argumentene kokte ned til "alt i det er klart og lagt på sin plass." Imidlertid er grunnårsaken til vanskeligheter for ekte nybegynnere ideen om selve syklusen, og ikke skrivingen. Hvis en person ikke forstår denne ideen, vil han ha problemer med syntaksen. Så snart ideen er realisert, forsvinner problemene med kodedesign av seg selv.

I mine materialer følger temaet løkker temaet forgrening. Den eksterne likheten til hvis og mens lar oss trekke en direkte analogi: "når betingelsen i overskriften er sann, blir kroppen henrettet." Den eneste særegenheten ved syklusen er at kroppen blir henrettet mange ganger.

Mitt andre argument er at mens krever mindre formatering enn for. Mindre formatering betyr færre dumme feil med manglende kommaer og parenteser. Nybegynnere har ennå ikke utviklet nok oppmerksomhet og nøyaktighet til automatisk å unngå syntaksfeil.
Det tredje argumentet er forklart i mange gode bøker som det første argumentet.

Hvis eleven lett kan transformere uttrykk, så kan du snakke om for i forbifarten. Eleven skal da velge det han liker best. Hvis transformasjoner forårsaker vanskeligheter, er det bedre å ikke distrahere oppmerksomheten din. La eleven først løse alt ved å bruke mens. Når du har mestret emnet looper, kan du skrive om løsningene for å øve på å konvertere mens til for.
Postcondition-løkker er et ganske sjeldent beist. Jeg bruker ikke tid på det i det hele tatt. Hvis en elev har mestret ideene om å identifisere mønstre og transformere uttrykk, kan han finne ut av det uten min hjelp.

Når jeg demonstrerer det første eksemplet for sterke elever, trekker jeg oppmerksomheten til det faktum at i det første eksemplet er det viktig å registrere ikke bare løsningen, men også hele handlingskjeden som førte til resultatet. Late elever kan forsømme skrivingen og kopiere bare den endelige algoritmen. De trenger å bli overbevist om at en dag vil det komme en vanskelig oppgave. For å løse det, må du følge trinnene som i dette eksemplet. Derfor er det viktig å registrere alle stadier. I de følgende problemene vil det være mulig å la bare den endelige versjonen av løsningen være igjen.

Hovedideen med automatisering er at vi overlater en datamaskin til å gjøre rutinearbeid for en person. En av de grunnleggende teknikkene er å skrive looper. Den brukes når flere identiske repeterende handlinger er skrevet i et program på rad.

Eksplisitt er bedre enn implisitt

Det kan virke som en god idé å vise den samme setningen flere ganger i den første løkkeoppgaven. For eksempel:

Hurra, det funker!
Hurra, det funker!
Hurra, det funker!
Hurra, det funker!
Hurra, det funker!
Hurra, det funker!
Hurra, det funker!
Hurra, det funker!

Dette alternativet er dårlig fordi tellerverdien ikke er synlig i utgangen. Dette er et problem for nybegynnere. Ikke undervurder henne. Først var denne oppgaven den første, og oppgaven med å utlede en rekke tall i stigende rekkefølge var den andre. Det var nødvendig å introdusere tilleggsbegreper "syklus N ganger" og "syklus fra A til B", som i hovedsak er det samme. For ikke å lage unødvendige enheter, bestemte jeg meg for å vise bare et eksempel med utdata fra en serie tall. Få mennesker klarer å lære å holde en teller i hodet og modellere oppførselen til et program i hodet uten forberedelse. Noen elever møter først mental modellering om temaet sykluser.
Etter litt øvelse gir jeg oppgaven med å gjenta samme tekst som skal løses selvstendig. Hvis du først gir en synlig teller og deretter en usynlig, vil elevene få færre problemer. Noen ganger er hintet "ikke skriv telleren på skjermen" nok.

Hvordan forklarer andre det?

I de fleste undervisningsmateriell på Internett er syntaksen til syklusen gitt som en del av en "forelesning". For eksempel, på developer.mozilla.org (for øyeblikket), er flere andre konstruksjoner beskrevet sammen med while-løkken. I dette tilfellet er bare designene i seg selv gitt i form av maler. Resultatet av lanseringen deres er beskrevet i ord, men det er ingen illustrasjon. Etter min mening multipliserer en slik presentasjon av emnet nytten av slike materialer med null. Eleven kan skrive om koden og kjøre den selv, men han trenger fortsatt en standard for sammenligning. Hvordan kan du forstå at et eksempel er skrevet om riktig hvis det ikke er noe å sammenligne resultatet med?
Når kun en mal er gitt, uten eksempel, blir det enda vanskeligere for eleven. Hvordan forstå at kodefragmentene er plassert riktig i malen? Du kan prøve å skrive en eller annen måte, og løp deretter. Men hvis det ikke er noen standard for å sammenligne resultatet, vil heller ikke lansering hjelpe.

I C++-kurset om Intuitiv er løkkesyntaksen begravd på tredje side av forelesning 4 om emnet "operatører". Når man forklarer syntaksen til løkker, legges det spesiell vekt på begrepet "operatør". Begrepet presenteres som et sett med fakta som "symbol; dette er en setning", "{} er en sammensatt setning", "brødteksten i loopen må være en setning". Jeg liker ikke denne tilnærmingen fordi den ser ut til å skjule viktige relasjoner bak ett begrep. Å analysere kildekoden til et program i termer på dette nivået er nødvendig av kompilatorutviklere for å implementere språkspesifikasjonen, men ikke av studenter som en første tilnærming. Nykommere innen programmering er sjelden nøye nok til å følge så nøye med på vilkår. Det er en sjelden person som husker og forstår nye ord første gang. Nesten ingen kan bruke et begrep de nettopp har lært riktig. Derfor får elevene mange feil som "Jeg skrev mens(a<7);{, men programmet fungerer ikke."
Etter min mening er det i begynnelsen bedre å gi syntaksen til konstruksjonen umiddelbart med parenteser. Alternativet uten parentes skal bare forklares hvis eleven har et spesifikt spørsmål: "hvorfor er det ingen parentes og det fungerer."

I Okulovs bok "Fundamentals of Programming" fra 2012, begynner en introduksjon til løkker med for-mønsteret, gir deretter anbefalinger for bruken, og går deretter umiddelbart til den eksperimentelle delen av leksjonen. Jeg forstår at boken ble skrevet for den minoriteten av svært dyktige elever som sjelden kommer til timene mine.

I populære bøker er resultatet av kodefragmenter alltid skrevet. For eksempel Shildts "Java 8. The Complete Guide" 2015-utgaven. Først gis en mal, deretter et eksempelprogram og umiddelbart etter det - resultatet av utførelse.

Som et eksempel, tenk på en while-løkke som gjør det motsatte
nedtelling starter fra 10, og nøyaktig 10 linjer med "tiltak" vises:

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

Når det er kjørt, gir dette programmet ti "sykluser" som følger:
такт 10
такт 9
такт 8
такт 7
такт 6
такт 5
такт 4
такт 3
такт 2
такт 1

Tilnærmingen med å beskrive en mal, et eksempelprogram og resultatet av programmet brukes også i boken «Javascript for Kids» og i js-kurset på w3schools.com. Nettsideformatet lar til og med dette eksemplet være interaktivt.

Stroustrups bok fra 2016 Principles and Practice Using C++ gikk enda lenger. Det første trinnet er å forklare hvilket resultat som skal oppnås, og etter det vises teksten til programmet. Dessuten tar de ikke bare et tilfeldig program som eksempel, men gir en ekskursjon inn i historien. Dette er med på å trekke oppmerksomheten til det: «Se, dette er ikke bare en ubrukelig tekst. Du ser noe meningsfullt."

Som et eksempel på iterasjon, betrakt det første programmet som ble utført på en lagret programmaskin (EDSAC). Den ble skrevet av David Wheeler ved Computer Laboratory ved Cambridge University, England 6. mai 1949. Dette programmet beregner og skriver ut en enkel liste over kvadrater.
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

Her inneholder hver linje et tall etterfulgt av et tabulatortegn ('t') og kvadratet på det tallet. C++-versjonen av dette programmet ser slik ut:

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

Interessant nok er ikke syntaksmønsteret beskrevet i denne boken. Stroustrup i instruktørveiledningen (oversettelse) understreker at den respekterer elevenes intelligens. Kanskje regnes evnen til å identifisere et mønster i flere eksempler som en manifestasjon av slik intelligens.

Som jeg forklarer meg selv

Stroustrups tilnærming: å beskrive resultatet, deretter løse problemet, og deretter en uavhengig analyse av studenten - virker mest gjennomtenkt. Derfor bestemte jeg meg for å ta det som grunnlag, men fortelle det ved å bruke et mindre historisk eksempel - oppgaven med å utlede en "innholdsfortegnelse". Den danner et gjenkjennelig anker slik at man så kan si «husk oppgaven om innholdsfortegnelsen» og slik at elevene husker akkurat dette. I mitt eksempel prøvde jeg å forhindre ytterligere to av de vanligste misoppfatningene. Neste vil jeg skrive om dem mer detaljert.

I denne oppgaven blir vi introdusert for teknikker for å løse komplekse problemer. Den første beslutningen må gjøres primitiv og enkel. Vel, da kan du tenke på hvordan du kan forbedre denne løsningen.
Введение
Глава 1
Глава 2
Глава 3
Глава 4
Глава 5
Глава 6
Глава 7
Заключение

I følge mine observasjoner fører «mal-eksempel-resultat»-tilnærmingen i ulike kombinasjoner fortsatt til at elevene oppfatter syklusen som en hieroglyf. Dette viste seg ved at de ikke forsto hvorfor det var en betingelse for å skrive der, hvordan man velger mellom i++ og i— og andre tilsynelatende åpenbare ting. For å unngå disse misoppfatningene, bør tilnærmingen til å snakke om sykluser understreke betydningen av å gjenta identiske handlinger og først deretter formalisere dem ved hjelp av en struktur. Derfor, før du gir loop-syntaksen, må du løse problemet direkte. En primitiv løsning på innholdsfortegnelsesproblemet ser slik ut:

Console.WriteLine("Введение");
Console.WriteLine("Глава 1");
Console.WriteLine("Глава 2");
Console.WriteLine("Глава 3");
Console.WriteLine("Глава 4");
Console.WriteLine("Глава 5");
Console.WriteLine("Глава 6");
Console.WriteLine("Глава 7");
Console.WriteLine("Заключение");

Hvordan kan det forbedres?
Erstatt monotone handlinger med en syklus.
Hvilke handlinger gjentas på rad uten endringer?
Det er ingen i dette fragmentet. Kommandoene for å vise ordet "Kapittel" med et tall er imidlertid veldig like hverandre.
Derfor er neste trinn å finne forskjellen mellom fragmentene. Det er bare i denne oppgaven at alt er åpenbart, da vil ikke enkeltkommandoer bli gjentatt, men kodeblokker på 5 linjer eller mer. Du må søke ikke bare i listen over kommandoer, men i forgrenings- eller loopkonstruksjoner.
I eksemplet er forskjellen mellom kommandoene i tallet etter ordet "Chapter".
Når forskjellen er funnet, må du forstå endringsmønsteret. Det forskjellige fragmentet er tallet? Øker eller minker den hele tiden? Hvordan endres verdien av et tall mellom to lag side om side?
I eksemplet øker tallet etter ordet "Chapter" i trinn på 1. Forskjellen er funnet, mønsteret avsløres. Nå kan du erstatte det forskjellige fragmentet med en variabel.
Du må deklarere en slik variabel før det første av de repeterende fragmentene. En slik variabel kalles vanligvis I eller j eller noe mer detaljert. Startverdien må være lik den første verdien som vises på skjermen. I eksemplet er den første verdien 1.
Hvilken startverdi bør tas for å vise tallserien "100, 101, 102, 103, 104, 105"?
Det første tallet i denne serien er 100.
Etter hver utgangskommando må du øke verdien til denne variabelen med 1. Denne enheten er endringstrinnet.
Hvilket trinn vil være i serien med tall "100, 102, 104, 106"?
Trinn 2 i denne raden.
Etter å ha erstattet det forskjellige fragmentet med en variabel, vil koden se slik ut:

Console.WriteLine("Введение");
int i;
i = 0;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Глава " + i);
i = i + 1;
Console.WriteLine("Заключение");

Etter å ha brukt "uttrykk mønsteret til en variabel"-teknikken i koden, får du flere grupper med identiske handlinger som går på rad. Nå kan gjentatte handlinger erstattes med en syklus.

Sekvensen for å løse et problem der du må bruke løkker består av følgende trinn:

  1. Løs "head-on" med mange separate kommandoer
  2. Finn et mønster
  3. Uttrykk mønsteret til en variabel
  4. Ordne som en syklus

Deretter introduseres nye begreper slik at studenten ikke befinner seg i situasjonen "Jeg forstår alt, men jeg kan ikke si det":
— en teller er alltid en variabel som er nødvendig for å spore antall trinn i en løkke. Vanligvis et heltall som sammenlignes med begrensningen.
— tellersteg — beskrivelse av mønsteret av tellerendringer.
- constraint - et tall eller en variabel som telleren sammenlignes med slik at algoritmen er endelig. Tellerverdien endres for å nærme seg grensen.
— loop body — et sett med kommandoer som vil bli gjentatt. Når de sier "kommandoen er skrevet i en løkke," mener de kroppen.
— loop iteration — engangsutførelse av loop body.
— loop condition — et logisk uttrykk som bestemmer om en annen iterasjon skal utføres. (Det kan være forvirring med forgreningsstrukturer her)
Du må være forberedt på at studentene først vil bruke begreper til andre formål. Dette gjelder både de sterke og de svake. Å etablere et felles språk er en kunst. Nå skal jeg skrive kort: du må sette oppgaven "uthev kodefragmentet med <term>" og bruke disse begrepene selv riktig i samtalen.
Etter transformasjon med en løkke oppnås fragmentet:

Console.WriteLine("Введение");
int i = 0;
while (i < 7) {
    Console.WriteLine("Глава " + i);
    i = i + 1;
}
Console.WriteLine("Заключение");

Den viktigste misforståelsen

En populær misforståelse blant studenter er at de plasserer handlinger i en løkke som bare må gjøres én gang. For eksempel slik:

;
int i = 0;
while (i < 7) {
    Console.WriteLine("Введение")
    Console.WriteLine("Глава " + i);
    i = i + 1;
    Console.WriteLine("Заключение");
}

Elever støter på dette problemet hele tiden, både i begynnelsen og i mer komplekse problemer.
Nøkkeltips i dette tilfellet:

Hvor mange ganger bør du gjenta kommandoen: én eller mange ganger?

Kommandoene for å skrive ut ordene "Introduksjon" og "Konklusjon" og deklarere og initialisere variabelen i er ikke som andre repeterende handlinger. De utføres bare én gang, noe som betyr at de må skrives utenfor løkketeksten.

Alle tre stadier av løsningen bør forbli i koden slik at du kan henvise til dem senere i tilfelle problemer. Det er nok å kommentere de to første alternativene slik at de ikke forstyrrer.
Elevens oppmerksomhet bør rettes mot følgende fakta:
— I en loop-tilstand sammenlignes vanligvis en teller og en grense. Telleren kan endre seg i løkkens kropp, men grensen kan ikke. For å bryte denne regelen må du formulere overbevisende grunner.
— Kommandoer for å vise ordene «Introduksjon» og «Konklusjon» er plassert utenfor selve sløyfen. Vi må utføre dem 1 gang. "Introduksjon" - før du gjentar handlingene, "Konklusjon" - etter.
I prosessen med å konsolidere dette emnet, mestre de neste, samt håndtere vanskeligheter, er det nyttig for selv sterke elever å stille spørsmålet: "Hvor mange ganger må denne handlingen utføres? En eller mange?

Utvikling av tilleggskompetanse

I prosessen med å studere sykluser utvikler studentene også ferdighetene til å diagnostisere og løse problemer. For å utføre diagnostikk må studenten presentere ønsket resultat og sammenligne det med det faktiske resultatet. Korrigerende handlinger avhenger av forskjellen mellom dem.
Siden studenter på dette stadiet fortsatt har liten ide om det "ønskede" resultatet, kan de fokusere på testdata. Som regel er det ingen på dette stadiet som ennå forstår hva som kan gå galt og hvordan de skal håndtere det. Derfor skriver jeg i en notatbok en beskrivelse av typiske problemer og flere måter å løse dem på. Å velge den mest passende er studentens oppgave.
En registrering er nødvendig for å spørre «hendte det som var forventet?», «Hvilke av disse situasjonene skjedde nå?», «Hjelpet den anvendte løsningen?»

  1. Antall handlinger er 1 mindre eller flere enn forventet. Løsninger:
    – øke startverdien til telleren med 1.
    — bytt ut den strenge sammenligningsoperatoren (< eller >) med en ikke-streng (<= eller >=).
    – endre grenseverdien til 1.
  2. Handlinger i en loop utføres uten stopp, på ubestemt tid. Løsninger:
    — legg til en tellendringskommando hvis den mangler.
    — fiks tellendringskommandoen slik at verdien blir nærmere grensen.
    — fjern kommandoen for endring av begrensninger hvis den er i selve løkken.
  3. Antall handlinger i en loop er mer enn 1 mindre eller mer enn forventet. Handlingen i loopen ble ikke utført en gang. Først må du finne ut de faktiske verdiene til variablene rett før loopen starter. Løsninger:
    — endre startverdien til begrensningen
    — endre startverdien til telleren

Oppgave 3 innebærer vanligvis å bruke feil variabel eller ikke tilbakestille telleren til null.

Etter denne forklaringen kan eleven fortsatt ha ulike misoppfatninger om hvordan looper fungerer.
For å fjerne de vanligste, gir jeg deg følgende oppgaver:

  1. Der grensen, innledende tellerverdi eller tellertrinnet angis av brukeren.
  2. Der tellerverdien må brukes i et eller annet aritmetisk uttrykk. Det er lurt å bruke en teller i det radikale uttrykket eller i nevneren slik at forskjellen er ikke-lineær.
  3. Der tellerverdien ikke vises på skjermen mens loopen kjører. For eksempel å vise det nødvendige antallet identiske tekstfragmenter eller tegne en figur med skilpaddegrafikk.
  4. Der du først må utføre noen repeterende handlinger, og deretter andre.
  5. Der du må utføre andre handlinger før og etter gjentakelse

For hver oppgave må du oppgi testdata og forventet resultat.

For å forstå hvor raskt du kan bevege deg, må du lese vilkårene for disse problemene og spørre: "hvordan skiller de seg fra eksemplet?", "Hva må endres i eksemplet for å løse dem?" Hvis eleven svarer meningsfullt, så la ham løse minst én i klassen, og resten hjemme på egen hånd. Hvis løsningen er vellykket, kan vi begynne å forklare forholdene inne i løkkene.
Hvis du har problemer med å løse problemer på egenhånd, må du jobbe gjennom alt i timen. For å unngå å løse problemet minner om å tegne en ugle, anbefaler jeg først å løse problemet på en ikke-universell måte. Altså slik at løsningen består den første testen og ikke bruker løkkekonstruksjonen. Vel, bruk deretter transformasjoner for å oppnå universalitet av løsningen.

Løkker og greiner

Etter min mening er det nyttig å gi emnet "sykluser innenfor grener" separat. Slik at du senere kan se forskjellen mellom å sjekke en tilstand flere ganger og å sjekke den én gang.
Oppgavene for konsolidering vil handle om å skrive ut tall fra A til B, som legges inn av brukeren:
- alltid i stigende rekkefølge.
- stigende eller synkende avhengig av verdiene til A og B.

Emnet "forgrening innenfor løkker" bør flyttes videre først etter at studenten har mestret teknikkene: "erstatte et mønster med en variabel" og "erstatte repeterende handlinger med en syklus."
Hovedårsaken til å bruke grener inne i løkker er anomalier i mønsteret. I midten bryter den avhengig av de første dataene.
For de studentene som er i stand til å lete etter en løsning ved å kombinere enkle teknikker, er det nok å si "forgrening kan skrives i løkker" og gi oppgaven "for eksempel" helt å løse selvstendig.
Eksempel på oppgave:

Brukeren skriver inn tallet X. Vis tallene fra 0 til 9 i en kolonne og sett et '+'-tegn overfor tallet som er lik X.

Hvis 0 ble lagt inn0+
1
2
3
4
5
6
7
8
9

Hvis 6 ble lagt inn0
1
2
3
4
5
6+
7
8
9

Hvis 9 ble lagt inn0
1
2
3
4
5
6
7
8
9+

Hvis 777 ble lagt inn0
1
2
3
4
5
6
7
8
9

Hvis en kort forklaring ikke er nok til å skrive med en løkke, må du oppnå en universell løsning på det samme problemet uten løkke.
Du får ett av to alternativer:
Ønsket

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

Mulig

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

Jeg gir en lignende oppgave på forhånd, mens jeg studerer emnet forgrening.
Hvis studenten kommer opp med et "mulig" alternativ, må du fortelle dem at det kan være mange løsninger på det samme problemet. Imidlertid er de forskjellige i deres motstand mot endringer i krav. Still spørsmålet: "Hvor mange steder i koden må korrigeres hvis jeg måtte legge til et annet nummer?" I den "mulige" versjonen må du legge til en gren til og legge til et nytt nummer på 10 andre steder. I den "ønskede" er det nok å legge til bare en gren.
Sett oppgaven til å reprodusere det "ønskede" alternativet, finn deretter et mønster i koden, utfør en variabelerstatning og skriv en løkke.
Hvis du har en idé om hvordan du kan løse dette problemet uten en løkke på annen måte, vennligst skriv i kommentarfeltet.

Løkker innenfor løkker

I dette emnet må du være oppmerksom på følgende:
— tellere for indre og ytre løkker må være forskjellige variabler.
— telleren for den indre sløyfen må tilbakestilles mange ganger (det vil si i kroppen til den ytre sløyfen).
— i tekstutdataoppgaver kan du ikke først skrive én bokstav på flere linjer, og deretter den andre. Du må først skrive ut alle bokstavene i den første linjen, deretter alle bokstavene i den andre, og så videre.

Det er best å begynne å forklare temaet løkker i løkker ved å forklare viktigheten av å tilbakestille telleren til null.
Eksempel på oppgave:

Brukeren skriver inn to tall: R og T. Skriv ut to linjer med "#"-tegn. Den første linjen skal inneholde R-tegn. Den andre linjen inneholder T-stykker. Vis en feilmelding hvis et tall er negativt.

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

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

R=-1, T=6R-verdien må være ikke-negativ

R=6, T=-2T-verdien må være ikke-negativ

Selvfølgelig har dette problemet også minst to løsninger.
Ønsket

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

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

Forskjellen er at i den "mulige" løsningen ble en annen variabel brukt for å sende ut den andre linjen. Du bør insistere på å bruke samme variabel for begge løkkene. Denne begrensningen kan begrunnes med at en løsning med én teller i to sykluser vil være en illustrasjon av begrepet «tellertilbakestilling». Det er nødvendig å forstå dette begrepet når du løser følgende problemer. Som et kompromiss kan du lagre begge løsningene på problemet.

Et typisk problem med å bruke en tellervariabel for to løkker ser slik ut:
R=5, T=11#####
######

Antall tegn i den andre linjen samsvarer ikke med verdien av T. Hvis du trenger hjelp med dette problemet, må du se på notatene om typiske problemer med løkker. Dette er symptom #3. Det diagnostiseres hvis du legger til en tellerverdi umiddelbart før den andre syklusen. Rettet ved tilbakestilling. Men det er bedre å ikke fortelle dette med en gang. Eleven skal prøve å formulere minst én hypotese.

Det finnes selvfølgelig en annen løsning. Men jeg har aldri sett det blant studenter. På stadiet av å studere sykluser vil historien om det distrahere oppmerksomheten. Du kan komme tilbake til det senere når du lærer om strengfunksjoner.
Mulig #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));

Neste obligatoriske oppgave:

Vis tallene fra 0 til 9. Hvert tall skal stå på hver sin linje. Antall sifre i en linje (W) legges inn fra tastaturet.

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

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

Hvis en student har mestret teknikken for å erstatte en variabel, vil han takle det ganske raskt. Et mulig problem vil igjen være å tilbakestille variabelen. Hvis du ikke kan håndtere transformasjonen, betyr det at du hadde det travelt og trenger å løse enklere problemer.

Takk for din oppmerksomhet. Lik og abonner på kanalen.

PS Hvis du finner skrivefeil eller feil i teksten, vennligst gi meg beskjed. Dette kan gjøres ved å velge en del av teksten og trykke "⌘ + Enter" på Mac, og "Ctrl / Enter" på klassiske tastaturer, eller gjennom private meldinger. Hvis disse alternativene ikke er tilgjengelige, skriv om feil i kommentarfeltet. Takk skal du ha!

Kun registrerte brukere kan delta i undersøkelsen. Logg inn, vær så snill.

Avstemning for lesere uten karma

  • 20,0%Jeg underviser profesjonelt, +12

  • 10,0%Jeg underviser profesjonelt, -11

  • 70,0%Jeg underviser ikke, +17

  • 0,0%Jeg underviser ikke, -10

  • 0,0%Annet0

10 brukere stemte. 5 brukere avsto.

Kilde: www.habr.com

Legg til en kommentar