Fundamentos de C++

Tipos, expressões, entrada e saída, condições, ciclos e âmbito de variáveis.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

Estrutura de um programa

Este programa completo escreve uma mensagem fixa no ecrã:

#include <iostream>

int main() {
    std::cout << "Olá\n";
}

Ao correr o programa, vês Olá numa linha.

A primeira linha traz a ferramenta de escrita no ecrã. O bloco int main() marca onde o computador começa. A linha do meio escreve o texto.

Cada instrução simples termina com ;. Um bloco de função ou de ciclo não precisa de ; depois da chaveta final. Uma definição de classe e um do ... while terminam com ;. \n dentro do texto muda de linha.

O compilador traduz este ficheiro para um executável. Chegar ao fim de main equivale a return 0;, que indica sucesso ao sistema.

Declarar variáveis com tipos fixos

Uma variável dá nome a um objeto cujo tipo determina os valores representáveis e as operações disponíveis.

int guarda inteiros, double guarda valores de vírgula flutuante, char guarda uma unidade de carácter e bool guarda true ou false. Um objeto é uma região de armazenamento com um tipo e uma variável dá-lhe um nome, por isso inicializa as variáveis antes da primeira leitura.

// Excerto de declarações.
int quantidade = 0;
double preco = 2.75;
char letra = 'A';
bool encontrado = false;
const int limite = 20;
auto total = 3.5; // O compilador deduz double; o tipo continua fixo.

const impede alterar o objeto através desse nome. auto pede ao compilador que deduza o tipo a partir do inicializador, não adia a decisão para a execução. Uma inicialização com chavetas, como int n{3};, impede certas conversões que perdem informação. int n{3.7}; é rejeitado; int n = 3.7; converte para 3.

A largura de int e de long depende do sistema, por isso não assumes tamanhos fixos. Usa sizeof(T) para medir bytes e <limits> para consultar limites. Nos exemplos desta cadeira, char conta armazenamento, não letras visuais de Unicode.

Operadores e divisão

+, -, *, / e % fazem operações aritméticas, com % a calcular o resto de uma divisão inteira. == compara; = atribui. Os operadores relacionais, como < e >=, produzem um bool.

Tipos e divisão
#include <iostream>

int main() {
    int a = 7;
    int b = 2;
    double truncado = a / b;
    double quociente = static_cast<double>(a) / b;
    std::cout << truncado << " " << quociente << "\n";
    std::cout << a % b << " " << std::boolalpha << (a > b) << "\n";
}
Resultado

Executa o código para ver a saída e os gráficos.

Saída:

3 3.5
1 true

A divisão inteira trunca em direção a zero. Por exemplo, -7 / 2 dá -3 e -7 % 2 dá -1, mantendo a == (a / b) * b + a % b quando a operação é representável.

Dividir um inteiro por zero tem comportamento indefinido. O overflow de um inteiro com sinal também tem comportamento indefinido. Não contes com que volte ao menor valor.

Os valores double são aproximações. Para resultados calculados, escolhe o teste adequado ao contrato e ao erro numérico, por exemplo std::fabs(a - b) < 1e-9 com <cmath>.

&& representa “e”, || representa “ou” e ! nega uma condição. Os dois primeiros usam curto-circuito, ou seja, em n != 0 && soma / n > 10 a divisão só é avaliada se n != 0. Usa parênteses quando ajudam a ver a ordem.

Não escrevas 0 <= nota <= 20: C++ compara primeiro 0 <= nota, produz 0 ou 1, e compara esse resultado com 20. Escreve 0 <= nota && nota <= 20.

++i incrementa antes de produzir o valor; i++ produz o valor anterior e incrementa. Num ciclo que ignora esse valor, ambos avançam uma posição. Evita alterar a mesma variável várias vezes na mesma expressão.

Entrada e saída com iostream

#include <iostream> disponibiliza os fluxos padrão. std::cout << valor escreve; std::cin >> valor tenta extrair um valor do tipo da variável. std:: indica o namespace da biblioteca padrão. Na condição de um if ou while, o fluxo vale falso se uma leitura anterior ativou failbit ou badbit. Encontrar o fim e ativar apenas eofbit não torna uma leitura bem-sucedida falsa. A página Ficheiros e validação desenvolve estes estados com registos completos.

