Como ensinar a superar as dificultades, e ao mesmo tempo escribir ciclos

A pesar de que falaremos dun dos temas básicos, este artigo está escrito para profesionais con experiencia. O obxectivo é mostrar que conceptos erróneos teñen os principiantes na programación. Para os desenvolvedores en exercicio, estes problemas foron resoltos durante moito tempo, esquecéronse ou non se decataron de nada. O artigo pode ser útil se de súpeto precisas axudar a alguén con este tema. O artigo fai paralelos con material de varios libros sobre programación de Schildt, Stroustrup, Okulov.

Escolleuse o tema dos ciclos porque se exclúe a bastante xente cando domina a programación.

Esta técnica está deseñada para estudantes débiles. Como regra xeral, as persoas fortes non se quedan atrapadas neste tema e non hai necesidade de elaborar técnicas especiais para eles. O obxectivo secundario do artigo é pasar esta técnica da clase "funciona para todos os alumnos, pero só un profesor" á clase "funciona para todos os estudantes, todos os profesores". Non reclamo orixinalidade absoluta. Se xa estás usando unha metodoloxía semellante para ensinar este tema, escribe en que se diferencia a túa versión. Se decides usalo, cóntanos como foi. Se se describe unha técnica similar nun libro, escriba o nome.


Esta técnica traballei durante 4 anos, estudando individualmente con alumnos de distintos niveis formativos. En total son uns cincuenta alumnos e dúas mil horas de clases. Ao principio, os estudantes sempre quedaron atrapados neste tema e marcharon. Despois de cada alumno, axustáronse a metodoloxía e os materiais. Durante o último ano, os estudantes xa non estiveron atrapados neste tema, polo que decidín compartir os meus descubrimentos.

Por que tantas letras? Os ciclos son tan elementais!

Como escribín anteriormente, para os desenvolvedores en exercicio e para os estudantes fortes, a complexidade do concepto de bucles pódese subestimar. Por exemplo, podes dar unha conferencia longa, ver cabezas asentindo e ollos intelixentes. Pero ao tratar de resolver calquera problema comezan o estupor e os problemas inexplicables. Despois da charla, os estudantes probablemente tiñan só unha comprensión parcial. A situación vese agravada polo feito de que os propios estudantes non poden expresar cal é exactamente a súa ilusión.
Un día decateime de que os alumnos percibían os meus exemplos como xeroglíficos. É dicir, como pezas de texto indivisibles nas que hai que engadir algunha letra "máxica" e funcionará.
Ás veces notei que os estudantes pensan que para resolver un problema concreto é necesario algo máis un deseño que aínda non cubrín. Aínda que a solución requiriu só unha lixeira modificación do exemplo.

Entón ocorréuseme que o foco non debería estar na sintaxe das expresións, senón na idea de refactorizar código repetitivo usando bucles. Unha vez que os estudantes dominan esta idea, calquera sintaxe pódese mellorar con pouca práctica.

A quen e por que ensino?

Dado que non hai probas de acceso, as clases poden incluír tanto estudantes fortes como moi débiles. Podes ler máis sobre os meus alumnos no artigo Retrato dos estudantes do curso nocturno
Esforcínme para asegurarme de que todos os que queiran aprender a programación poidan aprendelo.
As miñas clases realízanse individualmente e o alumno paga o seu propio diñeiro por cada unha. Parece que os estudantes optimizarán os custos e demandarán o mínimo. Non obstante, a xente acode a clases presenciais cun profesor vivo non polo coñecemento en si, senón pola confianza do aprendido, por unha sensación de progreso e pola aprobación do experto (profesor). Se o alumnado non sente progreso na súa aprendizaxe, marchará. En xeral, as clases pódense estruturar para que o alumnado sinta un progreso no aumento do número de estruturas coñecidas. É dicir, primeiro estudamos ao detalle, despois estudamos, despois facemos e agora temos preparado un curso de mil e unha noite, no que só se estudan os ciclos durante dous meses, e ao final, un alumno que escribiu unha biblioteca estándar baixo ditado. Non obstante, para resolver problemas prácticos, precisa non só coñecemento do material, senón tamén independencia na súa aplicación e na procura de nova información. Polo tanto, para os cursos presenciais, creo que o principio correcto é ensinar o mínimo e fomentar o estudo independente de matices e temas relacionados. No tema dos bucles, considero que a construción while é o mínimo. Podes entender o principio a partir del. Coñecendo o principio, podes dominar tanto para ti como para facelo.

