Resumo
Esta aula abre a quinta unidade do curso, dedicada às funções. Explica para que serve a unidade: ensinar a decompor um problema em partes com nome, cada uma com uma interface e um contrato, e a resolver certos problemas reduzindo-os a uma instância menor de si mesmos, por recursão; apresenta suas quatro aulas e o fio que as une; recorda o que a unidade dá por sabido, sobretudo os laços e seus invariantes da unidade 4; formula o problema que a unidade resolve, o de um programa que repete o mesmo cálculo copiado e que, por um descuido na cópia, responde errado sem que o compilador diga nada; antecipa o contrato (a pré-condição e a pós-condição) como a forma com que a unidade especificará cada parte; e mostra aonde conduz, nas unidades seguintes e no curso Programação em C++ II.
Objetivos de aprendizagem
- Descrever a sequência de conteúdos da unidade e explicar o que cada aula traz à seguinte.
- Recordar os algoritmos da unidade 4 (o rastreamento de um laço, seu invariante e sua variante) e revisá-los se for preciso.
- Antecipar, com um exemplo, a ideia de contrato: o que uma parte do programa exige de quem a usa e o que lhe garante em troca.
- Reconhecer o que se espera saber fazer ao terminar a unidade, e distingui-lo do que se aprenderá nas unidades seguintes.
Avaliação de entrada
Antes de percorrer a unidade, convém medir o ponto de partida. Esta avaliação é uma autoavaliação: não se pontua, e seu único propósito é orientar o estudo. As cinco primeiras perguntas verificam o que a unidade dá por sabido: o rastreamento de um laço, seu invariante, a pré-condição de uma especificação, a cópia de um valor na inicialização e a busca, dentro de um programa da unidade 4, de um cálculo com entradas e saídas próprias. As cinco seguintes tocam, na ordem das aulas, as ideias centrais da unidade: a pilha de chamadas, a passagem de um argumento, a separação entre o cálculo e a apresentação, a definição recursiva do fatorial e a execução de uma função que chama a si mesma. Ninguém é obrigado a acertá-las ainda, e em algumas delas “ainda não sei” é uma resposta honesta: cada resposta, certa ou não, explica o ponto e nomeia a aula que o trata. As mesmas habilidades voltam a ser medidas no final, na aula de síntese.
Antes de começar a unidade, meça seu ponto de partida. É uma autoavaliação breve: não recebe nota e seu resultado fica guardado apenas no seu navegador.
Pergunta 1De unidades anterioresO que escreve
int n{305}; int c{1}; while (n >= 10) { n = n / 10; ++c; } std::println("{}", c);?Conta as iterações e esquece queccomeça em 1.Dá uma iteração a mais: com a condiçãon >= 10já é falsa.Confunde o contador com o valor dendepois da primeira iteração.Pergunta 2De unidades anterioresNo laço
int total{0}; int k{1}; while (k <= n) { total += k; ++k; }, com , que relação vale cada vez que se avalia a condição?Vale no meio da iteração, depois de somar e antes de incrementar, mas não quando se avalia a condição.Vale só ao terminar: é a pós-condição, não o invariante.É a condição do laço, e é falsa justamente ao sair; um invariante vale também nesse momento.Vale no começo, com a soma vazia e ; e, se vale antes de uma iteração, vale depois, porque a iteração soma e depois o incrementa. Ao sair, , e o invariante dá a soma de 1 a . A aula Recursão justifica suas funções com o mesmo raciocínio por indução.Revisar: Projetar laços corretos
Pergunta 3De unidades anterioresA especificação da divisão diz: “dados inteiros e , obter e com e ”. Qual é sua pré-condição?
Confunde a pré-condição com a pós-condição: isso é o que o resultado cumpre, não o que se exige dos dados.É uma condição sobre a saída, não sobre a entrada.Com não existe nenhum com : o problema não tem solução, e a pré-condição o exclui.A pré-condição é o que se exige dos dados para que o problema tenha solução; a pós-condição, o que o resultado cumpre. A unidade converte esse par no contrato de cada função: a pré-condição obriga quem chama, e a pós-condição, a função.Revisar: Do problema ao algoritmo
Pergunta 4De unidades anterioresDepois de
int a{3}; int b{a}; b = 7;, quanto valea?Acredita quebeaficam unidas para sempre; a inicialização copia o valor, não a posição.Confunde a cópia com uma variável sem inicializar:arecebeu 3 e nada o mudou.A inicializaçãoint b{a}copia na posição debo valor queatinha; depois, as duas posições são independentes. A aula Parâmetros e escopo mostra que um parâmetro se inicializa do mesmo modo, com uma cópia do argumento, e ensina a outra possibilidade: um segundo nome para a mesma posição.Revisar: Variáveis e memória
Pergunta 5De unidades anterioresO programa da aula 4.4 que escreve os primos menores que 100 tem um laço que percorre os candidatos e, dentro dele, outro que testa seus divisores. Que parte é um cálculo com entradas e saídas próprias, que conviria nomear?
Confunde a entrada e a saída do programa inteiro com as de um cálculo interior.É uma instrução, não um cálculo com sentido próprio: não tem uma entrada e um resultado que alguém queira usar.Confunde um dado com uma tarefa: a variável guarda o resultado do cálculo, mas não é o cálculo.O laço interior não depende de nada além do candidato, e seu resultado é um sim ou um não. Dar-lhe nome permite ler o laço exterior como sua especificação: “para cada candidato, se for primo, escrevê-lo”. A aula Projetar com funções reescreve assim esse programa.Revisar: Algoritmos numéricos
Pergunta 6Um programa começa em
main;mainchama uma funçãog, egchama outra funçãoh. Enquantohse executa, que chamadas estão em curso?Acredita que quem chama desaparece ao chamar; ao contrário, espera para continuar onde parou.Acredita quegterminou ao chamarh; terminará quandohlhe devolver o controle.É uma resposta honesta: a aula 5.1 o explica com uma figura da pilha.Pergunta 7Com a função
int f(int x) { x = x + 1; return x; }, o que escreveint a{3}; int b{f(a)}; std::println("{} {}", a, b);?Acredita que a função modifica o argumento; por padrão, recebe uma cópia.Acredita que a mudança dexnão alcança nem sequer o valor devolvido.Acredita que um parâmetro não pode ser modificado; pode, a menos que seja declaradoconst.O parâmetroxé uma variável defque se inicializa com uma cópia do argumento: a função muda a cópia e devolve 4, eaconserva seu 3. É a passagem por valor, o modo padrão de C++.Revisar: Parâmetros e escopo
Pergunta 8Um programa lê uma data e deve escrever seu dia da semana. Que decomposição separa o cálculo da apresentação?
Mistura duas tarefas: o que foi calculado não pode ser reutilizado nem comparado com um valor esperado.Separa as tarefas, mas as comunica por um efeito oculto: quem lê a chamada não vê de onde vem o dado.É uma resposta honesta: a aula 5.3 ensina a decidir que funções escrever.Assim o cálculo se testa com números, sem olhar a tela, e pode servir a outro programa que escreva o resultado de outra maneira. A aula 5.3 chama esse critério de “uma função, uma tarefa”.Revisar: Projetar com funções
Pergunta 9Qual das definições seguintes define para todo natural ?
Sem caso base, a definição não para nunca: remeteria a , e assim sem fim.Define bem para , mas deixa sem definir , que vale 1.Define a partir de si mesmo: a definição é circular e não reduz o problema.Pergunta 10Com
int f(int n) { if (n == 0) { return 0; } return n + f(n - 1); }, o que escrevestd::println("{}", f(3));?Acredita que se executa uma só chamada, ou confunde o argumento com o resultado.Acredita que oreturn 0do caso base é o resultado de toda a cadeia; é só o da última chamada.O nome da função é conhecido desde seu cabeçalho, e pode ser usado em seu próprio corpo.f(3)esperaf(2), que esperaf(1), que esperaf(0); esta devolve 0, e na volta somam-se 1, 2 e 3. A função calcula , a mesma soma que o laço da segunda pergunta.Revisar: Recursão
Carregando o conteúdo…