C++ else if

Com if e else, o programa escolhe entre dois caminhos. Mas a professora Ana não dá só "aprovado" ou "reprovado": ela dá conceitos A, B, C e D, conforme a faixa da nota. Para três, quatro ou mais caminhos, você encadeia as perguntas com else if ("senão, se"). Nesta aula você vai montar o boletim da Ana, ver por que a ordem das perguntas muda o resultado e entender a diferença entre else if e vários if soltos.

Você vai aprender
  • Como escrever uma cadeia if → else if → else, e como o C++ a percorre.
  • Por que a ordem das condições importa (o bug do "9,5 é conceito C").
  • A diferença entre else if e vários if independentes.
  • Os cuidados com as fronteiras: > ou >=?
  • Como tratar valores inválidos primeiro e o papel do else final.
  • O "else pendurado" e o aviso -Wdangling-else.

Todos os programas desta aula foram compilados com o g++ 15.2 na máquina fictícia da Ana (usuária ana, computador notebook), com g++ -std=c++23 -Wall -Wextra arquivo.cpp -o programa.


A ideia: a fila de perguntas da triagem

No pronto-socorro, a enfermeira faz perguntas em ordem, da mais grave para a mais leve: "Está inconsciente? Então, vermelho. Senão, está sangrando muito? Então, laranja. Senão, tem febre alta? Então, amarelo. Senão, verde". Assim que uma resposta é "sim", ela para de perguntar e encaminha o paciente. Só quem respondeu "não" a todas chega ao último caso.

O else if funciona igual: o C++ testa as condições de cima para baixo, entra no primeiro bloco cuja condição é verdadeira e pula todo o resto da cadeia.


1. O boletim: conceitos A, B, C e D

As faixas da professora Ana:

NotaConceito
9 ou maisA
de 7 até menos de 9B
de 5 até menos de 7C
menos de 5D
#include <iostream>

int main() {
    double nota = 0;
    std::cout << "Nota: ";
    std::cin >> nota;

    if (nota >= 9) {
        std::cout << "Conceito A\n";
    } else if (nota >= 7) {
        std::cout << "Conceito B\n";
    } else if (nota >= 5) {
        std::cout << "Conceito C\n";
    } else {
        std::cout << "Conceito D\n";
    }
}
if (nota >= 9)
A primeira pergunta. Se for verdadeira, mostra A e a cadeia acaba.
else if (nota >= 7)
"Senão, se a nota for 7 ou mais". Só é testada se a primeira foi falsa. Por isso não precisa escrever nota < 9: se chegou aqui, já se sabe que a nota é menor que 9.
else if (nota >= 5)
Só testada se as duas anteriores foram falsas: aqui, a nota é menor que 7.
else
O "todos os outros casos": só roda se todas as condições foram falsas. Não tem condição.
$ g++ -std=c++23 -Wall -Wextra conceito.cpp -o conceito
$ ./conceito
Nota: 9.5                « a Ana digitou 9.5 e Enter
Conceito A
$ ./conceito
Nota: 7                  « exatamente 7: 7 >= 7 é verdadeiro
Conceito B
$ ./conceito
Nota: 6.8
Conceito C
$ ./conceito
Nota: 3
Conceito D

Acompanhe a nota 6.8:

  1. 6.8 >= 9? Falso. Desce.
  2. 6.8 >= 7? Falso. Desce.
  3. 6.8 >= 5? Verdadeiro. Mostra Conceito C.
  4. O else é pulado, e o programa segue depois da cadeia.
O else if não é uma palavra nova

O C++ não tem um comando "else if": é um else seguido de um if. Escrito com todas as chaves, o boletim seria uma escadinha de ifs dentro de elses:

if (nota >= 9) {
    std::cout << "Conceito A\n";
} else {
    if (nota >= 7) {
        std::cout << "Conceito B\n";
    } else {
        if (nota >= 5) {
            std::cout << "Conceito C\n";
        } else {
            std::cout << "Conceito D\n";
        }
    }
}

Funciona igual, mas vai empurrando o código para a direita. Escrever else if na mesma linha é a forma "achatada" de dizer a mesma coisa.