Para lograr o dominio do material por parte do alumnado débil, non é suficiente describir a sintaxe. É necesario dar tarefas máis sinxelas pero variadas e describir exemplos con máis detalle. En definitiva, a velocidade de desenvolvemento está limitada pola capacidade do alumno para transformar expresións e buscar patróns. Para os estudantes intelixentes, a maioría das tarefas serán aburridas. Cando estudas con eles, non tes que insistir en resolver o 100% dos problemas. O meu material pódese ver en meu github. É certo que o repositorio é máis parecido ao grimorio dun bruxo: ninguén máis que eu entenderá onde está e, se fallas na comprobación, podes volverte tolo.

A metodoloxía está orientada á práctica

A teoría explícase co exemplo de resolución dun problema. Nunha clase de fundamentos de programación onde se ensinan ramas e bucles, simplemente non é posible dar unha conferencia útil sobre un tema durante unha hora enteira. 15-20 minutos son suficientes para explicar o concepto. As principais dificultades xorden á hora de realizar tarefas prácticas.
Os profesores principiantes poden destruír operadores, ramas, bucles e matrices nunha soa conferencia. Pero os seus alumnos enfrontaranse ao problema de asimilar esta información.
É necesario non só contar o material, senón tamén asegurarse de que os oíntes o entenden.

O feito de dominar un tema está determinado pola forma en que o alumno afronta o traballo independente.
Se un alumno conseguiu resolver un problema sobre un tema sen a axuda dun profesor, entón o tema foi dominado. Para garantir a autoproba, cada tarefa descríbese nunha táboa con escenarios de proba. As tarefas teñen unha orde clara. Non se recomenda omitir tarefas. Se a tarefa actual é demasiado difícil, pasar á seguinte é inútil. É aínda máis complicado. Para que o alumno domine a tarefa complexa actual, explícanselle varias técnicas utilizando o exemplo do primeiro problema. En realidade, todo o contido do tema redúcese a técnicas para superar as dificultades. Os ciclos son máis un efecto secundario.

A primeira tarefa é sempre un exemplo. O segundo difire lixeiramente e realízase "de forma independente" inmediatamente despois do primeiro baixo a supervisión dun profesor. Todas as tarefas posteriores están dirixidas a prestar atención a varias pequenas cousas que poden causar equívocos.

A explicación do exemplo é un diálogo no que o alumno debe chamar de volta á propagación e validación cruzada para asegurarse de que domina unha parte do material.

Serei banal e direi que o primeiro exemplo sobre o tema é moi importante. Se tes o material para un traballo independente extenso, pódense corrixir as omisións do primeiro exemplo. Se non hai nada máis que o exemplo, entón o alumno probablemente non dominará o tema.

Mentres ou para?

Unha das cuestións controvertidas é a elección da construción para o exemplo: mentres ou para. Unha vez, un amigo desenvolvedor en prácticas sen experiencia docente pasou unha hora convencéndome de que o bucle for era o máis fácil de entender. Os argumentos reducíronse en que "todo está claro e está no seu lugar". Non obstante, a causa raíz das dificultades para os principiantes reais é a idea do ciclo en si, e non a súa escrita. Se unha persoa non entende esta idea, terá dificultades coa sintaxe. Tan pronto como se realiza a idea, os problemas do deseño do código desaparecen por si sós.

