Resumo
Esta aula encerra a quarta unidade do curso, dedicada ao controle de fluxo. Reconstrói a cadeia de conceitos que vai da condição aos algoritmos numéricos, passando pela decisão e pela análise por casos, pelo laço e suas três formas, pelos padrões de laço, pelo invariante e pela variante; separa o que disso vale em qualquer linguagem do que é próprio de C++; reúne o comportamento indefinido da unidade, que se concentra nos contadores, nos acumuladores e nas condições que estouram, com um programa que o mostra e sua correção; repete em sua avaliação de saída as habilidades da avaliação de entrada; e termina com seis desafios que combinam a unidade inteira, desde o algoritmo de Euclides estendido até o calendário de um mês.
Objetivos de aprendizagem
- Projetar decisões cujos casos sejam disjuntos e exaustivos, e testá-las com uma entrada por caso e por borda.
- Projetar laços corretos que terminam, escolhendo sua forma e seus padrões a partir da especificação.
- Justificar a correção de um laço com um invariante e sua terminação com uma variante, também nos algoritmos numéricos da unidade.
- Reconhecer o comportamento indefinido da unidade (o contador, o acumulador e a condição que estouram, a divisão que a condição devia impedir) e reescrever o laço sem ele.
- Separar, no que se aprendeu na unidade, o que vale em qualquer linguagem do que é próprio de C++.
O que a unidade alcançou
A unidade se propôs ensinar a governar a ordem de execução com decisões e laços, e a raciocinar sobre sua correção: que cada caso seja atendido, que cada laço faça o que deve e que termine. O propósito foi cumprido apoiando-se somente no que a introdução declarou como sabido: as condições da unidade 3, os tipos da unidade 2 e o rastreamento e a variante da aula 1.1. O programa que calculava o máximo divisor comum com três passos fixos, e que, conforme os dados, respondia errado ou dividia por zero, foi substituído por um laço de três linhas, e agora se pode demonstrar que esse laço é correto para todos os dados não negativos.
Decisões
A aula Decisões ensinou a instrução if, sempre com chaves. Mostrou que em uma cadeia de else if se executa o primeiro ramo cuja condição é verdadeira, de modo que o caso real de cada ramo é sua condição junto com a negação de todas as anteriores; daí que a ordem importe e que um ramo possa ficar inalcançável sem aviso. Estabeleceu o critério de correção de toda decisão: seus casos devem ser disjuntos (são-no pela forma da cadeia) e exaustivos (são-no se ela termina em else), e devem coincidir com os da especificação, o que se testa no interior de cada caso e de cada lado de cada borda. Apresentou o operador condicional, para escolher entre dois valores breves sem uma decisão inteira. Encerrou com enum class e switch, cujo caso esquecido o compilador adverte.
Laços
A aula Laços apresentou while, do e for como três formas de um mesmo mecanismo: o while avalia sua condição antes de cada iteração e pode não fazer nenhuma; o do faz pelo menos uma; o for reúne em seu cabeçalho a inicialização, a condição e o incremento, e sua variável de controle vive somente no laço. Ensinou suas equivalências, a tabela de rastreamento, com avaliações da condição para iterações de um while que termina por sua condição (e avaliações em um do), e a contagem das iterações pelo cabeçalho, que previne o erro de um a mais. Acrescentou break, continue e os laços aninhados, cujo corpo interno se executa uma soma de vezes: com limites fixos, com o triângulo.
Projetar laços corretos
A aula Projetar laços corretos fez do laço um objeto de projeto. Reuniu os padrões (contador, acumulador, máximo e mínimo, sentinela e flag), cada um definido pelo que sua variável significa depois de cada iteração. Definiu o invariante, uma afirmação que vale cada vez que se avalia a condição, com suas três obrigações: inicialização, manutenção e conclusão, que junto com a condição falsa dá a pós-condição; e o reconheceu como uma indução sobre o número de iterações. Ensinou a projetar ao contrário, da pós-condição ao invariante e do invariante ao corpo. Justificou a terminação com a variante, e mostrou três laços em que a aritmética de C++ a invalida: o real que salta o 1.0, o contador sem sinal que dá a volta e o contador com sinal que estoura. Deu, por último, o primeiro contato com o depurador.
Algoritmos numéricos
A aula Algoritmos numéricos aplicou o anterior a quatro algoritmos clássicos, escritos dentro de main e demonstrados. A primalidade por divisões por tentativa, com a proposição de que basta chegar a e com a condição d <= n / d, que não estoura onde d * d <= n estoura. O algoritmo de Euclides, com o invariante e a variante , e seus dois perigos em C++: o resultado negativo e a divisão por zero se a condição é avaliada depois do corpo. A mudança de base por divisões sucessivas e a regra de Horner, que avalia um polinômio com uma multiplicação por coeficiente. E a bissecção, garantida pelo teorema do valor intermediário e governada por um contador inteiro cujo número de iterações se calcula de antemão.
Carregando o conteúdo…