Estrutura de Seleção Múltipla: Escolha / Caso (switch / case)
Descubra como substituir cadeias repetitivas de comparações de igualdade por uma estrutura limpa, elegante e de altíssimo desempenho. Aprenda a dominar o comando pare, compreenda o mecanismo de fallthrough e entenda como as jump tables aceleram seu código.
1. O Problema da Igualdade Repetitiva: Por Que o Escolha/Caso Nasceu?
Nas Aulas 08 e 09, você dominou a arte de guiar o fluxo do programa através de condições booleanas e encadeamentos lineares com se / senao se / senao. No entanto, existe um padrão de problema extremamente frequente em software que revela uma limitação de elegância do se: a avaliação de uma única variável contra uma lista de valores constantes específicos.
Pense no menu de opções de um caixa eletrônico ou de um sistema de autoatendimento telefônico (URA):
• Digite 1 para Consultar Saldo;
• Digite 2 para Efetuar Depósito;
• Digite 3 para Fazer Transferência;
• Digite 4 para Falar com Atendente;
• Digite 5 para Encerrar o Atendimento.
Se implementarmos esse menu utilizando se / senao se, o código resultante terá esta aparência redundante:
se (opcao == 1) {
consultarSaldo();
} senao se (opcao == 2) {
efetuarDeposito();
} senao se (opcao == 3) {
fazerTransferencia();
} senao se (opcao == 4) {
falarAtendente();
} senao se (opcao == 5) {
encerrar();
} senao {
saida("Opção Inválida!");
}
Note a ineficiência visual: repetimos a palavra opcao == cinco vezes! Estamos avaliando a mesma expressão contra diferentes valores literais. Para solucionar esse problema e proporcionar uma sintaxe muito mais limpa e legível para seleções categóricas, os criadores das primeiras linguagens estruturadas criaram a estrutura Escolha / Caso (em inglês, switch / case).
2. A Anatomia da Estrutura Escolha / Caso
A estrutura escolha / caso possui quatro elementos primordiais: a expressão de teste central, os rótulos de caso (caso), a instrução de saída de bloco (pare / break) e o caso de escape padrão (padrao / default):
escolha (expressao_avaliada) {
caso valor_constante_1:
instrucao_A();
pare;
caso valor_constante_2:
instrucao_B();
pare;
padrao:
instrucao_padrao();
}
Vamos analisar as responsabilidades de cada componente:
-
escolha (expressao): Define qual valor será inspecionado pelo mecanismo de chaveamento. A expressão pode ser uma variável inteira, um caractere ou, em linguagens modernas (como JavaScript, Java 7+ e C#), uma cadeia de texto (string). -
caso valor:: Rótulo que define o ponto de entrada caso o valor avaliado coincida perfeitamente com aquele literal. -
pare(oubreak): Comando que interrompe a execução e faz o fluxo saltar para fora de todo o bloco doescolha. -
padrao(oudefault): Bloco opcional executado se nenhum dos valores listados corresponder ao valor da expressão avaliada. -
}(chave de fechamento): Delimita o fim da estruturaescolha, como nas linguagens C-like.
3. O Comando Pare (break) e o Mecanismo de Fallthrough (Efeito Cascata)
A característica mais singular do switch / case em relação ao if / else é a forma como a CPU transita entre os blocos. Quando um teste de caso é atendido, o computador não para automaticamente ao fim daquele caso: ele continua executando todas as linhas de código abaixo incondicionalmente até encontrar uma instrução explícita de parada ou o fim do bloco!
Esse comportamento é denominado internacionalmente de Fallthrough (literalmente, "cair através"). É exatamente para evitar o fallthrough acidental que utilizamos o comando pare (break) ao final de cada caso.
4. Agrupamento de Casos: Usando o Fallthrough a Seu Favor
Embora o fallthrough acidental seja uma das fontes mais frequentes de bugs para novatos, ele não foi criado por engano. Quando usado intencionalmente por programadores experientes, o fallthrough permite agrupar múltiplos casos que compartilham a mesma resposta lógica de forma extremamente limpa.
Imagine um algoritmo que recebe o número do dia da semana (de 1 a 7, onde 1 é Domingo e 7 é Sábado) e precisa classificar se aquele dia é um Dia Útil ou Fim de Semana:
numero diaSemana = entrada("Digite o dia da semana (1 a 7):");
escolha (diaSemana) {
caso 1:
caso 7:
saida("Fim de semana! Hora de descansar.");
pare;
caso 2:
caso 3:
caso 4:
caso 5:
caso 6:
saida("Dia útil. Foco nos estudos e no trabalho!");
pare;
padrao:
saida("Número inválido! O dia deve ser de 1 a 7.");
}
Veja como o agrupamento funciona: se diaSemana for 2, 3, 4, 5 ou 6, o computador entra no primeiro caso que coincidir, "escorrega" pelas linhas sem comandos intermediários e executa a mensagem comum de dia útil antes de encontrar o pare. Essa técnica substitui uma longa expressão composta com múltiplos operadores ||.
5. O Caso Padrão (padrao / default): A Rede de Proteção
A cláusula padrao (ou default) é o equivalente funcional ao bloco final do senao estudado nas aulas anteriores. Ela é disparada se o valor testado não corresponder a absolutamente nenhum dos rótulos anteriores.
Embora não seja obrigatória do ponto de vista estritamente sintático, incluir o padrao é um mandamento de programação defensiva. Usuários frequentemente digitam números fora dos limites esperados (como digitar "9" em um menu de 1 a 4). Sem o padrao, o programa simplesmente ignoraria a entrada em silêncio, deixando o usuário sem feedback.
6. Como o Hardware Otimiza o Switch: O Segredo das Jump Tables
Por que engenheiros de computação preferem switch / case a longas cadeias de if / else if em sistemas de alto desempenho (como motores de jogos, compiladores e sistemas operacionais)?
A resposta está na arquitetura de baixo nível da CPU. Quando você escreve uma cadeia de 10 if / else if, a CPU precisa executar até 10 instruções comparativas sequenciais (complexidade \(O(n)\)). Se a opção desejada for a décima, as nove anteriores tiveram que ser testadas primeiro.
Em contraste, quando os casos de um switch envolvem inteiros consecutivos ou próximos, os compiladores modernos geram uma estrutura chamada Jump Table (Tabela de Salto). O compilador monta um vetor na memória contendo os endereços exatos das instruções de cada caso. A CPU calcula o endereço por indexação aritmética simples em tempo \(O(1)\) constante e salta instantaneamente para o código de destino, não importando se há 5 ou 500 opções no menu!
7. Quando Usar: Se / Senão Se vs Escolha / Caso
Saber escolher a ferramenta adequada para o problema certo é o que distingue um programador experiente de um iniciante:
| Critério | Se / Senão Se (if / else if) | Escolha / Caso (switch / case) |
|---|---|---|
| Tipo de Teste | Qualquer expressão booleana complexa | Igualdade estrita contra valores literais |
| Faixas Numéricas | Excelente (ex: idade >= 18 && idade <= 65) |
Inadequado na maioria das linguagens |
| Múltiplas Variáveis | Suporta combinar variáveis distintas | Avalia uma única variável/expressão |
| Menus e Estados | Verboso e repetitivo | Limpo, elegante e altamente legível |
| Performance (\(N\) grande) | Busca sequencial \(O(N)\) | Otimizável via Jump Table \(O(1)\) |
8. 5 Armadilhas Fatais com Escolha / Caso
1ª Armadilha: Esquecer o "pare" (break) Involuntariamente
É o erro clássico universal. O desenvolvedor esquece o pare ao fim do caso 1, e o programa executa a rotina do caso 1 e logo em seguida a do caso 2. Sempre revise visualmente o final de cada bloco de caso.
2ª Armadilha: Tentar Usar Operadores Relacionais no Caso
Escrever caso > 10: ou caso x >= 5 && x <= 10: é erro de sintaxe em Portugol, C, C++, Java e JavaScript clássico. O rótulo do caso exige um valor constante exato, não uma expressão relacional.
3ª Armadilha: Variáveis no Rótulo do Caso
O rótulo deve ser uma constante literal conhecida em tempo de compilação (ex: caso 1: ou caso "SALVAR":). Você não pode escrever caso outraVariavel: na maioria das linguagens estruturadas.
4ª Armadilha: Incompatibilidade de Tipos (Type Mismatch)
Se a expressão for do tipo numero e você testar contra um texto (ex: caso "1": em vez de caso 1:), a igualdade estrita falhará e o programa cairá no padrao.
5ª Armadilha: Esquecer que o "padrao" Não Precisa de "pare" se For o Último
Se o padrao estiver posicionado no rodapé da estrutura, o pare é opcional porque o bloco já termina ali. No entanto, se você posicionar o caso padrão no início ou no meio (permitido em algumas linguagens), omitir o pare fará a execução desabar sobre o primeiro caso!
9. Exercício Resolvido Completo: URA Telefônica Bancária
Vamos construir o algoritmo de uma Unidade de Resposta Audível (URA) de um banco digital, demonstrando validação, navegação e mensagens de atendimento:
saida("========================================");
saida(" BEM-VINDO À CENTRAL LOGICABR DIGITAL ");
saida("========================================");
saida("1 - Consultar Saldo e Extrato");
saida("2 - Solicitar Segunda Via de Fatura");
saida("3 - Contratar Empréstimo ou Crédito");
saida("4 - Reportar Perda ou Roubo de Cartão");
saida("5 - Falar com Especialista de Suporte");
saida("0 - Encerrar a Ligação");
numero opcaoMenu = entrada("Escolha a opção desejada:");
escolha (opcaoMenu) {
caso 1:
saida("[SALDO] Seu saldo disponível é de R$ 3.450,80.");
pare;
caso 2:
saida("[FATURA] A 2ª via foi enviada para o seu e-mail cadastrado.");
pare;
caso 3:
saida("[CRÉDITO] Você possui R$ 15.000,00 pré-aprovados na sua conta.");
pare;
caso 4:
saida("[EMERGÊNCIA] Seu cartão foi bloqueado preventivamente por segurança.");
pare;
caso 5:
saida("[SUPORTE] Transferindo sua chamada para a fila prioritária...");
pare;
caso 0:
saida("Obrigado por ligar para o logicabr.dev Bank. Até logo!");
pare;
padrao:
saida("[ERRO] Opção '" + opcaoMenu + "' inexistente. Por favor, tente novamente.");
}
saida("Ligação finalizada com sucesso.");
Teste de Mesa (Rastreamento de Cenários)
| Cenário | opcaoMenu | Caso Correspondente | Ação Executada | Efeito do Pare |
|---|---|---|---|---|
| Consulta | 1 | caso 1: |
Exibe saldo de R$ 3.450,80 | Salta para a linha final da ligação |
| Bloqueio | 4 | caso 4: |
Bloqueia cartão imediatamente | Salta para a linha final da ligação |
| Entrada Errada | 8 | padrao: |
Alerta de opção inexistente | Encerra a estrutura normalmente |
Exercício Prático 2: A Calculadora Universal de Operações Aritméticas
Em muitas aplicações de console e utilitários de linha de comando (CLI), o usuário não digita números para selecionar a ação; ele digita o próprio símbolo da operação matemática desejada ('+', '-', '*' ou '/'). Veja como a estrutura escolha / caso trata caracteres de texto de maneira intuitiva e protege o sistema contra a divisão por zero:
numero num1 = entrada("Digite o primeiro número:");
texto operador = entrada("Digite a operação (+, -, *, /):");
numero num2 = entrada("Digite o segundo número:");
escolha (operador) {
caso "+":
numero soma = num1 + num2;
saida("Resultado: " + num1 + " + " + num2 + " = " + soma);
pare;
caso "-":
numero sub = num1 - num2;
saida("Resultado: " + num1 + " - " + num2 + " = " + sub);
pare;
caso "*":
numero mult = num1 * num2;
saida("Resultado: " + num1 + " * " + num2 + " = " + mult);
pare;
caso "/":
se (num2 == 0) {
saida("[ERRO MATEMÁTICO] Não é possível dividir por zero!");
} senao {
numero div = num1 / num2;
saida("Resultado: " + num1 + " / " + num2 + " = " + div);
}
pare;
padrao:
saida("[ERRO] Operador '" + operador + "' inválido. Escolha +, -, * ou /.");
}
Perceba como integramos harmoniosamente uma estrutura condicional se / senao dentro do caso "/" para inspecionar o divisor antes de executar a operação. Essa combinação de escolha no nível macro e se no nível micro é o padrão ouro de design de código limpo na indústria de software.
10. Tabela de Sintaxe Multi-Linguagem
| Linguagem | Comando Switch | Cláusula de Caso | Comando de Saída | Caso Padrão |
|---|---|---|---|---|
| logicabr.dev | escolha (v) { |
caso X: |
pare; |
padrao: |
| JavaScript / TS | switch (v) { |
case X: |
break; |
default: |
| C / Java / C# | switch (v) { |
case X: |
break; |
default: |
| Python (3.10+) | match v: |
case X: |
Não necessita de break | case _: |
11. Perguntas Frequentes (FAQ)
Por que o Python não tinha comando 'switch' até a versão 3.10?
Por muitos anos, a comunidade e os criadores do Python consideravam o if / elif / else suficientemente claro e performático, recomendando dicionários para mapeamento chave-valor. Apenas na versão 3.10 o Python introduziu o match / case, trazendo não apenas seleção simples, mas Pattern Matching Estrutural avançado.
O que acontece se eu esquecer a cláusula 'padrao:' (default)?
Se a variável avaliada não coincidir com nenhum dos casos cadastrados e não houver um bloco padrao:, a estrutura simplesmente encerra sem produzir qualquer efeito colateral. Nenhuma exceção de parada ou erro em tempo de execução é disparado, mas o usuário pode ficar sem retorno de interface. Por boa prática de engenharia defensiva, inclua sempre a cláusula padrao: para tratar entradas anômalas ou não mapeadas.
Posso usar textos (strings) no comando escolha / caso?
Na plataforma logicabr.dev e em ecossistemas contemporâneos como JavaScript, TypeScript, Java (desde a versão 7) e C#, sim! Você pode avaliar textos literais como caso "SIM": e caso "NAO": diretamente. Em linguagens antigas como C clássico dos anos 1970, apenas tipos inteiros primitivos e caracteres (char) eram aceitos pela arquitetura.
Qual é a diferença entre Switch/Case e Tabelas de Dispersão (Lookup Tables de Objetos)?
Em engenharia de software avançada (especialmente em TypeScript, Python e JavaScript), quando o número de casos se torna muito grande ou quando as ações precisam ser injetadas dinamicamente, desenvolvedores sêniores frequentemente substituem o switch por um Dicionário de Funções (Lookup Table). Nele, uma estrutura de chave-valor mapeia a opção diretamente para uma função anônima ou manipulador (ex: acoes[opcao]()). Essa abordagem desacopla o código e viabiliza a aplicação do Princípio Aberto/Fechado (OCD do SOLID), embora para menus procedurais e fluxos de controle direto o escolha / caso continue sendo a solução mais legível e rápida.
Pratique Escolha / Caso na IDE Online!
Crie menus interativos e teste o comportamento do comando pare no editor interativo do logicabr.dev.