Come insegnare a superare le difficoltà e, allo stesso tempo, a scrivere cicli

Sebbene si tratti di un argomento basilare, questo articolo è scritto per professionisti esperti. L'obiettivo è mostrare quali fraintendimenti hanno i principianti nella programmazione. Per i programmatori praticanti, questi problemi sono già stati risolti da tempo, dimenticati o addirittura mai notati. L'articolo potrebbe rivelarsi utile, nel caso vi capiti di dover aiutare qualcuno su questo argomento. Vengono tracciate parallelismi con materiali di vari libri di programmazione di autori come Schildt, Stroustrup e Okulov.

L'argomento sui cicli è stato scelto perché molti abbandonano proprio durante l'apprendimento della programmazione.

Questa metodologia è progettata per studenti meno forti. Di solito, gli studenti più capaci non si bloccano su questo tema e non è necessario elaborare metodologie particolari per loro. L'obiettivo secondario dell'articolo è quello di rendere questa metodologia applicabile a tutti gli studenti e a tutti gli insegnanti, invece di essere limitata a «funziona per tutti gli studenti, ma solo con un insegnante». Non pretendo di essere assolutamente originale. Se già utilizzate una metodologia simile per insegnare questo argomento, vi prego di comunicarmi in cosa il vostro approccio differisce. Se decidete di applicarla, raccontatemi come è andata. Se una metodologia simile è descritta in un libro, vi prego di indicare il titolo.


Ho sviluppato questa metodologia per 4 anni, lavorando individualmente con studenti di vari livelli. In totale, ho avuto circa cinquanta studenti e duemila ore di lezione. Inizialmente, gli studenti si bloccavano sempre su questo tema e se ne andavano. Dopo ogni studente, la metodologia e i materiali venivano corretti. Nell'ultimo anno, gli studenti non si bloccano più su questo tema, quindi ho deciso di condividere le mie esperienze.

Perché scrivere tante parole? I cicli sono così elementari!

Come ho già detto, per i programmatori praticanti e per gli studenti più forti, la difficoltà del concetto di cicli può essere sottovalutata. Ad esempio, si può tenere una lunga conferenza, vedere teste annuire e occhi brillanti. Ma nel tentativo di risolvere un qualsiasi problema, ci si blocca e si incontrano problemi inspiegabili. Dopo la conferenza, gli studenti probabilmente hanno solo una comprensione parziale. La situazione è aggravata dal fatto che gli studenti non riescono a esprimere qual è esattamente il loro fraintendimento.
Un giorno ho realizzato che gli studenti percepiscono i miei esempi come geroglifici. Cioè come segmenti di testo indecifrabili, nei quali bisogna scrivere una sorta di lettera "magica" affinché tutto funzioni.
A volte notavo che gli studenti pensano che per risolvere un compito specifico sia necessaria un'altra costruzione che non ho ancora menzionato. Anche se per risolvere la questione era sufficiente modificare un po' l'esempio.

Quindi sono arrivato all'idea che l'attenzione principale deve essere rivolta non alla sintassi delle espressioni, ma all'idea di rifattorizzare il codice ripetitivo attraverso i cicli. Non appena gli studenti padroneggiano questa idea, qualsiasi sintassi viene appresa grazie a piccoli esercizi.

A chi e perché insegno

Poiché non ci sono esami di ammissione, in aula possono esserci sia studenti forti che molto deboli. Potete leggere di più sui miei studenti nell'articolo Ritratto degli ascoltatori dei corsi serali
Il mio obiettivo era quello di far apprendere la programmazione a chiunque desiderasse farlo.
Le mie lezioni si svolgono individualmente e lo studente paga di tasca propria per ogni sessione. Sembrerebbe che gli studenti cerchino di ottimizzare le spese e richiedano il minimo indispensabile. Tuttavia, le persone partecipano a lezioni in presenza con un insegnante non solo per le conoscenze, ma per la sicurezza di aver assimilato ciò che è stato insegnato, per la sensazione di progresso e per l'approvazione dell'esperto (insegnante). Se gli studenti non sentono di fare progressi nel loro apprendimento, si allontaneranno. In generale, è possibile strutturare le lezioni in modo tale che gli studenti avvertano un progresso nell'aumento delle costruzioni familiari. Pertanto, iniziamo studiando in dettaglio i cicli while, poi quelli for, poi do while, e così abbiamo un corso che dura mille e una notte, in cui i cicli vengono studiati per due mesi, e alla fine c'è uno studente che ha scritto la libreria standard su dettatura. Tuttavia, per risolvere compiti pratici, non basta conoscere il materiale, ma occorre anche autonomia nel suo utilizzo e nella ricerca di nuove informazioni. Pertanto, per i corsi in presenza, considero giusto il principio di insegnare le basi e incentivare lo studio autonomo di dettagli e argomenti correlati. Riguardo ai cicli, considero la costruzione while come il minimo essenziale. Da essa è possibile comprendere il principio. Conoscendo il principio, è possibile padroneggiare autonomamente anche for e do-while.