2. A ordem importa

A mesma cadeia, com as perguntas em ordem crescente, parece igualmente certa. Veja o que acontece com a melhor aluna da turma:

#include <iostream>

int main() {
    double nota = 9.5;

    if (nota >= 5) {
        std::cout << "Conceito C\n";
    } else if (nota >= 7) {
        std::cout << "Conceito B\n";
    } else if (nota >= 9) {
        std::cout << "Conceito A\n";
    } else {
        std::cout << "Conceito D\n";
    }
}
$ g++ -std=c++23 -Wall -Wextra ordem.cpp -o ordem
$ ./ordem
Conceito C               « 9.5 deveria ser A!

Nenhum aviso, nenhum erro: o programa está "certo" para o compilador. Mas 9.5 >= 5 é verdadeiro, então a primeira condição já captura a nota, e a cadeia acaba ali. As perguntas >= 7 e >= 9 nunca chegam a ser feitas para quem tirou 5 ou mais: os blocos de B e A são inalcançáveis.

Regra: da faixa mais restrita para a mais ampla

Com >=, comece pelo valor mais alto (9, depois 7, depois 5). Com <, comece pelo mais baixo (nota < 5, depois nota < 7…). Faça a pergunta: "alguma condição de cima já engole os casos desta?". Se sim, a ordem está errada.

Missão: este é o programa com a ordem errada. Reorganize as condições (sem mudar os números) para que a nota 9.5 dê Conceito A. Depois, teste com 7, 6.8 e 3.

#include <iostream>

int main() {
    double nota = 9.5;

    if (nota >= 5) {
        std::cout << "Conceito C\n";
    } else if (nota >= 7) {
        std::cout << "Conceito B\n";
    } else if (nota >= 9) {
        std::cout << "Conceito A\n";
    } else {
        std::cout << "Conceito D\n";
    }
}
#include <iostream>

int main() {
    double nota = 9.5;

    if (nota >= 9) {
        std::cout << "Conceito A\n";
    } else if (nota >= 7) {
        std::cout << "Conceito B\n";
    } else if (nota >= 5) {
        std::cout << "Conceito C\n";
    } else {
        std::cout << "Conceito D\n";
    }
}

3. else if × vários if

E se a Ana tirar o else e escrever três if independentes, um embaixo do outro?

#include <iostream>

int main() {
    double nota = 9.5;

    if (nota >= 9) {
        std::cout << "Conceito A\n";
    }
    if (nota >= 7) {
        std::cout << "Conceito B\n";
    }
    if (nota >= 5) {
        std::cout << "Conceito C\n";
    }
}
$ ./varios
Conceito A
Conceito B               « três conceitos para a mesma aluna!
Conceito C

Sem else, cada if é uma pergunta separada, feita sempre, não importa o que aconteceu antes. 9.5 é maior ou igual a 9, a 7 e a 5: os três blocos rodam.

if / else if / elseVários if soltos
Quantos blocos podem rodarNo máximo um (exatamente um, se houver else)Zero, um, vários ou todos
Testa as condições seguintes depois de achar uma verdadeira?NãoSim, testa todas
Use quandoAs opções se excluem: um conceito por aluno, uma faixa de preço, uma opção de menuAs verificações são independentes: "tem desconto?", "tem frete grátis?", "ganhou brinde?" podem ser todas verdadeiras

Dá para fazer vários if soltos funcionarem com faixas completas, usando && ("e", aula Operadores Lógicos):

#include <iostream>

int main() {
    double nota = 9.5;

    if (nota >= 5 && nota < 7) {
        std::cout << "Conceito C\n";
    }
    if (nota >= 7 && nota < 9) {
        std::cout << "Conceito B\n";
    }
    if (nota >= 9) {
        std::cout << "Conceito A\n";
    }
    if (nota < 5) {
        std::cout << "Conceito D\n";
    }
}
$ ./faixas
Conceito A               « faixas completas: a ordem não importa mais

