Com ensenyar a superar les dificultats, i alhora escriure cicles

Tot i que parlarem d'un dels temes bàsics, aquest article està escrit per a professionals amb experiència. L'objectiu és mostrar quines idees errònies tenen els principiants en la programació. Per als desenvolupadors en pràctica, aquests problemes s'han resolt durant molt de temps, s'han oblidat o no s'han adonat gens. L'article pot ser útil si de sobte necessiteu ajudar algú amb aquest tema. L'article fa paral·lelismes amb material de diversos llibres sobre programació de Schildt, Stroustrup i Okulov.

S'ha escollit el tema dels cicles perquè molta gent n'està exclòs a l'hora de dominar la programació.

Aquesta tècnica està dissenyada per a estudiants febles. Com a regla general, les persones fortes no s'enganxen en aquest tema i no hi ha necessitat d'aconseguir tècniques especials per a ells. L'objectiu secundari de l'article és traslladar aquesta tècnica de la classe "funciona per a tots els alumnes, però només un professor" a la classe "funciona per a tots els alumnes, tots els professors". No reclamo l'originalitat absoluta. Si ja esteu utilitzant una metodologia semblant per ensenyar aquest tema, si us plau, escriu com és diferent la teva versió. Si decidiu utilitzar-lo, digueu-nos com us ha anat. Si es descriu una tècnica similar en un llibre, escriu-ne el nom.


Vaig treballar aquesta tècnica durant 4 anys, estudiant individualment amb alumnes de diferents nivells de formació. En total hi ha una cinquantena d'alumnes i dues mil hores de classe. Al principi, els estudiants sempre es van quedar atrapats en aquest tema i van marxar. Després de cada alumne, es va ajustar la metodologia i els materials. Durant l'últim any, els estudiants ja no s'han quedat atrapats en aquest tema, així que vaig decidir compartir les meves troballes.

Per què tantes cartes? Els cicles són tan elementals!

Com he escrit més amunt, per als desenvolupadors en pràctica i per als estudiants forts, es pot subestimar la complexitat del concepte de bucles. Per exemple, podeu donar una conferència llarga, veure caps que assenteixen i ulls intel·ligents. Però quan s'intenta resoldre qualsevol problema, comencen l'estupor i els problemes inexplicables. Després de la conferència, els estudiants probablement només tenien una comprensió parcial. La situació s'agreuja pel fet que els mateixos estudiants no poden expressar quina és exactament la seva il·lusió.
Un dia em vaig adonar que els alumnes percebien els meus exemples com a jeroglífics. És a dir, com peces de text indivisibles en què cal afegir alguna lletra "màgica" i funcionarà.
De vegades he observat que els alumnes pensen que per resoldre un problema concret cal alguna cosa més un disseny que encara no he cobert. Tot i que la solució només va requerir una lleugera modificació de l'exemple.

Així que em va ocórrer la idea que el focus no hauria de centrar-se en la sintaxi de les expressions, sinó en la idea de refactoritzar codi repetitiu mitjançant bucles. Un cop els estudiants han dominat aquesta idea, qualsevol sintaxi es pot millorar amb poca pràctica.

A qui i per què ensenyo?

Com que no hi ha proves d'accés, les classes poden incloure estudiants forts i molt febles. Podeu llegir més sobre els meus alumnes a l'article Retrat dels estudiants del curs nocturn
M'he esforçat per assegurar-me que tothom qui vulgui aprendre programació ho pugui aprendre.
Les meves classes es fan individualment i l'estudiant paga els seus propis diners per cadascuna. Sembla que els estudiants optimitzaran els costos i exigiran el mínim. No obstant això, la gent va a classes presencials amb un professor en directe no pel coneixement en si, sinó per la confiança del que ha après, per una sensació de progrés i per l'aprovació de l'expert (professor). Si els alumnes no senten progressos en el seu aprenentatge, marxaran. En general, les classes es poden estructurar de manera que els estudiants sentin progressos en l'augment del nombre d'estructures conegudes. És a dir, primer estudiem amb detall, després estudiem per, després fem una estona, i ara tenim preparat un curs de mil i una nit, en el qual només s'estudien els cicles durant dos mesos i, al final, un estudiant que va escriure una biblioteca estàndard sota dictat. Tanmateix, per resoldre problemes pràctics, cal no només el coneixement del material, sinó també la independència en la seva aplicació i en la recerca de nova informació. Per tant, per als cursos presencials, crec que el principi correcte és ensenyar el mínim i fomentar l'estudi independent de matisos i temes relacionats. En el tema dels bucles, considero que la construcció while és el mínim. Podeu entendre el principi a partir d'ell. Coneixent el principi, pots dominar tant per tu mateix com per fer-ho.