Per favorire l'apprendimento del materiale da parte degli studenti più deboli, non basta descrivere la sintassi. È necessario fornire più esercizi semplici ma variati e spiegare in dettaglio gli esempi. Alla fine, la velocità di apprendimento è limitata dalla capacità dello studente di trasformare le espressioni e di cercare schemi. Per gli studenti intelligenti, la maggior parte degli esercizi risulterà noiosa. Quando si lavora con loro, non è necessario insistere sulla risoluzione del 100% dei problemi. Puoi vedere il mio materiale su il mio GitHub. Tuttavia, il repository assomiglia più a un grimorio da stregone: nessuno, tranne me, capirà dove si trova cosa e se si falla un controllo, si potrebbe impazzire.

Il metodo è orientato alla pratica

La teoria viene spiegata attraverso l'esempio di una soluzione. Durante le lezioni di programmazione di base, dove si studiano le diramazioni e i cicli, non è possibile tenere una lezione utile su un solo argomento per un'ora intera. 15-20 minuti sono sufficienti per spiegare un concetto. Le principali difficoltà sorgono durante l'esecuzione di compiti pratici.
I docenti principianti possono elencare operatori, diramazioni, cicli e array in un'unica lezione. Tuttavia, gli studenti si troveranno di fronte a un problema nell'assimilare queste informazioni.
Non è sufficiente raccontare il materiale, bisogna anche assicurarsi che gli ascoltatori lo abbiano compreso.

Il fatto che un argomento sia stato assimilato è determinato da come lo studente gestisce il lavoro autonomo.
Se lo studente riesce a risolvere un problema sull'argomento senza l'aiuto dell'insegnante, significa che l'argomento è stato assimilato. Per garantire un controllo autonomo, per ogni compito viene descritta una tabella con scenari di test. Gli esercizi seguono un ordine ben definito. È sconsigliato saltare i compiti. Se un compito attuale è troppo difficile, è inutile passare al successivo, che sarà ancora più complesso. Per aiutare lo studente a superare un compito difficile, vengono spiegati alcuni approcci utilizzando l'esempio del primo compito. In sostanza, tutto il contenuto dell'argomento è incentrato su strategie per superare le difficoltà. I cicli sono, piuttosto, un effetto collaterale.

Il primo compito è sempre un esempio. Il secondo differisce leggermente e viene eseguito "autonomamente" subito dopo il primo sotto la supervisione dell'insegnante. Tutti i successivi esercizi sono progettati per richiamare l'attenzione su piccoli dettagli che possono causare malintesi.

La spiegazione di un esempio consiste in un dialogo in cui lo studente deve attivare il back propagation e la cross-validation per assicurarsi di aver assimilato il materiale.

Sarà banale, ma affermerò che il primo esempio sull'argomento è molto importante. Quando ci sono materiali per un ampio lavoro autonomo, le mancanze del primo esempio possono essere corrette. Se non c'è nient'altro oltre all'esempio, è probabile che lo studente non riesca ad assimilare l'argomento.

While o for?

Uno dei dibattiti è la scelta della struttura per l'esempio: while o for. Un giorno, un mio amico sviluppatore professionista senza esperienza di insegnamento mi ha convinto per un'ora che il ciclo for è il più semplice da comprendere. Gli argomenti si riducevano al fatto che "è tutto chiaro e ben organizzato". Tuttavia, la vera causa delle difficoltà dei principianti risiede nell'idea stessa di ciclo, e non nella sua scrittura. Se una persona non comprende questa idea, avrà difficoltà con la sintassi. Non appena l'idea è compresa, i problemi di codifica svaniscono da soli.

Nei miei materiali, l'argomento dei cicli segue quello delle diramazioni. La somiglianza esterna tra if e while consente di tracciare un'analogia diretta: "quando la condizione nell'intestazione è vera, viene eseguito il corpo". L'unica particolarità del ciclo è che il corpo viene eseguito molte volte.