Nos meus materiais, o tema dos bucles segue o tema da ramificación. A semellanza externa de if e while permítenos facer unha analoxía directa: "cando a condición da cabeceira é verdadeira, entón execútase o corpo". A única peculiaridade do ciclo é que o corpo é executado moitas veces.

O meu segundo argumento é que mentres require menos formato que para. Menos formato significa menos erros estúpidos con comas e parénteses que faltan. Os principiantes aínda non desenvolveron a atención e a meticulosidade suficientes para evitar automaticamente erros de sintaxe.
O terceiro argumento explícase en moitos bos libros como primeiro argumento.

Se o alumno pode facilmente transformar expresións, entón podes falar de paso. Despois o alumno elixirá o que máis lle gusta. Se as transformacións causan dificultades, entón é mellor non distraer a atención. Deixa que o alumno primeiro resolva todo usando while. Unha vez que dominas o tema dos bucles, podes reescribir as solucións para practicar a conversión while to for.
Os bucles poscondición son unha besta bastante rara. Non lle paso tempo en absoluto. Se un alumno domina as ideas de identificación de patróns e de transformación de expresións, pode descubrilo sen a miña axuda.

Ao demostrar o primeiro exemplo a estudantes fortes, chamo a atención sobre o feito de que no primeiro exemplo é importante rexistrar non só a solución, senón tamén toda a cadea de accións que levaron ao resultado. Os estudantes preguiceiros poden descoidar a escrita e copiar só o algoritmo final. Deben estar convencidos de que algún día se lles presentará unha tarefa difícil. Para solucionalo, terás que seguir os pasos como neste exemplo. Por iso é importante rexistrar todas as etapas. Nos seguintes problemas será posible deixar só a versión final da solución.

A idea principal da automatización é que encomendamos a un ordenador para que faga o traballo rutineiro dunha persoa. Unha das técnicas básicas é escribir bucles. Utilízase cando se escriben varias accións repetidas idénticas nun programa seguidas.

É mellor explícito que implícito

Pode parecer unha boa idea mostrar a mesma frase varias veces na primeira tarefa de bucle. Por exemplo:

Vaia, funciona!
Vaia, funciona!
Vaia, funciona!
Vaia, funciona!
Vaia, funciona!
Vaia, funciona!
Vaia, funciona!
Vaia, funciona!

Esta opción é mala porque o valor do contador non está visible na saída. Este é un problema para os principiantes. Non a subestimes. Nun primeiro momento, esta tarefa foi a primeira, e a tarefa de derivar unha serie de números en orde ascendente foi a segunda. Foi necesario introducir termos adicionais "ciclo N veces" e "ciclo de A a B", que son esencialmente o mesmo. Para non crear entidades innecesarias, decidín mostrar só un exemplo coa saída dunha serie de números. Poucas persoas conseguen aprender a soster un contador na cabeza e modelar o comportamento dun programa na súa cabeza sen preparación. Algúns estudantes atopan por primeira vez o modelado mental sobre o tema dos ciclos.
Despois dun pouco de práctica, dou a tarefa de repetir o mesmo texto para resolver de forma independente. Se dás primeiro un contador visible e despois outro invisible, os alumnos terán menos problemas. Ás veces a suxestión "non escribas o contador na pantalla" é suficiente.

Como o explican outros?

Na maioría dos materiais educativos de Internet, a sintaxe do ciclo dáse como parte dunha "conferencia". Por exemplo, en developer.mozilla.org (actualmente), descríbense varias outras construcións xunto co bucle while. Neste caso, só se dan os propios deseños en forma de modelos. O resultado do seu lanzamento descríbese con palabras, pero non hai ningunha ilustración. Na miña opinión, tal presentación do tema multiplica por cero a utilidade destes materiais. O alumno pode reescribir o código e executalo el mesmo, pero aínda necesita un estándar para a comparación. Como podes entender que un exemplo foi reescrito correctamente se non hai nada con que comparar o resultado?
Cando só se dá un modelo, sen exemplo, faise aínda máis difícil para o alumno. Como entender que os fragmentos de código están colocados correctamente no modelo? Podes tentar escribir dalgún xeito, e despois corre. Pero se non hai un estándar para comparar o resultado, o lanzamento tampouco axudará.