Per aconseguir el domini del material per part dels alumnes febles, no n'hi ha prou amb descriure la sintaxi. Cal donar tasques més senzilles però variades i descriure exemples amb més detall. En definitiva, la velocitat de desenvolupament es veu limitada per la capacitat de l'alumne de transformar expressions i cercar patrons. Per als estudiants intel·ligents, la majoria de les tasques seran avorrides. Quan estudies amb ells, no has d'insistir a resoldre el 100% dels problemes. El meu material es pot veure a el meu github. És cert que el dipòsit s'assembla més al grimori d'un bruixot: ningú més que jo entendrà què és on, i si falles la comprovació, pots tornar-te boig.

La metodologia està orientada a la pràctica

La teoria s'explica utilitzant l'exemple de resolució d'un problema. En una classe de fonaments de programació on s'ensenyen branques i bucles, simplement no és possible donar una conferència útil sobre un tema durant una hora sencera. 15-20 minuts són suficients per explicar el concepte. Les principals dificultats sorgeixen a l'hora de realitzar tasques pràctiques.
Els professors principiants poden detonar operadors, branques, bucles i matrius en una conferència. Però els seus alumnes s'enfrontaran al problema d'assimilar aquesta informació.
Cal no només explicar el material, sinó també assegurar-se que els oients l'entenen.

El fet de dominar un tema està determinat per com l'estudiant s'enfronta al treball independent.
Si un alumne va aconseguir resoldre un problema sobre un tema sense l'ajuda d'un professor, llavors el tema s'ha dominat. Per garantir l'autoprova, cada tasca es descriu en una taula amb escenaris de prova. Les tasques tenen un ordre clar. No es recomana saltar tasques. Si la tasca actual és massa difícil, passar a la següent és inútil. Encara és més complicat. Perquè l'estudiant pugui dominar la tasca complexa actual, se li expliquen diverses tècniques utilitzant l'exemple del primer problema. De fet, tot el contingut del tema es redueix a tècniques per superar les dificultats. Els cicles són més un efecte secundari.

La primera tasca és sempre un exemple. El segon difereix lleugerament i es realitza "de manera independent" immediatament després del primer sota la supervisió d'un professor. Totes les tasques posteriors estan destinades a prestar atenció a diverses petites coses que poden provocar idees errònies.

L'explicació de l'exemple és un diàleg en què l'estudiant necessita tornar a cridar la propagació i la validació creuada per assegurar-se que ha dominat una part del material.

Seré banal i diré que el primer exemple sobre el tema és molt important. Si disposeu del material per a un treball independent extens, es poden corregir les omissions del primer exemple. Si no hi ha res més a part de l'exemple, és probable que l'estudiant no domini el tema.

Mentre o per?

Un dels temes polèmics és l'elecció de la construcció per a l'exemple: mentre o per. Una vegada, un amic desenvolupador en pràctica sense experiència docent va passar una hora convèncer-me que el bucle for era el més fàcil d'entendre. Els arguments es reduïen a "tot el que hi ha és clar i està disposat al seu lloc". Tanmateix, l'arrel de les dificultats per als principiants reals és la idea del cicle en si, i no la seva escriptura. Si una persona no entén aquesta idea, tindrà dificultats amb la sintaxi. Tan bon punt es realitza la idea, els problemes del disseny del codi desapareixen per si mateixos.