Não uses uma variável como se a leitura tivesse resultado sem confirmar o estado do fluxo. Em if (!(std::cin >> n)), o programa deteta entrada ausente ou inválida. Esta validação é diferente de verificar se o valor está no intervalo permitido.

Escolha com switch

Quando a escolha depende de um valor inteiro com casos fixos, switch evita uma cadeia de if. Quando não pretendes continuar no caso seguinte, sai com break ou return. Casos agrupados e queda intencional continuam possíveis.

// Excerto: classifica uma opção de menu.
int opcao = 2;
switch (opcao) {
    case 1: std::cout << "um\n"; break;
    case 2: std::cout << "dois\n"; break;
    default: std::cout << "outra\n"; break;
}

Com opcao = 2, o programa escreve dois. Sem o break do caso 1, escolher 1 executaria também o caso 2. O default trata os valores não listados.

Escolha, iteração e âmbito

if executa um ramo conforme uma condição e else corresponde ao if sem else mais próximo.

O for separa inicialização, condição e avanço. O programa seguinte lê uma quantidade de notas e conta as que são pelo menos 10; as notas variam de 0 a 20 e a quantidade não excede 1000.

Contar valores válidos
#include <iostream>

int main() {
    int quantidade = 0;
    if (!(std::cin >> quantidade) || quantidade < 0 || quantidade > 1000) {
        std::cout << "Quantidade invalida\n";
        return 0;
    }
    int aprovadas = 0;
    for (int i = 0; i < quantidade; ++i) {
        int nota = 0;
        if (!(std::cin >> nota) || nota < 0 || nota > 20) {
            std::cout << "Nota invalida\n";
            return 0;
        }
        if (nota >= 10) ++aprovadas;
    }
    std::cout << "Aprovadas: " << aprovadas << "\n";
}
Resultado

Executa o código para ver a saída e os gráficos.

Saída:

Aprovadas: 3

Segue o exemplo com entrada 5 e notas 9 10 15 0 20:

Antes da iteração iNotas já lidasaprovadas
0nenhuma0
190
29, 101
39, 10, 152
49, 10, 15, 02
59, 10, 15, 0, 203

Antes da iteração de índice i, já lemos i notas válidas e aprovadas conta apenas essas notas. Esta afirmação é um invariante do ciclo. A leitura seguinte e o if mantêm-no, e ++i aproxima o fim. Quando i atinge a quantidade, todas as notas foram consideradas. Para quantidade zero, o corpo não corre.

while testa antes de cada iteração e pode correr zero vezes. do ... while testa depois e corre pelo menos uma vez. Usa while quando o corpo pode não fazer sentido nenhuma vez, como ler notas de uma quantidade que pode ser zero.

Uma variável declarada num bloco só é visível nesse bloco e nos blocos interiores que não a ocultam. O i declarado no for deixa de estar visível depois dele. Uma variável local normal tem duração automática: a sua vida termina ao sair do bloco. Âmbito indica onde o nome é visível e duração de vida indica quando o objeto existe; não são a mesma coisa.

Compilar e correr com g++

Guarda o programa num ficheiro notas.cpp. Num terminal com GCC disponível, na pasta do ficheiro, corre:

g++ -std=c++17 -Wall -Wextra -Wpedantic notas.cpp -o notas
./notas

O primeiro comando compila e liga o programa. -o escolhe o executável, -std=c++17 fixa a linguagem e as opções -W ativam avisos. Se não houver erros, executa o segundo comando e introduz os números. Depois de mudares o código, volta a compilar, porque correr um executável antigo não valida a versão nova.

Toolchain no macOS e no Windows

No macOS, o comando g++ pode identificar o Clang. Confirma com g++ --version; os programas destas páginas usam C++17 portátil. No Windows, usa a toolchain indicada pela cadeira ou um terminal WSL com GCC. Projetos com vários ficheiros precisam de um ambiente local.