No curso de C++ sobre Intuitivo, a sintaxe do bucle está soterrada na terceira páxina da Lección 4 sobre o tema "operadores". Ao explicar a sintaxe dos bucles, ponse especial énfase no termo "operador". O termo preséntase como un conxunto de feitos como “símbolo; esta é unha instrución", "{} é unha instrución composta", "o corpo do bucle debe ser unha instrución". Non me gusta este enfoque porque parece ocultar relacións importantes detrás dun termo. Os desenvolvedores do compilador necesitan analizar o código fonte dun programa en termos deste nivel para implementar a especificación da linguaxe, pero non os estudantes como primeira aproximación. Os recén chegados á programación raramente son o suficientemente meticulosos como para prestar tanta atención aos termos. É unha persoa rara que lembra e entende palabras novas a primeira vez. Case ninguén pode aplicar correctamente un termo que acaba de aprender. Polo tanto, os estudantes reciben moitos erros como "Escribín mentres(a<7);{, pero o programa non funciona".
Na miña opinión, ao principio é mellor dar inmediatamente entre parénteses a sintaxe da construción. A opción sen paréntese só debe explicarse se o alumno ten unha pregunta específica: "por que non hai parénteses e funciona?"

No libro de Okulov de 2012 "Fundamentos da programación", unha introdución aos bucles comeza co patrón for, logo dá recomendacións para o seu uso e, a continuación, pasa inmediatamente á sección experimental da lección. Entendo que o libro foi escrito para esa minoría de estudantes moi capaces que raramente veñen ás miñas clases.

Nos libros populares, o resultado dos fragmentos de código sempre está escrito. Por exemplo, a edición 8 de "Java 2015. The Complete Guide" de Shildt. En primeiro lugar, dáse un modelo, despois un programa de exemplo e inmediatamente despois - o resultado da execución.

Como exemplo, considere un bucle while que fai o contrario
conta atrás a partir de 10, e móstranse exactamente 10 liñas de "medidas":

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

Unha vez executado, este programa produce dez "ciclos" do seguinte xeito:
такт 10
такт 9
такт 8
такт 7
такт 6
такт 5
такт 4
такт 3
такт 2
такт 1

O enfoque de describir un modelo, un programa de exemplo e o resultado do programa tamén se usa no libro "Javascript for Kids" e no curso js en w3schools.com. O formato da páxina web permite incluso que este exemplo sexa interactivo.

O libro de 2016 de Stroustrup Principles and Practice Using C++ foi aínda máis alá. O primeiro paso é explicar que resultado se debe obter, e despois móstrase o texto do programa. Ademais, non toman como exemplo un programa aleatorio, senón que dan unha excursión á historia. Isto axuda a chamar a atención sobre el: “Mira, isto non é só un texto inútil. Ves algo significativo".

Como exemplo de iteración, considere o primeiro programa executado nunha máquina de programas almacenados (EDSAC). Foi escrito por David Wheeler no Computer Laboratory da Universidade de Cambridge, Inglaterra o 6 de maio de 1949. Este programa calcula e imprime unha lista sinxela de cadrados.
0 0
1 1
2 4
3 9
4 16
...
98 9604
99 9801

Aquí, cada liña contén un número seguido dun carácter de tabulación ('t') e o cadrado dese número. A versión C++ deste programa ten o seguinte aspecto:

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

Curiosamente, o patrón de sintaxe non se describe neste libro. Stroustrup no manual do instrutor (tradución) destaca que respecta a intelixencia dos seus alumnos. Quizais a capacidade de identificar un patrón en varios exemplos se considere unha manifestación de tal intelixencia.

Segundo me explico

O enfoque de Stroustrup: describir o resultado, despois resolver o problema e, a continuación, unha análise independente por parte do alumno, parece o máis reflexivo. Polo tanto, decidín tomalo como base, pero contalo usando un exemplo menos histórico: a tarefa de derivar un "índice". Forma unha áncora recoñecible para que logo poida dicir "lembrar a tarefa sobre o índice" e para que o alumnado lembre exactamente isto. No meu exemplo, tentei evitar outros dous dos equívocos máis comúns. A continuación escribirei sobre eles con máis detalle.

Nesta tarefa preséntannos técnicas para resolver problemas complexos. A decisión inicial ten que ser primitiva e sinxela. Ben, entón podes pensar en como mellorar esta solución.
Введение
Глава 1
Глава 2
Глава 3
Глава 4
Глава 5
Глава 6
Глава 7
Заключение

Segundo as miñas observacións, o enfoque "modelo-exemplo-resultado" en varias combinacións aínda leva a que os estudantes perciban o ciclo como un xeroglífico. Isto manifestouse no feito de que non entendían por que había unha condición para escribir alí, como elixir entre i++ e i— e outras cousas aparentemente obvias. Para evitar estes conceptos erróneos, o enfoque para falar de ciclos debería enfatizar o significado de repetir accións idénticas e só despois formalizarlas mediante unha estrutura. Polo tanto, antes de dar a sintaxe do bucle, cómpre resolver o problema directamente. Unha solución primitiva para o problema da táboa de contidos é así:

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

Como se pode mellorar?
Substitúe as accións monótonas por un ciclo.
Que accións se repiten seguidas sen cambios?
Non hai ningún neste fragmento. Non obstante, os comandos para mostrar a palabra "Capítulo" cun número son moi similares entre si.
Polo tanto, a seguinte etapa é atopar a diferenza entre os fragmentos. É só nesta tarefa onde todo é obvio, entón non se repetirán comandos únicos, senón bloques de código de 5 liñas ou máis. Terás que buscar non só na lista de comandos, senón tamén en construcións de ramificación ou bucle.
No exemplo, a diferenza entre os comandos está no número despois da palabra "Capítulo".
Unha vez atopada a diferenza, cómpre comprender o patrón de cambio. O fragmento diferente é o número? Está en constante aumento ou diminución? Como cambia o valor dun número entre dous equipos xuntos?
No exemplo, o número despois da palabra "Capítulo" aumenta en incrementos de 1. Atópase a diferenza, revélase o patrón. Agora podes substituír o fragmento diferente por unha variable.
Debe declarar tal variable antes do primeiro dos fragmentos que se repiten. Tal variable chámase normalmente I ou j ou algo máis detallado. O seu valor inicial debe ser igual ao primeiro valor que aparece na pantalla. No exemplo, o primeiro valor é 1.
Que valor inicial se debe tomar para mostrar a serie de números "100, 101, 102, 103, 104, 105"?
O primeiro número desta serie é 100.
Despois de cada comando de saída, cómpre aumentar o valor desta variable en 1. Esta unidade é o paso de cambio.
Que paso será na serie de números "100, 102, 104, 106"?
Paso 2 nesta fila.
Despois de substituír o fragmento diferente por unha variable, o código terá o seguinte aspecto:

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

Despois de aplicar a técnica "expresar o patrón dunha variable" no código, obtén varios grupos de accións idénticas que van seguidas. Agora as accións repetidas pódense substituír por un ciclo.

A secuencia de resolución dun problema no que cómpre usar bucles consta dos seguintes pasos:

  1. Resolve "de frente" con moitos comandos separados
  2. Busca un patrón
  3. Expresa o patrón dunha variable
  4. Deseño como ciclo

A continuación, introdúcense novos termos para que o alumno non se atope na situación de "Eu entendo todo, pero non o podo dicir":
— un contador é sempre unha variable que se necesita para rastrexar o número de pasos nun bucle. Normalmente un número enteiro que se compara coa restrición.
— paso de contador — descrición do patrón de cambios de contador.
- restrición - un número ou variable coa que se compara o contador para que o algoritmo sexa definitivo. O valor do contador cambia para achegarse ao límite.
— corpo do bucle — un conxunto de ordes que se repetirán. Cando din "o comando está escrito dentro dun bucle", refírese ao corpo.
— iteración do bucle — execución única do corpo do bucle.
— condición de bucle — unha expresión lóxica que determina se se executará outra iteración. (Aquí pode haber confusión coas estruturas ramificadas)
Debes estar preparado para o feito de que ao principio os estudantes usarán termos para outros fins. Isto aplícase tanto aos fortes como aos débiles. Establecer unha linguaxe común é unha arte. Agora escribirei brevemente: cómpre configurar a tarefa "destacar o fragmento de código con <term>" e usar estes termos correctamente na conversa.
Despois da transformación cun bucle, obtense o fragmento:

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

O principal equívoco

Unha idea errónea popular entre os estudantes é que colocan accións dentro dun bucle que só hai que facer unha vez. Por exemplo así:

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

Os estudantes atópanse con este problema todo o tempo, tanto ao comezo como en problemas máis complexos.
Consello clave neste caso:

Cantas veces debes repetir o comando: unha ou moitas veces?

Os comandos para imprimir as palabras "Introdución" e "Conclusión" e para declarar e inicializar a variable i non son como outras accións repetitivas. Exécutanse só unha vez, o que significa que deben escribirse fóra do corpo do bucle.

As tres etapas da solución deben permanecer no código para que poidas consultarlas máis tarde en caso de dificultades. Abonda con comentar as dúas primeiras opcións para que non interfiran.
Débese chamar a atención do alumno sobre os seguintes feitos:
— Nunha condición de bucle, adoita compararse un contador e un límite. O contador pode cambiar no corpo do bucle, pero o límite non. Para romper esta regra, cómpre formular razóns convincentes.
— Os comandos para mostrar as palabras "Introdución" e "Conclusión" sitúanse fóra do corpo do bucle. Temos que realizalos 1 vez. "Introdución" - antes de repetir as accións, "Conclusión" - despois.
No proceso de consolidación deste tema, de dominar os seguintes, así como de tratar as dificultades, é útil incluso para os estudantes fortes que se formulen a pregunta: “¿Cantas veces hai que realizar esta acción? Un ou moitos?

Desenvolvemento de habilidades adicionais

No proceso de estudo de ciclos, o alumnado tamén desenvolve a habilidade para diagnosticar e resolver problemas. Para realizar un diagnóstico, o alumno debe presentar o resultado desexado e comparalo co resultado real. As accións correctoras dependen da diferenza entre elas.
Dado que os estudantes nesta etapa aínda teñen pouca idea do resultado "desexado", poden centrarse nos datos da proba. Como regra xeral, ninguén neste momento comprende aínda o que pode saír mal e como tratalo. Por iso, escribo nun caderno unha descrición de problemas típicos e varias formas de resolvelos. Elixir o máis axeitado é tarefa do propio alumno.
Necesítase un rexistro para preguntar: "Ocorreu o que se esperaba?", "Cal destas situacións ocorreu agora?", "Axudou a solución aplicada?"

  1. O número de accións é 1 menos ou máis do esperado. Solucións:
    - Aumente o valor inicial do contador en 1.
    — substituír o operador de comparación estrita (< ou >) por outro non estrito (<= ou >=).
    - Cambiar o valor límite a 1.
  2. As accións nun bucle realízanse sen parar, de forma indefinida. Solucións:
    — engade un comando de cambio de contador se falta.
    — corrixir o comando de cambio de contador para que o seu valor se aproxime ao límite.
    — elimina o comando de cambio de restricións se está no corpo do bucle.
  3. O número de accións nun bucle é máis de 1 menos ou máis do esperado. A acción no bucle non se executou nin unha vez. Primeiro cómpre descubrir os valores reais das variables xusto antes de que comece o ciclo. Solucións:
    — cambiar o valor inicial da restrición
    — cambiar o valor inicial do contador

O problema 3 normalmente implica usar a variable incorrecta ou non reiniciar o contador a cero.

Despois desta explicación, o alumno aínda pode ter varios conceptos erróneos sobre como funcionan os bucles.
Para desfacer os máis habituais, fágoche as seguintes tarefas:

  1. No que o usuario introduce o límite, o valor inicial do contador ou o paso do contador.
  2. No que o valor do contador debe usarse nalgunha expresión aritmética. É recomendable empregar un contador na expresión radical ou no denominador para que a diferenza sexa non lineal.
  3. No que o valor do contador non se mostra na pantalla mentres se está a executar o bucle. Por exemplo, mostrando o número necesario de fragmentos de texto idénticos ou debuxando unha figura con gráficos de tartaruga.
  4. No que hai que realizar primeiro unhas accións repetitivas, e despois outras.
  5. No que cómpre realizar outras accións antes e despois de repetir

Para cada tarefa cómpre proporcionar datos de proba e o resultado esperado.

Para comprender a rapidez con que podes moverte, cómpre ler os termos destes problemas e preguntar: "en que se diferencian do exemplo?", "Que hai que cambiar no exemplo para resolvelos?" Se o alumno responde con sentido, entón déixalle resolver polo menos un na clase, e o resto na casa pola súa conta. Se a solución ten éxito, podemos comezar a explicar as condicións dentro dos bucles.
Se tes problemas para resolver problemas por ti mesmo, debes traballar todo na clase. Para evitar que a resolución do problema recorde a debuxar unha curuxa, recomendo primeiro resolver o problema dun xeito non universal. É dicir, para que a solución pase a primeira proba e non utilice a construción do bucle. Ben, entón aplica transformacións para acadar a universalidade da solución.

Lazos e ramas

Na miña opinión, é útil dar o tema "ciclos dentro das ramas" por separado. Para que despois poidas ver a diferenza entre comprobar unha condición varias veces e verificala unha vez.
As tarefas de consolidación consistirán na saída de números de A a B, que son introducidos polo usuario:
- sempre en orde ascendente.
- ascendente ou descendente dependendo dos valores de A e B.

O tema da "ramificación dentro de bucles" debe moverse só despois de que o alumno domine as técnicas: "substituír un patrón por unha variable" e "substituír accións repetitivas por un ciclo".
A razón principal para usar ramas dentro dos bucles son as anomalías no patrón. No medio rompe dependendo dos datos iniciais.
Para aqueles estudantes que son capaces de buscar unha solución combinando técnicas sinxelas, abonda con dicir "a ramificación pódese escribir dentro de bucles" e dar o problema "por exemplo" completamente para resolver de forma independente.
Tarefa de exemplo:

O usuario introduce o número X. Mostra os números do 0 ao 9 nunha columna e pon un signo "+" fronte ao número que é igual a X.

Se se introduciu 00+
1
2
3
4
5
6
7
8
9

Se se introduciu 60
1
2
3
4
5
6+
7
8
9

Se se introduciu 90
1
2
3
4
5
6
7
8
9+

Se se introduciu 7770
1
2
3
4
5
6
7
8
9

Se unha breve explicación non é suficiente para escribir cun bucle, entón tes que conseguir unha solución universal para o mesmo problema sen bucle.
Terá unha das dúas opcións:
Desexado

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

Posible

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

Dou unha tarefa semellante de antemán, mentres estudo o tema da ramificación.
Se o alumno presenta unha opción "posible", entón cómpre dicirlle que pode haber moitas solucións para o mesmo problema. Non obstante, difiren na súa resistencia aos cambios nos requisitos. Fai a pregunta: "Cantos lugares do código habería que corrixir se tivese que engadir outro número?" Na versión "posible", terás que engadir unha rama máis e engadir un número novo noutros 10 lugares. No "desexado" abonda con engadir só unha rama.
Establece a tarefa para reproducir a opción "desexada", despois busca un patrón no código, realiza unha substitución de variable e escribe un bucle.
Se tes unha idea de como resolver este problema sen bucle doutro xeito, escribe nos comentarios.

Loops dentro de Loops

Neste tema cómpre prestar atención ao seguinte:
— os contadores para os bucles interior e exterior deben ser variables diferentes.
— o contador do bucle interior debe restablecerse moitas veces (é dicir, no corpo do bucle exterior).
— nas tarefas de saída de texto, non pode escribir primeiro unha letra en varias liñas e despois a segunda. Primeiro debes imprimir todas as letras da primeira liña, despois todas as letras da segunda, etc.

É mellor comezar a explicar o tema dos bucles dentro dos bucles explicando a importancia de restablecer o contador a cero.
Tarefa de exemplo:

O usuario introduce dous números: R e T. Imprime dúas liñas de caracteres "#". A primeira liña debe conter caracteres R. A segunda liña contén pezas T. Se algún número é negativo, mostra unha mensaxe de erro.

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

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

R=-1, T=6O valor R debe ser non negativo

R=6, T=-2O valor T debe ser non negativo

Obviamente, este problema tamén ten polo menos dúas solucións.
Desexado

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

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

A diferenza é que na solución "posible" utilizouse unha segunda variable para producir a segunda liña. Debería insistir en usar a mesma variable para ambos os bucles. Esta limitación pódese xustificar polo feito de que unha solución cun contador para dous ciclos será unha ilustración do termo "reinicio do contador". É necesario comprender este termo á hora de resolver os seguintes problemas. Como compromiso, pode gardar ambas as solucións ao problema.

Un problema típico co uso dunha variable contadora para dous bucles aparece así:
R=5, T=11#####
######

O número de caracteres da segunda liña non se corresponde co valor de T. Se necesitas axuda con este problema, debes consultar as notas sobre os problemas típicos dos bucles. Este é o síntoma número 3. Diagnósticose se engade unha saída de valor de contador inmediatamente antes do segundo ciclo. Corrixido mediante o reinicio. Pero é mellor non contar isto de inmediato. O alumno debe intentar formular polo menos unha hipótese.

Hai, por suposto, outra solución. Pero nunca o vin entre os estudantes. Na etapa de estudo de ciclos, a historia sobre el distraerá a atención. Podes volver a el máis tarde cando aprendas sobre as funcións de cadea.
Posible #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));

Próxima tarefa obrigatoria:

Mostra os números do 0 ao 9. Cada número debe estar na súa propia liña. O número de díxitos dunha liña (W) introdúcese desde o teclado.

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

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

Se un alumno dominou a técnica de substitución dunha variable, afrontarase con bastante rapidez. Un posible problema volverá ser ao restablecer a variable. Se non podes xestionar a transformación, significa que tiñas présa e necesitas resolver problemas máis sinxelos.

Grazas pola súa atención. Gústame e subscríbete á canle.

PD Se atopas erros tipográficos ou erros no texto, avisame. Isto pódese facer seleccionando parte do texto e premendo "⌘ + Intro" en Mac e "Ctrl / Intro" nos teclados clásicos ou a través de mensaxes privadas. Se estas opcións non están dispoñibles, escribe sobre os erros nos comentarios. Grazas!

Só os usuarios rexistrados poden participar na enquisa. Rexístrate, por favor.

Enquisa para lectores sen karma

  • 20,0%Ensino profesionalmente, +12

  • 10,0%Ensino profesionalmente, -11

  • 70,0%Non ensino, +17

  • 0,0%Non ensino, -10

  • 0,0%Outros 0

Votaron 10 usuarios. 5 usuarios abstivéronse.

Fonte: www.habr.com

Engadir un comentario