Als meus materials, el tema dels bucles segueix el tema de la ramificació. La similitud externa de if i while ens permet dibuixar una analogia directa: "quan la condició de la capçalera és certa, llavors el cos s'executa". L'única particularitat del cicle és que el cos s'executa moltes vegades.

El meu segon argument és que mentre requereix menys format que for. Menys format significa menys errors estúpids amb comes i parèntesis que falten. Els principiants encara no han desenvolupat prou atenció i meticulositat per evitar automàticament errors de sintaxi.
El tercer argument s'explica en molts bons llibres com el primer argument.

Si l'estudiant pot transformar fàcilment expressions, llavors podeu parlar-ne de passada. A continuació, l'alumne triarà el que més li agrada. Si les transformacions causen dificultats, és millor no distreure la vostra atenció. Deixeu que l'alumne primer ho resolgui tot utilitzant while. Un cop hàgiu dominat el tema dels bucles, podeu reescriure les solucions per practicar la conversió while to for.
Els bucles posteriors a la condició són una bèstia força rara. No hi passo gens de temps. Si un estudiant ha dominat les idees d'identificar patrons i transformar expressions, pot esbrinar-ho sense la meva ajuda.

Quan mostro el primer exemple a estudiants forts, crido l'atenció sobre el fet que en el primer exemple és important registrar no només la solució, sinó també tota la cadena d'accions que van conduir al resultat. Els estudiants mandrosos poden descuidar l'escriptura i copiar només l'algorisme final. Han d'estar convençuts que un dia els hi sortirà una tasca difícil. Per solucionar-ho, haureu de seguir els passos com en aquest exemple. Per això és important registrar totes les etapes. En els problemes següents serà possible deixar només la versió final de la solució.

La idea principal de l'automatització és que confiem a un ordinador per fer el treball rutinari d'una persona. Una de les tècniques bàsiques és l'escriptura de bucles. S'utilitza quan s'escriuen diverses accions repetitives idèntiques en un programa seguides.

Val més explícit que implícit

Pot semblar una bona idea mostrar la mateixa frase diverses vegades a la primera tasca de bucle. Per exemple:

Hura, funciona!
Hura, funciona!
Hura, funciona!
Hura, funciona!
Hura, funciona!
Hura, funciona!
Hura, funciona!
Hura, funciona!

Aquesta opció és dolenta perquè el valor del comptador no és visible a la sortida. Aquest és un problema per als principiants. No la subestimeu. Al principi, aquesta tasca era la primera, i la tasca de derivar una sèrie de nombres en ordre ascendent era la segona. Calia introduir termes addicionals "cicle N temps" i "cicle d'A a B", que són essencialment el mateix. Per no crear entitats innecessàries, vaig decidir mostrar només un exemple amb la sortida d'una sèrie de números. Poques persones aconsegueixen aprendre a agafar un comptador al cap i modelar el comportament d'un programa al cap sense preparació. Alguns estudiants troben per primera vegada el modelatge mental sobre el tema dels cicles.
Després d'una mica de pràctica, dono la tasca de repetir el mateix text per resoldre de manera independent. Si primer doneu un comptador visible i després un d'invisible, els alumnes tindran menys problemes. De vegades, la pista "no escriviu el comptador a la pantalla" és suficient.

Com ho expliquen els altres?

A la majoria de materials educatius d'Internet, la sintaxi del cicle es dóna com a part d'una "conferència". Per exemple, a developer.mozilla.org (actualment), es descriuen altres construccions juntament amb el bucle while. En aquest cas, només els dissenys es donen en forma de plantilles. El resultat del seu llançament es descriu amb paraules, però no hi ha cap il·lustració. Al meu entendre, aquesta presentació del tema multiplica per zero la utilitat d'aquests materials. L'estudiant pot reescriure el codi i executar-lo ell mateix, però encara necessita un estàndard per a la comparació. Com es pot entendre que un exemple s'hagi reescrit correctament si no hi ha res amb què comparar el resultat?
Quan només es dóna una plantilla, sense exemple, encara es fa més difícil per a l'estudiant. Com entendre que els fragments de codi estan col·locats correctament a la plantilla? Pots provar d'escriure d'alguna manera, i després córrer. Però si no hi ha cap estàndard per comparar el resultat, el llançament tampoc ajudarà.