Il secondo argomento a mio favore è che while richiede meno processamento rispetto a for. Meno processamento significa meno errori stupidi con virgole e parentesi dimenticate. I principianti non hanno ancora sviluppato una sufficiente attenzione e meticolosità per evitare automaticamente gli errori di sintassi.
Il terzo argomento è che in molti buoni libri while viene spiegato per primo.

Se lo studente riesce a trasformare facilmente le espressioni, allora posso parlare di for passandoci sopra. Lo studente poi sceglierà da solo cosa preferisce. Se invece le trasformazioni creano difficoltà, è meglio non disperdere l'attenzione. Lascia che prima lo studente risolva tutto utilizzando while. Una volta che l'argomento dei cicli è stato assimilato, si possono riscrivere le soluzioni per esercitarsi nella trasformazione da while a for.
I cicli con post-condizione sono piuttosto rari. Non ci perdo tempo affatto. Se lo studente ha compreso le idee di identificazione degli schemi e trasformazione delle espressioni, sarà in grado di affrontarli senza il mio aiuto.

Nella dimostrazione del primo esempio agli studenti avanzati, sottolineo che in questo caso è fondamentale registrare non solo la soluzione, ma anche tutta la sequenza di azioni che hanno portato al risultato. Gli studenti superficiali possono trascurare la scrittura e limitarsi a riportare solo l'algoritmo finale. Devono essere convinti che prima o poi si troveranno di fronte a un compito complesso. Per risolverlo, sarà necessario seguire i passaggi come in questo esempio. Per questo motivo è importante registrare tutte le fasi. Nelle prossime attività, si potrà presentare solo la versione finale della soluzione.

L'idea principale dell'automazione è che affidiamo al computer il compito di eseguire il lavoro di routine per l'uomo. Una delle tecniche fondamentali è la scrittura di cicli. Viene utilizzata quando il programma esegue consecutivamente diverse azioni identiche e ripetitive.

Il chiaro è meglio dell'oscuro

Potrebbe sembrare una buona idea, nel primo esercizio sui cicli, stampare a schermo una frase identica più volte. Ad esempio:

Evviva, funziona!
Evviva, funziona!
Evviva, funziona!
Evviva, funziona!
Evviva, funziona!
Evviva, funziona!
Evviva, funziona!
Evviva, funziona!

Questa soluzione è scadente poiché nell'output non si vede il valore del contatore. Questo rappresenta un problema per i principianti. Non bisogna sottovalutare questa difficoltà. Inizialmente, questo compito era il primo, mentre l'esercizio di stampa di una sequenza di numeri in ordine crescente era il secondo. Era necessario introdurre termini aggiuntivi come "ciclo N volte" e "ciclo da A a B", che in sostanza sono la stessa cosa. Per evitare di creare entità superflue, ho deciso di mostrare solo l'esempio della stampa di una sequenza di numeri. Pochi riescono, senza preparazione, a mantenere in mente il contatore e a modellare il comportamento del programma nella loro mente. Alcuni studenti si trovano per la prima volta a dover modellare "in mente" proprio con il tema dei cicli.
Dopo un po' di pratica, la richiesta di ripetere lo stesso testo la assegno come esercizio autonomo. Se inizialmente mostriamo un contatore visibile e poi invisibile, gli studenti hanno meno difficoltà. A volte basta un suggerimento come "non stampare il contatore a schermo".

Come viene spiegato altrove?

Nella maggior parte dei materiali didattici online, la sintassi del ciclo è presentata all'interno di una "lezione". Ad esempio, su developer.mozilla.org (attualmente) insieme al ciclo while vengono descritti anche altre costrutti. Vengono presentati esclusivamente i costrutti stessi come modelli. I risultati della loro esecuzione sono descritti a parole e manca l'illustrazione. A mio avviso, un approccio del genere riduce a zero l'utilità di tali materiali. Lo studente può riscrivere il codice e farlo funzionare da solo, ma ha comunque bisogno di un modello di riferimento. Come si fa a sapere se l'esempio è stato trascritto correttamente, se non c'è nulla con cui confrontare il risultato?
Quando viene fornito solo un modello, senza esempio, lo studente trova ancora più difficile capire. Come può sapere se i frammenti di codice sono stati posizionati correttamente nel modello? Può provare a scrivere in qualche modo, e poi farlo eseguire. Ma se non c'è un modello di riferimento per il risultato, l'esecuzione non aiuterà.

