Resumo
Esta aula abre a primeira unidade do curso, dedicada aos primeiros passos na programação com C++. Explica para que serve a unidade: levar quem nunca programou de um problema enunciado em linguagem corrente até um programa que compila, executa, lê dados e escreve resultados, sabendo o que cada ferramenta fez no caminho; apresenta suas seis aulas e o fio que as une, desde o algoritmo escrito em português até a classificação dos erros; precisa o pouco que se dá por sabido, que é a aritmética escolar, o hábito de seguir instruções escritas e o manejo de arquivos e pastas; formula o problema que a unidade resolve, o de converter um cálculo que se sabe fazer à mão num procedimento que uma máquina executa sem se enganar e sem se cansar; 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.
- Reconhecer os conhecimentos prévios que o curso supõe (operar com inteiros e decimais, calcular um quociente e um resto, seguir instruções escritas, salvar um arquivo numa pasta determinada) e revisá-los se for preciso.
- Explicar, com um exemplo, o caminho que a unidade ensina a percorrer: do enunciado à especificação, da especificação ao algoritmo e do algoritmo ao programa que se compila e se executa.
- 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. Como esta é a primeira unidade do curso, não há perguntas sobre unidades anteriores; em seu lugar, as três primeiras verificam o que o curso dá por sabido: o quociente e o resto de uma divisão inteira, a ordem dos passos de um procedimento e o nome, a extensão e a pasta de um arquivo. As sete seguintes tocam, em ordem, as ideias centrais das seis aulas da unidade. Quem nunca programou não deve esperar acertá-las, e não importa: 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 anterioresRepartem-se 47 folhas entre 6 pessoas, em partes inteiras iguais, e as que não bastam para uma volta completa são guardadas. Quantas recebe cada pessoa e quantas são guardadas?
É a divisão com decimais, não a inteira: as folhas não se partem, e a pergunta pede quantas sobram.Arredondar o quociente para cima exige folhas que não existem; o resto da divisão inteira nunca é negativo quando dividendo e divisor são positivos.Confunde o resto com a parte decimal do quociente: o resto se conta em folhas, não em frações de volta.É a divisão inteira: o quociente é o maior número de voltas completas, e o resto o que sobra, que é sempre menor que o divisor. O curso a usa desde o primeiro programa, e em C++ ela tem operadores próprios.Revisar: Do problema ao algoritmo
Pergunta 2De unidades anterioresPara enviar um arquivo anexo por correio eletrônico há quatro passos: A, escrever o endereço do destinatário; B, clicar em “Enviar”; C, abrir uma mensagem nova; D, anexar o arquivo. Qual é a ordem adequada?
A ordem da enumeração não é a ordem da execução: com ela, a mensagem seria enviada antes de existir.O resultado depende da ordem: o que se anexa depois de enviar não chega.Envia a mensagem sem destinatário e sem anexo; os passos posteriores já não a mudam.Alguns passos dependem de outros (não se pode anexar a uma mensagem que não foi aberta, nem completar uma já enviada), e outros não. Reconhecer essas dependências é a primeira coisa que exige escrever um algoritmo.Revisar: Do problema ao algoritmo
Pergunta 3De unidades anterioresUm arquivo está salvo em
C:\Users\ana\programas\suma.cpp. Qual é o seu nome, qual a sua extensão e em que pasta está?Confunde a pasta que contém o arquivo com o próprio arquivo: o nome é o último componente do caminho.A extensão faz parte do nome; alguns sistemas a ocultam por omissão, e o curso pede para mostrá-la, porquesuma.cppesuma.exesão arquivos muito diferentes.C:é a unidade onde começa o caminho, não uma extensão.O caminho enumera as pastas desde a raiz até o arquivo; a extensão, o que segue o último ponto do nome, diz que tipo de conteúdo ele tem:.cppé código-fonte de C++. Para compilá-lo, o terminal deve estar situado nessa pasta ou receber o caminho completo.Revisar: Compilar, executar e configurar
Pergunta 4Uma receita diz: “Se a massa estiver seca, acrescentar uma colher de água e sovar; repetir até que não esteja”. A massa precisa de exatamente três colheres para deixar de estar seca. Quantas vezes se pergunta se a massa está seca?
Não conta a pergunta cuja resposta é “não”, que também se faz: sem ela, ninguém saberia que é preciso parar de acrescentar água.Confunde o texto do procedimento com a sua execução: a condição está escrita uma vez, mas é avaliada em cada volta.Conta os intervalos entre as colheres, não as perguntas.Em toda repetição que pergunta antes de agir, a condição é avaliada uma vez mais que o corpo: a última pergunta é a que permite sair. Seguir o procedimento à mão, contando, o mostra sem ambiguidade.Revisar: Do problema ao algoritmo
Pergunta 5Qual destas instruções qualquer pessoa, ou uma máquina, pode seguir exatamente da mesma maneira?
Depende do gosto de quem executa: duas pessoas a seguiriam de maneira diferente, e uma máquina não tem gosto.Não diz quantas vezes nem o que é ficar bom: a condição de término não é verificável.Não fixa os números: “grande” não é uma quantidade, e o divisor poderia ser zero.Diz que operação se faz, com que dado e onde fica o resultado; nada depende do juízo de quem a executa. Essa precisão é uma das três exigências de um algoritmo.Revisar: Do problema ao algoritmo
Pergunta 6Um programa compila sem erros nem avisos, executa bem com muitos dados, e com um em particular para com a mensagem “division by zero”. Em que momento se produziu o erro?
O compilador traduz o texto, não o executa, e não conhece os dados que o usuário digitará.O ligador reúne as partes do programa; não faz contas nem vê dados.Com outros dados o mesmo executável funciona: o defeito está no que o programa faz com esse dado, não nas ferramentas.O que depende só do texto do programa se descobre ao compilar ou ao ligar; o que depende dos dados, só ao executar. Por isso um programa que compila não está, só por isso, livre de erros.Revisar: Programas, compiladores e C++
Pergunta 7Instalou-se o Visual Studio Code com sua extensão de C++, e ao pedir
g++ --versionno terminal, este responde que não reconheceg++. O que é mais provável?A extensão não contém o compilador nem intervém no que o terminal encontra.O comandog++ --versionnão compila nenhum programa: só pergunta a versão, e o terminal nem sequer encontrou a quem perguntá-la.O editor é indiferente: o que falta é o compilador, em qualquer editor.O editor não compila: chama um compilador à parte, que deve estar instalado e ser encontrado pelo terminal. A extensão de C++ ajuda a escrever o código, mas não traz compilador.Pergunta 8O compilador escreve uma mensagem que começa com
warning:e, apesar dela, produz o executável. O que significa?Isso seria um erro (error:), e então não haveria executável.Funcionar com os dados testados não prova nada sobre os demais; um aviso ignorado é, muitas vezes, o erro de amanhã.O executável é normal; o duvidoso é o que o programa faz no lugar assinalado.Um erro impede obter o executável; um aviso o permite, mas assinala código suspeito. Muitos avisos denunciam defeitos reais, e por isso o curso exige programas que compilem sem nenhum.Revisar: Compilar, executar e configurar
Pergunta 9Onde começa a execução de um programa de C++?
A primeira linha costuma ser uma diretiva#include, que é processada antes de compilar e não é executada.A ordem no arquivo não decide o ponto de entrada; quem o decide é o nomemain.O padrão fixa o nome do ponto de entrada; ele não se escolhe no comando de compilação.mainé o ponto de entrada: o sistema a chama ao pôr o programa em marcha, e o programa termina quando ela termina. Um programa semmaincompila, mas não liga.Revisar: Anatomia de um programa
Pergunta 10Um programa declara
int age{};, executastd::cin >> age;para ler uma idade, e o usuário digitaabc. O que acontece?Não para: continua como se a leitura tivesse dado certo, e por isso o defeito é perigoso.Uma variávelintsó guarda inteiros; as letras não se convertem em número nem se guardam.A leitura não tenta de novo: fracassa uma vez e deixa o fluxo em erro.A leitura de um inteiro fracassa ao encontrar uma letra; o padrão diz que a variável recebe 0 e que as leituras seguintes não farão nada até que se trate o erro. Se o programa não verifica a leitura, escreve conclusões falsas sem nenhum sinal.Revisar: Entrada, saída e erros
Os conteúdos da unidade
A unidade tem seis aulas, que percorrem em ordem o caminho de um problema a um programa em funcionamento. Cada uma supõe a anterior, e a primeira não supõe nada da linguagem.
- Do problema ao algoritmo. O curso começa sem código, porque o algoritmo precede o programa. A aula ensina a especificar um problema pela sua entrada, pela sua saída e pela relação entre ambas (a pré-condição e a pós-condição); a descrever um algoritmo em passos numerados, sem ambiguidade; a rastreá-lo à mão com uma tabela de rastreamento; a reconhecer nele a sequência, a decisão e a repetição; e a justificar que uma repetição termina, com uma quantidade que decresce a cada volta.
- Programas, compiladores e C++. Um algoritmo escrito para uma máquina é um programa, e um programa de C++ não se executa tal como se escreve: o pré-processador, o compilador e o ligador o convertem num executável. A aula percorre essas três etapas, distingue o que se descobre ao compilar do que só se manifesta ao executar, compara o modelo compilado com o interpretado e situa no tempo os padrões da linguagem, até C++23, o que o curso usa, e C++26, cuja implementação nos compiladores está em curso.
- Instalar o ambiente em Windows, macOS e Linux. Três guias completos, um por sistema, para instalar um compilador capaz de C++23 e o editor Visual Studio Code com sua extensão de C++, verificar que tudo funciona com um programa de teste e resolver as falhas frequentes: o compilador que o terminal não encontra, a versão antiga e o padrão que não foi pedido.
- Compilar, executar e configurar. O ciclo de editar, salvar, compilar, executar e ler, a partir do terminal e a partir do editor, com o comando de compilação do curso. A aula distingue os erros, que impedem o executável, dos avisos, que assinalam código suspeito; ativa os detectores (o de erros de memória, AddressSanitizer, e o de comportamento indefinido, UndefinedBehaviorSanitizer), que vigiam o programa enquanto ele roda; e explica por que uma saída mostra símbolos estranhos no lugar de acentos e do ñ.
- Anatomia de um programa. O programa mínimo, peça por peça: a diretiva de inclusão e os cabeçalhos, a função
maine o código de saída, o namespacestd, as instruções, os blocos e os comentários. A aula ensina a corrigir os erros de estrutura lendo as mensagens do compilador a partir da primeira, e fixa o guia de estilo do curso. - Entrada, saída e erros. O programa se comunica com o exterior: escreve com
std::printestd::println, com especificações de formato para a largura e as casas decimais, e lê comstd::cin. A aula mostra o que acontece quando a entrada não tem a forma esperada e como se verifica a leitura, e fecha a unidade com a classificação dos erros pelo seu momento: de compilação, de ligação, de execução e de lógica.
O fio que as une é o do próprio programa. A primeira aula o concebe, a segunda explica em que ele se converte, a terceira instala as ferramentas que o convertem, a quarta ensina a usá-las e a escutar o que dizem, a quinta o disseca e a sexta o põe a conversar com quem o usa. Se isto é assim, no final da unidade o estudante ainda sabe muito pouco de C++, mas sabe como se trabalha com ele, e isso é o que o resto do curso supõe.
O que se dá por sabido
O curso não supõe nenhuma experiência prévia em programação. Supõe, em compensação, três habilidades que convém revisar agora, se a avaliação de entrada mostrou alguma dúvida.
A primeira é a aritmética escolar: operar com inteiros e com decimais, respeitar a ordem das operações (a multiplicação e a divisão antes da adição e da subtração, salvo parênteses) e, sobretudo, calcular o quociente e o resto de uma divisão inteira. Esta última é mais importante do que parece. Dividir 47 folhas entre 6 pessoas dá 7 a cada uma e sobram 5, o que se escreve , com o resto menor que o divisor . C++ tem um operador para o quociente e outro para o resto, e grande parte dos cálculos com inteiros (converter segundos em horas, separar os algarismos de um número, decidir se um número é par) se reduz a eles. Quem quiser estudá-la com detenção a encontra, com a sua demonstração, no curso Álgebra e Geometria I: Números, Funções e Geometria do Plano; aqui basta saber calculá-la.
A segunda é o hábito de seguir instruções escritas ao pé da letra e de reconhecer quando uma instrução não basta para saber o que fazer. Não se trata de um conhecimento, mas de uma atitude: ler “acrescentar sal a gosto” e perceber que essa instrução depende de quem a executa. A primeira aula da unidade converte essa atitude em método.
A terceira é o manejo básico de um computador: criar uma pasta, salvar nela um arquivo com um nome escolhido, reconhecer a extensão do nome (.cpp, .txt, .exe) e saber em que pasta está cada arquivo. Convém configurar desde já o sistema para que mostre as extensões, que alguns sistemas, como o Windows, ocultam por omissão: o código-fonte suma.cpp e o executável suma.exe são arquivos muito diferentes, e confundi-los é uma fonte de erros absurdos. A unidade ensina também a usar o terminal, de modo que não é preciso sabê-lo de antemão; basta estar disposto a digitar comandos em vez de clicar em botões. Instalar programas exige, por último, poder fazê-lo no próprio computador; a aula de instalação indica uma alternativa on-line para quem não puder.
Não se supõe o inglês. As mensagens do compilador estão em inglês, e o curso ensina a lê-las campo por campo, de modo que o que importa nelas (o arquivo, a linha, o tipo de defeito) se entende sem dominar a língua. Tampouco se supõe nenhuma matemática além da escolar: os exemplos usam a divisão, as médias, a tabuada, as datas e as horas.
O problema que a unidade resolve
Um cálculo que se sabe fazer à mão não é ainda um programa. A distância entre ambos é o que a unidade ensina a percorrer, e um problema simples permite medi-la.
Um cronômetro registra a duração de cada atividade como um número de segundos, por exemplo 7384, e quer-se escrevê-la na forma habitual de horas, minutos e segundos, com os minutos e os segundos sempre com dois algarismos: 2:03:04. À mão, o cálculo é uma cadeia de divisões: , donde resultam 2 horas e 184 segundos; , donde resultam 3 minutos e 4 segundos. Para uma duração, faz-se em um minuto. Para as mil durações de um registro, em compensação, o cálculo à mão é longo e propenso a erros, e a tarefa se presta a que uma máquina a execute.
Ora, uma máquina não pode receber a explicação anterior. Recebe um texto numa linguagem de programação, e para escrever esse texto é preciso ter resolvido antes três questões que o cálculo à mão deixava implícitas. A primeira é a especificação: o que entra (um número inteiro de segundos, não negativo), o que sai (três inteiros, as horas, os minutos e os segundos) e que relação os une: se é o total, , com e . A segunda é o algoritmo: os passos precisos que, para qualquer entrada admissível, produzem essa saída.
- recebe o valor do quociente de por .
- recebe o valor do quociente por do resto de por .
- recebe o valor do resto de por .
- Escrever , dois-pontos, com dois algarismos, dois-pontos e com dois algarismos.
A terceira é a escrita do algoritmo em C++, com a forma exata que a linguagem exige, e a sua tradução a um executável com as ferramentas adequadas. O programa seguinte o faz. Contém muitas coisas que ainda não foram explicadas: as variáveis (aula 2.1), os operadores / e %, que dão o quociente e o resto da divisão inteira (aula 3.1), a leitura com std::cin e as especificações de formato (aula 1.6); a especificação {:02} deste programa, que escreve um número em duas posições completando com zeros à esquerda, é uma variante da largura que essa aula ensina e que a aula 3.1 usará. Por ora basta reconhecer nele os quatro passos do algoritmo.
#include <iostream>#include <print>int main(){ int total{}; // as variáveis serão explicadas na aula 2.1 std::print("Duração em segundos: "); std::cin >> total; const int hours{total / 3600}; const int minutes{total % 3600 / 60}; const int seconds{total % 60}; std::println("{} s = {}:{:02}:{:02}", total, hours, minutes, seconds);}7384Duração em segundos: 7384 s = 2:03:04As linhas 9 a 11 são os passos 1 a 3, e a linha 12 é o passo 4. Que o resultado coincida com o calculado à mão não é uma casualidade, mas a verificação que todo programa merece: testá-lo primeiro com um dado cuja resposta se conhece.
O programa resolve o problema, mas a unidade ensina também a desconfiar dele. Se o usuário digita abc em lugar de um número, a leitura fracassa, total fica em zero e o programa escreve, sem nenhum sinal de alarme, que a duração é 0:00:00: uma conclusão falsa com aparência de verdadeira. Se digita uma duração negativa, a especificação não diz o que deve acontecer, e o resultado carece de sentido. Se se escreve total / 360 em lugar de total / 3600, o programa compila, executa e dá um resultado errado, e nenhuma ferramenta o adverte. Cada um desses defeitos pertence a um tipo diferente de erro, que se descobre num momento diferente e se procura de um modo diferente; a última aula da unidade os classifica. Daí se segue que o problema que a unidade resolve não é só o de escrever este programa, mas o de saber por que funciona, com que dados deixa de funcionar e que ferramenta avisará, ou não, de cada defeito.
Portanto, ao terminar a unidade o estudante poderá escrever, compilar e executar programas deste tipo: uns poucos dados de entrada, umas contas em sequência e uns resultados escritos com formato. Não poderá ainda tomar decisões nem repetir instruções em C++ (embora sim num algoritmo escrito em português), nem escolher com critério o tipo de cada dado; isso é o que trazem as unidades seguintes.
Aonde conduz
A unidade é o limiar do curso. O que nela se usa sem explicar se explica depois, nesta ordem. A unidade 2, “Dados e tipos”, explica as variáveis e como se guardam na memória, os limites dos inteiros (e por que um cálculo correto pode estourar), o arredondamento dos números com decimais e as conversões entre tipos. A unidade 3, “Expressões e operadores”, explica a aritmética de C++, com o quociente e o resto dos negativos, a lógica das condições e o que o padrão deixa sem definir numa expressão. A unidade 4, “Controle de fluxo”, leva a C++ as decisões e as repetições que a primeira aula escreve em português, e ensina a justificar que um laço é correto e termina. A unidade 5 decompõe os programas em funções; a 6 introduz os dados compostos (arranjos, vetores, tabelas e registros), com os algoritmos de busca e ordenação e o seu custo; a 7 trata do texto, da entrada robusta e dos arquivos; e a 8, dos programas de vários arquivos, dos testes sistemáticos e do depurador.
Depois do curso, Programação em C++ II continua com o que este deixa de fora de propósito: os ponteiros e a memória dinâmica, as classes com métodos, os templates próprios, as funções anônimas e as exceções. Nenhum desses temas é necessário para resolver os problemas deste curso, e adiá-los permite concentrar-se no que vale em qualquer linguagem: especificar, projetar o algoritmo, escrevê-lo com clareza e verificar que é correto. A aula de síntese desta unidade recolherá precisamente essa distinção, entre o que é próprio de C++ e o que se levará a qualquer outra linguagem.