Al curs de C++ sobre intuïtiu, la sintaxi del bucle està enterrada a la tercera pàgina de la Lliçó 4 sobre el tema "operadors". Quan s'explica la sintaxi dels bucles, es fa especial èmfasi en el terme "operador". El terme es presenta com un conjunt de fets com “símbol; aquesta és una declaració", "{} és una sentència composta", "el cos del bucle ha de ser una sentència". No m'agrada aquest enfocament perquè sembla amagar relacions importants darrere d'un terme. Els desenvolupadors del compilador necessiten analitzar el codi font d'un programa en termes d'aquest nivell per implementar l'especificació del llenguatge, però no els estudiants com a primera aproximació. Els nouvinguts a la programació poques vegades són prou meticulosos com per prestar tanta atenció als termes. És una persona rara que recorda i entén paraules noves la primera vegada. Gairebé ningú pot aplicar correctament un terme que acaba d'aprendre. Per tant, els estudiants reben molts errors com "He escrit mentre(a<7);{, però el programa no funciona".
Al meu entendre, al principi és millor donar la sintaxi de la construcció immediatament entre parèntesis. L'opció sense parèntesis només s'ha d'explicar si l'alumne té una pregunta concreta: "per què no hi ha parèntesis i funciona?"

Al llibre d'Okulov del 2012 "Fundaments of Programming", una introducció als bucles comença amb el patró for, després dóna recomanacions per al seu ús i, a continuació, passa immediatament a la secció experimental de la lliçó. Entenc que el llibre va ser escrit per a aquesta minoria d'estudiants molt capaços que poques vegades vénen a les meves classes.

En els llibres populars, sempre s'escriu el resultat dels fragments de codi. Per exemple, l'edició 8 de "Java 2015. The Complete Guide" de Shildt. Primer, s'ofereix una plantilla, després un exemple de programa i immediatament després, el resultat de l'execució.

Com a exemple, considereu un bucle while que fa el contrari
compte enrere a partir de 10, i es mostren exactament 10 línies de "mesures":

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

Un cop executat, aquest programa genera deu "cicles" de la següent manera:
такт 10
такт 9
такт 8
такт 7
такт 6
такт 5
такт 4
такт 3
такт 2
такт 1

L'enfocament de descriure una plantilla, un programa d'exemple i el resultat del programa també s'utilitza al llibre "Javascript for Kids" i al curs js a w3schools.com. El format de la pàgina web fins i tot permet que aquest exemple sigui interactiu.

El llibre Principles and Practice Using C++ de Stroustrup del 2016 va anar encara més enllà. El primer pas és explicar quin resultat s'ha d'obtenir, i després es mostra el text del programa. A més, prenen com a exemple no només un programa aleatori, sinó que ofereixen una excursió a la història. Això ajuda a cridar l'atenció sobre això: “Mira, això no és només un text inútil. Veus quelcom significatiu".

Com a exemple d'iteració, considereu el primer programa executat en una màquina de programa emmagatzemat (EDSAC). Va ser escrit per David Wheeler al Computer Laboratory de la Universitat de Cambridge, Anglaterra, el 6 de maig de 1949. Aquest programa calcula i imprimeix una llista senzilla de quadrats.
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

Aquí, cada línia conté un número seguit d'un caràcter de tabulació ('t') i el quadrat d'aquest número. La versió C++ d'aquest programa té aquest aspecte:

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

Curiosament, el patró de sintaxi no es descriu en aquest llibre. Stroustrup al manual de l'instructor (traducció) destaca que respecta la intel·ligència dels seus alumnes. Potser la capacitat d'identificar un patró en diversos exemples es considera una manifestació d'aquesta intel·ligència.

Tal com m'explico