Nel corso di C++, la sintassi del ciclo è sepolta a pagina tre della lezione 4 sul tema "operatori". Nella spiegazione della sintassi dei cicli si pone particolare enfasi sul termine "operatore". Il termine è presentato come un insieme di fatti del tipo "simbolo; è un operatore", "{} è un operatore composto", "il corpo del ciclo deve essere un operatore". Questo approccio non mi piace perché sembra nascondere importanti interrelazioni dietro un unico termine. L'analisi del codice sorgente a questo livello è necessaria per gli sviluppatori di compilatori per implementare la sintassi del linguaggio, ma non per gli studenti in una prima fase. I principianti nella programmazione raramente hanno la meticolosità necessaria per prestare così tanta attenzione ai termini. È raro che una persona memorizzi e comprenda nuove parole al primo tentativo. Praticamente nessuno è in grado di applicare correttamente un termine appena appreso. Di conseguenza, gli studenti commettono numerosi errori del tipo "ho scritto while(a<7);{, ma il programma non funziona".
A mio parere, all'inizio è meglio fornire la sintassi della costruzione direttamente con le parentesi. La variante senza parentesi va spiegata solo se lo studente pone una domanda specifica "perché qui senza parentesi e funziona".

Nel libro di Okulov "Fondamenti della programmazione" del 2012, l'incontro con i cicli inizia con il modello for, poi si forniscono raccomandazioni sul suo utilizzo e subito dopo c'è una sezione di esperimenti. Ho l'impressione che il libro sia stato scritto per quella ristretta minoranza di studenti molto capaci, che raramente partecipano alle mie lezioni.

Nei libri popolari viene sempre scritto il risultato dei frammenti di codice. Ad esempio, nel libro di Schildt "Java 8. Guida completa" del 2015. Prima viene fornito un modello, poi un esempio di programma e subito dopo il risultato dell'esecuzione.

Prendiamo come esempio un ciclo while in cui viene eseguito un conteggio alla rovescia, partendo da 10, e vengono stampate esattamente 10 righe di "battiti":
Dopo l'avvio, questo programma stampa dieci "battiti" nel modo seguente:

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

L'approccio con la descrizione del modello, il programma di esempio e il risultato di questo programma è utilizzato anche nel libro "Javascript for Kids" e nel corso js su w3schools.com. Il formato della pagina web consente persino di rendere questo esempio interattivo.
passo 10
passo 9
passo 8
passo 7
passo 6
passo 5
passo 4
passo 3
passo 2
passo 1

Nel libro di Stroustrup "Principles and Practice Using C++" del 2016, l'autore va ancora oltre. Inizia spiegando quale risultato si dovrebbe ottenere e solo dopo mostra il testo del programma. Inoltre, il programma non è una semplice casualità, ma fa un excursus nella storia. Questo aiuta a attirare l'attenzione su di esso: "Guarda, questo non è solo un testo inutile. Vedi qualcosa di significativo".

Come esempio di iterazione, consideriamo il primo programma eseguito su una macchina con programma memorizzato (EDSAC). È stato scritto da David Wheeler nel laboratorio di informatica dell'Università di Cambridge (Inghilterra) il 6 maggio 1949. Questo programma calcola e stampa un semplice elenco di quadrati.

Qui, in ogni riga c'è un numero seguito da un carattere di tabulazione ('t') e dal quadrato di quel numero. La versione di questo programma in C++ appare così:
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

Curiosamente, il modello di sintassi in questo libro non è descritto. Stroustrup nel manuale per istruttori () sottolinea di rispettare l'intelligenza dei suoi studenti. Forse la capacità di identificare un modello in diversi esempi è considerata un segno di tale intelligenza.

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

Come spiego io stessotraduzioneL'approccio di Stroustrup: descrivere il risultato, poi risolvere il problema e infine far analizzare autonomamente lo studente — appare il più ragionato. Quindi ho deciso di adottare proprio il suo approccio, ma di parlare di un esempio meno storico: l'attività di stampa di un "indice". Essa forma un'ancora riconoscibile, in modo tale da dire poi "ricorda il problema dell'indice" e affinché gli studenti lo ricordino esattamente. Nel mio esempio, ho cercato di prevenire anche due dei fraintendimenti più comuni. Successivamente ne parlerò in modo più dettagliato.

In questo esercizio ci familiarizziamo con le tecniche di risoluzione di problemi complessi. La soluzione iniziale deve essere primitiva e semplice. Poi si può pensare a come migliorare questa soluzione.