Projetos com CMake e CLion

Projetos com vários ficheiros usam CMake para declarar cada executável e o CLion para configurar a toolchain e depurar. A página Organizar e depurar programas mostra o CMakeLists.txt mínimo e os dois comandos de configuração e build para um projeto com main.cpp.

Passagem de argumentos

Uma função pode receber uma cópia ou dar acesso ao objeto original. A escolha faz parte do contrato, não depende de o tipo ser “imutável” noutra linguagem. Vê Funções, arrays e texto para seguir a diferença linha a linha.

Strings

std::string é o tipo habitual para texto e gere o seu armazenamento. std::cin >> texto lê até ao próximo espaço; std::getline lê uma linha. Os exemplos de texto distinguem estas duas operações e as strings de C.

Ler e escrever ficheiros

Ficheiros usam fluxos como a entrada padrão, mas a abertura e os erros precisam de tratamento. A página Ficheiros e validação explica o ciclo correto e por que while (!eof()) é inadequado.

Como complemento aos primeiros programas, tens uma visão geral de C++ de Rodrigo Dias:

Abrir no YouTube

Exercícios

Conversão e divisão inteira

Com int soma = 11, n = 4;, prevê os valores de double a = soma / n;, double b = static_cast<double>(soma) / n; e int c = -soma / n;. Uma média deve conservar a parte fracionária. Qual expressão serve e porquê? Não executes antes de prever.

Pista

Determina primeiro o tipo de cada operando de /.

Solução

a vale 2.0: a divisão inteira produz 2 antes da conversão para o destino. b vale 2.75, pois um operando já é double quando a divisão é calculada. c vale -2, porque a divisão inteira trunca em direção a zero, em vez de arredondar para -3. Para a média, usa a expressão de b, verificando antes que n não é zero.

Confere a tua resposta:

  • Obtive 2, 2.75 e -2 nos três resultados.
  • Expliquei em que expressão a conversão antecede a divisão.
  • Corrigi o cálculo da média sem alterar os valores de entrada.
Voltar à explicação
Justificar o limite de um ciclo

O programa abaixo começa com total = 0 e executa total += i enquanto i < 4.

for (int i = 0; i < 4; ++i) total += i;

Indica os valores visitados, o total final e o que mudaria com i <= 4. Num array de quatro elementos, os índices válidos são 0 a 3.

Pista

Escreve cada valor de i que satisfaz a condição, por ordem.

Solução

Com i < 4, o corpo usa 0, 1, 2, 3, dando 0 + 1 + 2 + 3 = 6. Com i <= 4, inclui também 4, dando 10. Num array de quatro elementos, o segundo limite permitiria o índice inválido 4.

Confere a tua resposta:

  • Enumerei 0, 1, 2 e 3.
  • Obtive total 6 e distingui o total 10 da alternativa.
  • Expliquei o risco de usar <= com índices de um array.

Erros frequentes

Não contes o valor que termina o ciclo como se tivesse passado pelo corpo.

Voltar à explicação
Ordem da proteção de uma divisão

soma e n são inteiros não negativos. Compara as condições abaixo para n = 0. Qual evita a divisão por zero? Justifica a ordem de avaliação e prevê o resultado dessa condição para soma = 60 e n = 5.

n != 0 && soma / n > 10
soma / n > 10 && n != 0
n == 0 && soma / n > 10

Pista
Em &&, uma condição esquerda falsa impede avaliar a direita.
Solução

A primeira condição é segura para zero: n != 0 é falso e a divisão não é avaliada. Na segunda, a divisão vem antes da proteção. Na terceira, n == 0 é verdadeiro e obriga a avaliar a divisão. Estas duas versões têm comportamento indefinido para zero, não uma resposta booleana que possas prever. Com 60 e 5, a primeira avalia 12 > 10 e dá verdadeiro.

Confere a tua resposta:

  • Identifiquei a primeira condição como a única segura para n igual a zero.
  • Localizei a divisão indevida nas outras duas expressões.
  • Obtive verdadeiro para a primeira com soma 60 e n 5.
Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.