L'enfocament de Stroustrup: descriure el resultat, després resoldre el problema i després una anàlisi independent per part de l'estudiant, sembla el més reflexiu. Per tant, vaig decidir prendre-ho com a base, però explicar-ho amb un exemple menys històric: la tasca de derivar una "taula de continguts". Forma un àncora reconeixible perquè després puguis dir “recorda la tasca sobre la taula de continguts” i perquè els alumnes ho recordin exactament. En el meu exemple, vaig intentar evitar dues idees errònies més comunes. A continuació, escriuré sobre ells amb més detall.

En aquesta tasca s'introdueixen les tècniques per resoldre problemes complexos. La decisió inicial ha de ser primitiva i senzilla. Bé, llavors podeu pensar com millorar aquesta solució.
Введение
Глава 1
Глава 2
Глава 3
Глава 4
Глава 5
Глава 6
Глава 7
Заключение

Segons les meves observacions, l'enfocament "plantilla-exemple-resultat" en diverses combinacions encara condueix al fet que els estudiants perceben el cicle com un jeroglífic. Això es va manifestar en el fet que no entenien per què hi havia una condició per escriure allà, com triar entre i++ i i— i altres coses aparentment òbvies. Per evitar aquestes idees errònies, l'enfocament per parlar de cicles hauria de posar èmfasi en el significat de repetir accions idèntiques i només després formalitzar-les mitjançant una estructura. Per tant, abans de donar la sintaxi del bucle, heu de resoldre el problema directament. Una solució primitiva al problema de la taula de continguts és així:

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("Заключение");

Com es pot millorar?
Substitueix les accions monòtones per un cicle.
Quines accions es repeteixen seguides sense canvis?
No n'hi ha cap en aquest fragment. Tanmateix, les ordres per mostrar la paraula "Capítol" amb un número són molt semblants entre si.
Per tant, la següent etapa és trobar la diferència entre els fragments. És només en aquesta tasca on tot és obvi, llavors no es repetiran ordres individuals, sinó blocs de codi de 5 línies o més. Haureu de cercar no només a la llista d'ordres, sinó també en construccions de ramificació o bucle.
A l'exemple, la diferència entre les ordres està en el número després de la paraula "Capítol".
Un cop trobada la diferència, cal entendre el patró de canvi. El fragment diferent és el nombre? Està augmentant o disminuint constantment? Com canvia el valor d'un número entre dos equips l'un al costat de l'altre?
A l'exemple, el nombre després de la paraula "Capítol" augmenta en increments d'1. Es troba la diferència, es revela el patró. Ara podeu substituir el fragment diferent per una variable.
Heu de declarar aquesta variable abans del primer dels fragments que es repeteixen. Aquesta variable sol anomenar-se I o j o alguna cosa més detallada. El seu valor inicial ha de ser igual al primer valor que es mostra a la pantalla. A l'exemple, el primer valor és 1.
Quin valor inicial s'ha de prendre per mostrar la sèrie de números "100, 101, 102, 103, 104, 105"?
El primer nombre d'aquesta sèrie és 100.
Després de cada comanda de sortida, cal augmentar el valor d'aquesta variable en 1. Aquesta unitat és el pas de canvi.
Quin pas hi haurà a la sèrie de números "100, 102, 104, 106"?
Pas 2 en aquesta fila.
Després de substituir el fragment diferent per una variable, el codi tindrà aquest aspecte:

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("Заключение");

Després d'aplicar la tècnica "expressar el patró d'una variable" al codi, obteniu diversos grups d'accions idèntiques que van seguides. Ara les accions repetides es poden substituir per un cicle.

La seqüència de resolució d'un problema on cal utilitzar bucles consta dels passos següents:

  1. Resoldre "de front" amb moltes ordres separades
  2. Busca un patró
  3. Expressa el patró d'una variable
  4. Disseny com a cicle