Dalla mia osservazione, l'approccio "modello-esempio-risultato" in diverse combinazioni porta comunque al fatto che gli studenti percepiscono il ciclo come un geroglifico. Questo si manifestava nel fatto che non capivano perché fosse necessario scrivere una condizione, come scegliere tra i++ e i-- e altre cose apparentemente ovvie. Per evitare questi fraintendimenti, l'approccio alla spiegazione dei cicli deve sottolineare il significato della ripetizione di azioni identiche e solo dopo — la loro formalizzazione attraverso la costruzione. Pertanto, prima di fornire la sintassi del ciclo, è necessario risolvere il problema "in modo diretto". La soluzione primitiva del problema dell'indice appare così:

Console.WriteLine("Introduzione"); Console.WriteLine("Capitolo 1"); Console.WriteLine("Capitolo 2"); Console.WriteLine("Capitolo 3"); Console.WriteLine("Capitolo 4"); Console.WriteLine("Capitolo 5"); Console.WriteLine("Capitolo 6"); Console.WriteLine("Capitolo 7"); Console.WriteLine("Conclusione");
Introduzione
Capitolo 1
Capitolo 2
Capitolo 3
Capitolo 4
Capitolo 5
Capitolo 6
Capitolo 7
Conclusione

Come può essere migliorato?

Sostituere le azioni ripetitive con un ciclo.

Quali azioni qui si ripetono consecutivamente senza modifiche?
In questo frammento non ce ne sono. In effetti, i comandi per stampare la parola "Capitolo" con il numero sono molto simili tra loro.
Quindi la fase successiva è cercare le differenze tra i frammenti. Solo in questo problema tutto è ovvio, in seguito si ripeteranno non singoli comandi, ma blocchi di codice di 5 righe o più. Sarà necessario cercare non solo nella lista dei comandi, ma nelle strutture di ramificazione o ciclo.
Nel esempio la differenza tra i comandi è nel numero dopo la parola "Capitolo".
Appena trovata la differenza, è necessario capire la regolarità della modifica. Il frammento differente è un numero? Aumenta costantemente o diminuisce? Come cambia il valore del numero tra due comandi vicini?
Nel esempio, il numero dopo la parola "Capitolo" aumenta di passi di 1. La differenza è stata trovata, la regolarità è stata rilevata. Ora si può sostituire il frammento differente con una variabile.
Dovremmo dichiarare questa variabile prima del primo dei frammenti ripetuti. Questa variabile viene solitamente chiamata i o j o in modo più esplicito. Il suo valore iniziale dovrebbe essere uguale al primo valore che verrà visualizzato sullo schermo. In questo esempio, il primo valore è 1.
Quale valore iniziale dobbiamo prendere per stampare la serie di numeri "100, 101, 102, 103, 104, 105"?
In questa serie, il primo numero è 100.
Dopo ogni comando di stampa, è necessario incrementare il valore di questa variabile di 1. Questa unità rappresenta il passo di cambiamento.
In this row, the first number is 100.
After each output command, you need to increase the value of this variable by 1. This unit is the step change.
Qual è il passo nella sequenza di numeri «100, 102, 104, 106»?
In questa sequenza il passo è 2.
Dopo aver sostituito il frammento variabile, il codice apparirà così:

Console.WriteLine("Introduzione");
int i;
i = 0;
Console.WriteLine("Capitolo " + i);
i = i + 1;
Console.WriteLine("Capitolo " + i);
i = i + 1;
Console.WriteLine("Capitolo " + i);
i = i + 1;
Console.WriteLine("Capitolo " + i);
i = i + 1;
Console.WriteLine("Capitolo " + i);
i = i + 1;
Console.WriteLine("Capitolo " + i);
i = i + 1;
Console.WriteLine("Conclusione");

Dopo aver applicato il metodo "esprimere la regolarità come variabile", il codice risulta in più gruppi di azioni identiche che si susseguono. Ora le azioni ripetitive possono essere sostituite con un ciclo.

La sequenza per risolvere il problema, dove è necessario usare i cicli, consiste nei seguenti passaggi:

  1. Risolvere "a brutto" con una serie di comandi separati
  2. Trovare la regolarità
  3. Esprimere la regolarità come variabile
  4. Formulare come ciclo