Funciona, e a ordem deixa de importar. Mas é mais longo, faz sempre as quatro perguntas e é fácil errar uma fronteira (deixar um "buraco" entre duas faixas, ou uma sobreposição). Para opções que se excluem, a cadeia else if é mais simples e mais segura.


4. Fronteiras: > ou >=?

A tabela da professora diz "7 ou mais é B". Veja o que acontece se o programa usar > ("maior que", sem o igual):

#include <iostream>

int main() {
    double nota = 7.0;

    if (nota > 9) {
        std::cout << "Conceito A\n";
    } else if (nota > 7) {
        std::cout << "Conceito B\n";
    } else if (nota > 5) {
        std::cout << "Conceito C\n";
    } else {
        std::cout << "Conceito D\n";
    }
}
$ ./fronteira
Conceito C               « 7 > 7 é falso: o aluno com 7 caiu para C

Os erros de fronteira só aparecem com os valores exatamente no limite. Por isso, ao testar uma cadeia de else if, experimente sempre: um valor no meio de cada faixa e cada valor de fronteira (aqui: 9, 7 e 5).


5. Primeiro os casos inválidos; e o else final

No boletim, o que acontece com a nota 12, digitada por engano? Ela é maior que 9: vira "Conceito A". E -1 vira "Conceito D". Nenhum dos dois faz sentido. Uma boa prática é barrar os valores impossíveis primeiro, no topo da cadeia:

#include <iostream>

int main() {
    double nota = 0;
    std::cout << "Nota: ";
    std::cin >> nota;

    if (nota < 0 || nota > 10) {
        std::cout << "Nota inválida!\n";
    } else if (nota >= 9) {
        std::cout << "Conceito A\n";
    } else if (nota >= 7) {
        std::cout << "Conceito B\n";
    } else if (nota >= 5) {
        std::cout << "Conceito C\n";
    } else {
        std::cout << "Conceito D\n";
    }
}
$ ./invalida
Nota: 12
Nota inválida!
$ ./invalida
Nota: -1
Nota inválida!

O || quer dizer "ou": "se a nota for menor que 0 ou maior que 10". Depois dessa barreira, todas as outras condições podem contar com uma nota entre 0 e 10.

O else final é opcional

Uma cadeia pode terminar num else if, sem else. Aí, se nenhuma condição for verdadeira, nada acontece. Às vezes é isso mesmo que você quer ("se for VIP, dê brinde; senão, se for aniversariante, dê desconto", e os outros clientes não ganham nada). Mas, se todo caso precisa de uma resposta, ponha o else: ele garante que o programa nunca fica calado.


Formas diferentes + qual usar

FormaQuando usar
if / else if / elseOpções que se excluem, decididas por faixas ou condições variadas (notas, preços, idades).
Vários if soltosVerificações independentes, que podem ser todas verdadeiras.
Faixas completas com &&Quando a ordem não pode importar; em geral, a cadeia else if é melhor.
switchUma variável comparada com valores exatos (opção 1, 2, 3 de um menu; a letra 'S' ou 'N'). Não serve para faixas. Aula switch.
Ternário aninhadoEvite; veja Operador Ternário.

Quando dá errado

Uma faixa nunca aparece (o 9,5 virou C)

O que significa: uma condição mais ampla está antes de uma mais restrita e "engole" os casos dela. O compilador não avisa.

Como consertar: com >=, ordene do maior para o menor. Teste um valor de cada faixa.

Aparecem várias respostas para um caso só

O que significa: faltaram os else: são vários if independentes, e todos os verdadeiros rodaram.

Como consertar: ligue as condições com else if.

Um valor exatamente na fronteira cai na faixa errada

O que significa: > no lugar de >= (ou < no lugar de <=).

Como consertar: releia a regra ("7 ou mais" é >= 7) e teste os valores das fronteiras.

warning: suggest explicit braces to avoid ambiguous ‘else’ [-Wdangling-else]
#include <iostream>

int main() {
    double nota = 4.0;
    bool matriculada = false;

    if (matriculada)
        if (nota >= 7)
            std::cout << "Aprovada\n";
    else
        std::cout << "Não está matriculada\n";

    std::cout << "Fim\n";
}
$ g++ -std=c++23 -Wall -Wextra dangling.cpp -o dangling
dangling.cpp: In function ‘int main()’:
dangling.cpp:7:8: warning: suggest explicit braces to avoid ambiguous ‘else’ [-Wdangling-else]
    7 |     if (matriculada)
      |        ^