A continuació, s'introdueixen nous termes perquè l'estudiant no es trobi en la situació de "Ho entenc tot, però no ho puc dir":
— un comptador sempre és una variable que es necessita per fer un seguiment del nombre de passos en un bucle. Normalment un nombre enter que es compara amb la restricció.
— pas del comptador — descripció del patró de canvis del comptador.
- restricció: un nombre o variable amb la qual es compara el comptador perquè l'algorisme sigui definitiu. El valor del comptador canvia per apropar-se al límit.
— cos del bucle — un conjunt d'ordres que es repetiran. Quan diuen "l'ordre està escrit dins d'un bucle", es refereixen al cos.
— iteració del bucle — execució única del cos del bucle.
— condició de bucle — una expressió lògica que determina si s'executarà una altra iteració. (Pot haver-hi confusió amb les estructures de ramificació aquí)
Cal estar preparat per al fet que al principi els estudiants utilitzaran termes per a altres propòsits. Això s'aplica tant als forts com als febles. Establir un llenguatge comú és un art. Ara escriuré breument: cal que configureu la tasca "ressalteu el fragment de codi amb <term>" i feu servir aquests termes correctament a la conversa.
Després de la transformació amb un bucle, s'obté el fragment:

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

La principal concepció errònia

Una idea errònia popular entre els estudiants és que col·loquen accions dins d'un bucle que només s'han de fer una vegada. Per exemple com aquest:

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

Els estudiants es troben amb aquest problema tot el temps, tant al principi com en problemes més complexos.
Consell clau en aquest cas:

Quantes vegades hauríeu de repetir l'ordre: una o moltes vegades?

Les ordres per imprimir les paraules "Introducció" i "Conclusió" i declarar i inicialitzar la variable i no són com altres accions repetitives. S'executen només una vegada, el que significa que s'han d'escriure fora del cos del bucle.

Les tres etapes de la solució haurien de romandre al codi perquè pugueu consultar-les més endavant en cas de dificultats. N'hi ha prou amb comentar les dues primeres opcions perquè no interfereixin.
Cal cridar l'atenció de l'alumne sobre els fets següents:
— En una condició de bucle, normalment es comparen un comptador i un límit. El comptador pot canviar al cos del bucle, però el límit no. Per infringir aquesta regla, cal formular raons convincents.
— Les ordres per mostrar les paraules "Introducció" i "Conclusió" es troben fora del cos del bucle. Hem de realitzar-los 1 cop. "Introducció" - abans de repetir les accions, "Conclusió" - després.
En el procés de consolidació d'aquest tema, el domini dels següents, així com el tractament de les dificultats, és útil que fins i tot els alumnes forts es plantegin la pregunta: “Quantes vegades cal fer aquesta acció? Un o molts?

Desenvolupament d'habilitats addicionals

En el procés d'estudi dels cicles, els alumnes també desenvolupen l'habilitat de diagnosticar i resoldre problemes. Per dur a terme el diagnòstic, l'estudiant ha de presentar el resultat desitjat i comparar-lo amb el resultat real. Les accions correctores depenen de la diferència entre elles.
Com que els estudiants en aquesta etapa encara tenen poca idea del resultat "desitjat", poden centrar-se en les dades de la prova. Com a regla general, ningú en aquesta etapa encara entén què pot sortir malament i com fer-hi front. Per tant, escric en un quadern una descripció de problemes típics i diverses maneres de resoldre'ls. Escollir el més adequat és tasca del propi alumne.
Cal un registre per preguntar "va passar el que s'esperava?", "Quina d'aquestes situacions va passar ara?", "La solució aplicada va ajudar?"

  1. El nombre d'accions és 1 inferior o superior al previst. Solucions:
    — augmentar el valor inicial del comptador en 1.
    — substituïu l'operador de comparació estricte (< o >) per un de no estricte (<= o >=).
    - Canvieu el valor límit a 1.
  2. Les accions en un bucle es realitzen sense parar, de manera indefinida. Solucions:
    — afegiu una ordre de canvi de comptador si falta.
    — Fixeu l'ordre de canvi de comptador perquè el seu valor s'acosti al límit.
    — elimineu l'ordre de canvi de restricció si es troba al cos del bucle.
  3. El nombre d'accions en un bucle és més d'1 inferior o superior a l'esperat. L'acció del bucle no s'ha executat ni una sola vegada. Primer heu d'esbrinar els valors reals de les variables just abans que comenci el bucle. Solucions:
    — canviar el valor inicial de la restricció
    — canviar el valor inicial del comptador