In seguito vengono introdotti nuovi termini, affinché lo studente non si trovi nella situazione "capisco tutto, ma non riesco a dire":
— contatore — è sempre una variabile necessaria per tenere traccia del numero di iterazioni del ciclo. Di solito è un numero intero, confrontato con un limite.
— passo del contatore — descrizione della regolarità della modifica del contatore.
— limite — numero o variabile confrontati con il contatore, affinché l'algoritmo sia finito. Il valore del contatore viene modificato per avvicinarsi al limite.
— corpo del ciclo — insieme di comandi che verranno ripetuti. Quando si dice "il comando è scritto all'interno del ciclo", si riferisce specificamente al corpo.
— iterazione del ciclo — esecuzione singola del corpo del ciclo.
— condizione del ciclo — espressione logica dalla quale dipende se verrà eseguita un'altra iterazione. (Qui potrebbe esserci confusione con le strutture di ramificazione)
È necessario essere pronti al fatto che inizialmente gli studenti useranno i termini in modo errato. Questo vale sia per quelli forti che per quelli deboli. Stabilire un linguaggio comune è un'arte. Ora scriverò brevemente: bisogna porre l'obiettivo "evidenzia il frammento di codice con " e utilizzare correttamente questi termini nella conversazione.
Dopo la trasformazione usando il ciclo, il frammento risulta:

Console.WriteLine("Introduzione");
int i = 0;
while (i < 7) {
    Console.WriteLine("Capitolo " + i);
    i = i + 1;
}
Console.WriteLine("Conclusione");

Falsa convinzione principale

Una comune falsa convinzione tra gli studenti è che mettano all'interno della struttura di ciclo azioni che devono essere eseguite solo una volta. Ad esempio, così:

;
int i = 0;
while (i < 7) {
    Console.WriteLine("Introduzione")
    Console.WriteLine("Capitolo " + i);
    i = i + 1;
    Console.WriteLine("Conclusione");
}

Gli studenti si scontrano costantemente con questo problema, sia all'inizio sia in compiti più complessi.
Un suggerimento chiave in questo caso:

Quante volte è necessario ripetere la scrittura del comando: una volta o molte?

I comandi per stampare "Introduzione" e "Conclusione", così come la dichiarazione e l'inizializzazione della variabile i, non assomigliano ad altre azioni ripetitive. Vengono eseguiti solo una volta, quindi devono essere scritti al di fuori del corpo del ciclo.

Nel codice devono rimanere tutte e tre le fasi della soluzione, in modo da poterle richiamare in caso di difficoltà. I primi due modi è sufficiente comentarli affinché non infastidiscano.
L'attenzione dello studente deve essere rivolta ai seguenti fatti:
— Nella condizione del ciclo di solito si confrontano contatore e limite. Il contatore può cambiare all'interno del ciclo, mentre il limite non può. Per violare questa regola, ci devono essere motivi validi.
— I comandi per stampare le parole 'Introduzione' e 'Conclusione' si trovano al di fuori del corpo del ciclo. Devono essere eseguiti 1 volta. 'Introduzione' — prima delle azioni ripetute, 'Conclusione' — dopo.
Durante il consolidamento di questo argomento, l'apprendimento dei successivi e la risoluzione di difficoltà, è utile anche per gli studenti forti porre la domanda: "Questa azione quante volte deve essere eseguita? Una o molte?".

Sviluppo di abilità aggiuntive

Durante lo studio dei cicli, gli studenti affinano anche l'abilità di diagnosi e risoluzione dei problemi. Per condurre una diagnosi, lo studente deve rappresentare il risultato desiderato e confrontarlo con il risultato effettivo. La differenza tra di loro determina le azioni correttive.
Poiché gli studenti in questa fase hanno ancora una scarsa idea del "desiderato" risultato, possono orientarsi sui dati di test. Di solito in questa fase nessuno capisce ancora cosa potrebbe andare storto e come affrontarlo. Pertanto, fornisco per la scrittura nel quaderno una descrizione di problemi tipici e alcuni modi per risolverli. Scegliere il più adeguato è compito dello stesso studente.
È necessario chiedere "è andato come previsto?", "Quale di queste situazioni si è verificata ora?", "La soluzione applicata ha aiutato?".

  1. Il numero di azioni è uno in meno o uno in più di quanto previsto. Modi per risolvere:
    — aumentare il valore iniziale del contatore di 1.
    — sostituire l'operatore di confronto rigoroso (< o >) con un confronto non rigoroso (<= o >=).
    — modificare il valore del limite di 1.
  2. Le azioni nel ciclo vengono eseguite senza fermarsi, all'infinito. Modi per risolvere:
    — aggiungere un comando per modificare il contatore, se manca.
    — correggere il comando di modifica del contatore in modo che il suo valore si avvicini al limite.
    — rimuovere il comando di modifica del limite, se si trova nel corpo del ciclo.
  3. Il numero di azioni nel ciclo è più di 1 in meno o in più di quanto previsto. L'azione nel ciclo non è stata eseguita nemmeno una volta. Prima è necessario determinare i valori effettivi delle variabili immediatamente prima dell'inizio del ciclo. Modi per risolvere:
    — modificare il valore iniziale del limite
    — modificare il valore iniziale del contatore