$ ./dangling
Fim                      « a mensagem "Não está matriculada" não apareceu

O que significa: "sugiro chaves explícitas para evitar um else ambíguo". Pelo recuo, o else parece ser do primeiro if (matriculada). Mas, sem chaves, a regra do C++ é: o else pertence ao if mais próximo que ainda não tem else, o de dentro (nota >= 7). Como matriculada é falso, o if de fora pula tudo, inclusive o else. Esse é o famoso "else pendurado" (dangling else).

Como consertar: chaves deixam claro a quem o else pertence:

    if (matriculada) {
        if (nota >= 7) {
            std::cout << "Aprovada\n";
        }
    } else {
        std::cout << "Não está matriculada\n";
    }
error: ‘else’ without a previous ‘if’

O que significa: há algo entre o fim de um bloco e o else if/else seguinte (uma linha solta, um ; depois do ), uma chave fechada a mais).

Como consertar: o else precisa vir logo depois da } do bloco anterior. Veja o exemplo completo em if e else.


Referência rápida

EscritaO que faz
if (c1) { A } else if (c2) { B } else { C }Testa c1; se falso, testa c2; se falso, C. No máximo um bloco roda.
Ordem com >=Do maior limite para o menor
Ordem com <Do menor limite para o maior
else finalOpcional; garante uma resposta para todo caso
Casos inválidosPrimeiro da cadeia: if (x < 0 || x > 10) { … } else if …
-Wdangling-elseAvisa quando um else sem chaves pode pertencer a dois if

Exercícios

1. Complete a cadeia

Complete para mostrar "Criança", "Adolescente" ou "Adulto":

if (idade < 12) { std::cout << "Criança"; } (idade < 18) { std::cout << "Adolescente"; } { std::cout << "Adulto"; }

2. Com x = 15, o que mostra: if (x > 5) { std::cout << "a"; } else if (x > 10) { std::cout << "b"; } else { std::cout << "c"; }?

3. Com x = 15, o que mostra: if (x > 5) { std::cout << "a"; } if (x > 10) { std::cout << "b"; }?

4. Numa cadeia com <, qual ordem está certa?

Missão final: o desconto da lojinha

Missão: o programa lê o total da compra (a caixa já digita 130 para você). Complete a cadeia: a partir de R$ 200, Desconto: 15%; a partir de R$ 100, Desconto: 10%; a partir de R$ 50, Desconto: 5%; abaixo disso, Sem desconto. Com 130, deve sair Desconto: 10%. Para testar outros valores, troque a leitura por double total = 250;, por exemplo, e confira as fronteiras 200, 100 e 50.

#include <iostream>

int main() {
    double total = 0;
    std::cin >> total;

    if (total >= 200) {
        std::cout << "Desconto: 15%\n";
    }
    // continue a cadeia aqui
}
#include <iostream>

int main() {
    double total = 0;
    std::cin >> total;

    if (total >= 200) {
        std::cout << "Desconto: 15%\n";
    } else if (total >= 100) {
        std::cout << "Desconto: 10%\n";
    } else if (total >= 50) {
        std::cout << "Desconto: 5%\n";
    } else {
        std::cout << "Sem desconto\n";
    }
}

Resumo

  • else if encadeia perguntas: o C++ testa de cima para baixo, entra no primeiro bloco verdadeiro e pula o resto.
  • A ordem importa: com >=, do maior limite para o menor. Uma condição ampla no topo "engole" as de baixo, sem aviso do compilador.
  • else if → no máximo um bloco roda. Vários if soltos → todos os verdadeiros rodam.
  • Teste os valores de fronteira: > e >= só diferem neles.
  • Barre os valores inválidos primeiro. O else final é opcional, mas garante uma resposta.
  • Sem chaves, o else pertence ao if mais próximo (-Wdangling-else). Use chaves sempre.