El problema 3 sol implicar utilitzar la variable incorrecta o no posar el comptador a zero.

Després d'aquesta explicació, l'estudiant encara pot tenir diverses idees errònies sobre com funcionen els bucles.
Per dissipar els més habituals, us dono les tasques següents:

  1. En què l'usuari introdueix el límit, el valor inicial del comptador o el pas del comptador.
  2. En què el valor del comptador s'ha d'utilitzar en alguna expressió aritmètica. S'aconsella utilitzar un comptador en l'expressió radical o en el denominador perquè la diferència sigui no lineal.
  3. En què el valor del comptador no es mostra a la pantalla mentre s'executa el bucle. Per exemple, mostrant el nombre necessari de fragments de text idèntics o dibuixant una figura amb gràfics de tortuga.
  4. En què cal realitzar primer unes accions repetitives, i després d'altres.
  5. En què cal realitzar altres accions abans i després de repetir

Per a cada tasca cal proporcionar dades de prova i el resultat esperat.

Per entendre la rapidesa amb què pots moure't, has de llegir les condicions d'aquests problemes i preguntar: "en què es diferencien de l'exemple?", "Què s'ha de canviar a l'exemple per resoldre'ls?" Si l'alumne respon de manera significativa, deixeu-lo resoldre almenys un a classe i la resta a casa sol. Si la solució té èxit, podem començar a explicar les condicions dins dels bucles.
Si teniu problemes per resoldre problemes pel vostre compte, heu de treballar-ho tot a classe. Per evitar que la resolució del problema recordi dibuixar un mussol, recomano primer resoldre el problema d'una manera no universal. És a dir, perquè la solució superi la primera prova i no utilitzi la construcció del bucle. Bé, llavors apliqueu transformacions per aconseguir la universalitat de la solució.

Bucles i branques

Al meu entendre, és útil donar el tema "cicles dins de les branques" per separat. De manera que més endavant pugueu veure la diferència entre comprovar una condició diverses vegades i comprovar-la una vegada.
Les tasques de consolidació seran sobre la sortida de números de A a B, que són introduïts per l'usuari:
- sempre en ordre ascendent.
- ascendent o descendent segons els valors de A i B.

El tema de "ramificació dins dels bucles" només s'ha de passar després que l'estudiant hagi dominat les tècniques: "substituir un patró per una variable" i "substituir accions repetitives per un cicle".
El motiu principal per utilitzar branques dins dels bucles són les anomalies en el patró. Al mig es trenca segons les dades inicials.
Per a aquells estudiants que són capaços de buscar una solució combinant tècniques senzilles, n'hi ha prou amb dir "la ramificació es pot escriure dins de bucles" i donar el problema "per exemple" completament per resoldre de manera independent.
Tasca d'exemple:

L'usuari introdueix el número X. Mostra els nombres del 0 al 9 en una columna i posa un signe "+" davant del nombre que és igual a X.

Si s'ha introduït 00+
1
2
3
4
5
6
7
8
9

Si s'ha introduït 60
1
2
3
4
5
6+
7
8
9

Si s'ha introduït 90
1
2
3
4
5
6
7
8
9+

Si s'ha introduït 7770
1
2
3
4
5
6
7
8
9

Si no n'hi ha prou amb una breu explicació per escriure amb un bucle, haureu d'aconseguir una solució universal al mateix problema sense bucle.
Tindreu una de dues opcions:
Desitjat

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

Possible

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

Dono una tasca similar per endavant, mentre estudiem el tema de la ramificació.
Si l'estudiant presenta una opció "possible", cal dir-li que hi pot haver moltes solucions al mateix problema. Tanmateix, es diferencien en la seva resistència als canvis en els requisits. Fes la pregunta: "Quants llocs del codi caldria corregir si hagués d'afegir un altre número?" A la versió "possible", haureu d'afegir una branca més i afegir un número nou en 10 llocs més. Al "desitjat" n'hi ha prou amb afegir només una branca.
Establiu la tasca per reproduir l'opció "desitjada", després trobeu un patró al codi, realitzeu una substitució de variables i escriviu un bucle.
Si teniu una idea sobre com resoldre aquest problema sense un bucle d'una altra manera, escriviu als comentaris.