Di solito, il problema 3 è legato all'uso della variabile sbagliata o al non azzeramento del contatore.

Dopo questa spiegazione, lo studente potrebbe avere ancora varie errate convinzioni riguardo al funzionamento dei cicli.
Per chiarire le più comuni, propongo esercizi:

  1. In cui il limite, il valore iniziale del contatore o il passo del contatore vengono inseriti dall'utente.
  2. In cui il valore del contatore deve essere utilizzato in qualche espressione aritmetica. Preferibilmente con il contatore in un'espressione radice o nel denominatore, in modo che la differenza sia non lineare.
  3. In cui il valore del contatore non viene mostrato sullo schermo durante l'esecuzione del ciclo. Ad esempio, per stampare un numero specifico di frammenti di testo identici o disegnare una figura con grafica turtle.
  4. In cui devono essere eseguite prima alcune azioni ripetitive, e poi altre.
  5. In cui devono essere eseguite altre azioni prima e dopo quelle ripetitive.

Per ogni esercizio devono essere forniti dati di prova e risultati attesi.

Per capire quanto velocemente si può procedere, è necessario dare tempo per leggere le condizioni di questi esercizi e chiedere: "in cosa differiscono dall'esempio?", "Cosa bisogna cambiare nell'esempio per risolverli?". Se lo studente risponde in modo consapevole, allora può risolverne almeno uno in classe, mentre gli altri a casa autonomamente. Se la soluzione ha successo, allora si può iniziare la spiegazione sulle condizioni all'interno dei cicli.
Se ci sono difficoltà con la soluzione autonoma, è necessario lavorare su tutto in classe. Per evitare che la soluzione del problema somigli a un disegno di un gufo, consiglio di risolvere inizialmente il problema in modo non universale. Cioè, in modo che la soluzione superi il primo test e non utilizzi la struttura del ciclo. Poi, si possono applicare trasformazioni per ottenere la universalità della soluzione.

Cicli e ramificazioni

A mio avviso, è utile trattare il tema "cicli all'interno delle ramificazioni" separatamente. Così, poi sarà evidente la differenza tra il controllo multiplo di una condizione e quello singolo.
Gli esercizi di consolidamento riguarderanno la visualizzazione dei numeri da A a B, che vengono inseriti dall'utente:
— sempre in ordine crescente.
— in ordine crescente o decrescente a seconda dei valori di A e B.

Si deve passare al tema "ramificazioni all'interno dei cicli" solo dopo che lo studente ha acquisito competenze nei metodi: "sostituzione della regolarità con una variabile" e "sostituzione di azioni ripetitive con un ciclo".
La principale ragione per applicare ramificazioni all'interno dei cicli sono le anomalie nella regolarità. In mezzo, essa viene interrotta a seconda dei dati di partenza.
Agli studenti capaci di cercare soluzioni mediante la combinazione di semplici tecniche, basta dire: "le ramificazioni possono essere scritte all'interno dei cicli" e dare un esercizio "per esempio" completamente da risolvere autonomamente.
Esercizio per esempio:

L'utente inserisce il numero X. Stampare a colonna i numeri da 0 a 9 e mettere il segno ‘+’ accanto al numero uguale a X.

Se è stato inserito 00+
1
2
3
4
5
6
7
8
9

Se è stato inserito 60
1
2
3
4
5
6+
7
8
9

Se è stato inserito 90
1
2
3
4
5
6
7
8
9+

Se è stato inserito 7770
1
2
3
4
5
6
7
8
9

Se la breve spiegazione non è sufficiente per scrivere con il ciclo, allora è necessario ottenere una soluzione universale dello stesso problema senza ciclo.
Otterrai una delle due opzioni:
Desiderato

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

Possibile

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

