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.
- 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 ife váriosifindependentes. - Os cuidados com as fronteiras:
>ou>=? - Como tratar valores inválidos primeiro e o papel do
elsefinal. - 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:
| Nota | Conceito |
|---|---|
| 9 ou mais | A |
| de 7 até menos de 9 | B |
| de 5 até menos de 7 | C |
| menos de 5 | D |
#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:
6.8 >= 9? Falso. Desce.6.8 >= 7? Falso. Desce.6.8 >= 5? Verdadeiro. MostraConceito C.- O
elseé pulado, e o programa segue depois da cadeia.
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.
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 / else | Vários if soltos | |
|---|---|---|
| Quantos blocos podem rodar | No 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ão | Sim, testa todas |
| Use quando | As opções se excluem: um conceito por aluno, uma faixa de preço, uma opção de menu | As 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.
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
| Forma | Quando usar |
|---|---|
if / else if / else | Opções que se excluem, decididas por faixas ou condições variadas (notas, preços, idades). |
Vários if soltos | Verificações independentes, que podem ser todas verdadeiras. |
Faixas completas com && | Quando a ordem não pode importar; em geral, a cadeia else if é melhor. |
switch | Uma 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 aninhado | Evite; veja Operador Ternário. |
Quando dá errado
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.
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.
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
| Escrita | O 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 final | Opcional; garante uma resposta para todo caso |
| Casos inválidos | Primeiro da cadeia: if (x < 0 || x > 10) { … } else if … |
-Wdangling-else | Avisa quando um else sem chaves pode pertencer a dois if |
Exercícios
1. Complete a cadeia
Complete para mostrar "Criança", "Adolescente" ou "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 ifencadeia 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áriosifsoltos → todos os verdadeiros rodam.- Teste os valores de fronteira:
>e>=só diferem neles. - Barre os valores inválidos primeiro. O
elsefinal é opcional, mas garante uma resposta. - Sem chaves, o
elsepertence aoifmais próximo (-Wdangling-else). Use chaves sempre.