Loops dins de Loops

En aquest tema heu de parar atenció al següent:
— Els comptadors dels bucles interior i exterior han de ser variables diferents.
— el comptador del bucle interior s'ha de reiniciar moltes vegades (és a dir, al cos del bucle exterior).
— a les tasques de sortida de text, primer no podeu escriure una lletra en diverses línies i després la segona. Primer heu d'imprimir totes les lletres de la primera línia, després totes les lletres de la segona, i així successivament.

El millor és començar a explicar el tema dels bucles dins dels bucles explicant la importància de reiniciar el comptador a zero.
Tasca d'exemple:

L'usuari introdueix dos números: R i T. Imprimeix dues línies de caràcters "#". La primera línia ha de contenir caràcters R. La segona línia conté peces T. Si algun número és negatiu, mostra un missatge d'error.

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

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

R=-1, T=6El valor R ha de ser no negatiu

R=6, T=-2El valor T no ha de ser negatiu

Evidentment, aquest problema també té almenys dues solucions.
Desitjat

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

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

La diferència és que a la solució "possible", es va utilitzar una segona variable per donar sortida a la segona línia. Hauríeu d'insistir a utilitzar la mateixa variable per als dos bucles. Aquesta limitació es pot justificar pel fet que una solució amb un comptador per a dos cicles serà una il·lustració del terme "reinicialització del comptador". Entendre aquest terme és necessari per resoldre els problemes següents. Com a compromís, podeu desar ambdues solucions al problema.

Un problema típic amb l'ús d'una variable de comptador per a dos bucles apareix així:
R=5, T=11#####
######

El nombre de caràcters de la segona línia no es correspon amb el valor de T. Si necessiteu ajuda amb aquest problema, heu de consultar les notes sobre problemes típics amb bucles. Aquest és el símptoma número 3. Es diagnostica si afegiu una sortida de valor de comptador immediatament abans del segon cicle. Es corregeix reiniciant. Però és millor no dir-ho de seguida. L'estudiant ha d'intentar formular almenys una hipòtesi.

Hi ha, és clar, una altra solució. Però no ho he vist mai entre els estudiants. En l'etapa d'estudi dels cicles, la història al respecte distraurà l'atenció. Podeu tornar-hi més tard quan apreneu sobre les funcions de cadena.
Possible #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));

Següent tasca necessària:

Mostra els números del 0 al 9. Cada número ha d'estar en la seva pròpia línia. El nombre de dígits d'una línia (W) s'introdueix des del teclat.

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

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

Si un estudiant ha dominat la tècnica de substitució d'una variable, ho farà amb força rapidesa. Un possible problema tornarà a ser en reiniciar la variable. Si no pots gestionar la transformació, vol dir que tenies pressa i necessites resoldre problemes més senzills.

Gràcies per la vostra atenció. Fes m'agrada i subscriu-te al canal.

PS Si trobeu errors ortogràfics o errors al text, si us plau, feu-m'ho saber. Això es pot fer seleccionant part del text i prement "⌘ + Enter" al Mac i "Ctrl / Enter" als teclats clàssics o mitjançant missatges privats. Si aquestes opcions no estan disponibles, escriviu sobre els errors als comentaris. Gràcies!

Només els usuaris registrats poden participar en l'enquesta. Inicia sessiósi us plau.

Enquesta per a lectors sense karma

  • 20,0%Ensenyo professionalment, +12

  • 10,0%Ensenyo professionalment, -11

  • 70,0%No ensenyo, +17

  • 0,0%No ensenyo, -10

  • 0,0%Altres 0

Han votat 10 usuaris. 5 usuaris es van abstenir.

Font: www.habr.com

Afegeix comentari