Do solito fornisco un compito simile in anticipo, durante lo studio del tema sui ramificazioni.
Se lo studente ha ottenuto una variante «possibile», è importante spiegare che per uno stesso problema possono esserci molte soluzioni. Tuttavia, queste differiscono per la loro robustezza ai cambiamenti dei requisiti. Fai la domanda: «Quanti punti nel codice dovranno essere modificati se sarà necessario aggiungere un altro numero?» Nella variante «possibile» dovrà essere aggiunta un'altra ramificazione e modificato in dieci altri luoghi il nuovo numero. In quella «desiderata» basterà aggiungere solo una ramificazione.
Assegna il compito di riprodurre la variante «desiderata», quindi di identificare nel codice delle regole, eseguire la sostituzione della variabile e scrivere un ciclo.
Se hai idee su come risolvere questo problema senza un ciclo in un altro modo, per favore scrivile nei commenti.

Cicli all'interno di cicli

In questo tema è importante notare che:
— i contatori per il ciclo interno ed esterno devono essere diverse variabili.
— il contatore per il ciclo interno deve essere azzerato molte volte (cioè nel corpo del ciclo esterno).
— nei problemi di output di testo non si può scrivere inizialmente una lettera su più righe e poi la successiva. Prima bisogna stampare tutte le lettere della prima riga, poi tutte le lettere della seconda e così via.

È meglio iniziare la spiegazione del tema sui cicli all'interno dei cicli spiegando l'importanza di azzerare il contatore.
Esercizio per esempio:

L'utente inserisce due numeri: R e T. Stampare due righe di simboli "#". Nella prima riga devono esserci R simboli. Nella seconda riga T simboli. Se uno dei numeri è negativo, stampare un messaggio di errore.

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

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

R=-1, T=6Il valore di R deve essere non negativo

R=6, T=-2Il valore di T deve essere non negativo

È chiaro che anche questo problema ha almeno due possibili soluzioni.
Desiderato

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

Possibile n. 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 differenza è che nella soluzione «possibile» per l'output della seconda riga è stata utilizzata una seconda variabile. È necessario insistere sull'uso della stessa variabile per entrambi i cicli. Si può argomentare questa limitazione dicendo che una soluzione con un solo contatore per due cicli sarà un'illustrazione del termine «azzeramento del contatore». Comprendere questo termine è necessario per risolvere i prossimi problemi. Come compromesso, si possono mantenere entrambe le soluzioni del problema.

Un problema tipico con l'uso di una sola variabile contatore per due cicli si manifesta così:
R=5, T=11#####
######

Il numero di simboli nella seconda riga non corrisponde al valore di T. Se hai bisogno di aiuto con questo problema, è necessario «punzecchiare» nel riassunto sui problemi tipici con i cicli. Questo è il sintomo n. 3. Si diagnostica se si aggiunge l'output del valore del contatore immediatamente prima del secondo ciclo. Si corregge azzerando. Ma è meglio non dirlo subito. Lo studente dovrebbe cercare di formulare almeno un'ipotesi.

Ci sono sicuramente anche altre soluzioni. Ma non le ho mai viste tra gli studenti. Durante lo studio dei cicli, parlarne distrarrebbe l'attenzione. Si può tornare su di esso più tardi, studiando le funzioni legate alle stringhe.
Possibile n. 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));

Il prossimo compito obbligatorio:

Stampa sullo schermo i numeri da 0 a 9. Ogni numero deve essere su una propria riga. Il numero di cifre per riga (W) viene inserito dalla tastiera.

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

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

Se uno studente ha appreso la tecnica per sostituire una variabile, dovrebbe riuscirci piuttosto rapidamente. Il problema potrebbe tornare a essere l'azzeramento della variabile. Se non riesce a effettuare la conversione, significa che hai fretta e che è necessario risolvere problemi più semplici.

Grazie per l'attenzione. Metti mi piace e iscriviti al canale.

P.S. Se hai trovato refusi o errori nel testo, ti prego di farmelo sapere. Puoi farlo evidenziando una parte del testo e premendo su Mac «⌘ + Enter», e sulle tastiere classiche «Ctrl / Enter», oppure tramite messaggi privati. Se queste opzioni non sono disponibili, scrivi gli errori nei commenti. Grazie!

Solo gli utenti registrati possono partecipare al sondaggio. Accedi, per favore.

Sondaggio per lettori senza karma

  • 20,0%Insegno professionalmente, +12

  • 10,0%Insegno professionalmente, -11

  • 70,0%Non insegno, +17

  • 0,0%Non insegno, -10

  • 0,0%Altro0

Hanno votato 10 utenti. Si sono astenuti 5 utenti.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster