Bem-vindo ao quinto capítulo da Especialização em Engenharia de Sistemas com Linguagem C (C17/C23)! ⚡

Até este momento, nossos programas executavam comandos de forma estritamente sequencial (uma linha após a outra). Neste capítulo, você aprenderá como alterar o fluxo de execução através da tomada de decisões lógicas, utilizando if, if...else, if...else if...else, seleção múltipla com switch-case e expressões compactas com o Operador Condicional Ternário (?:).

Estruturas Condicionais, Decisão e Operador Ternário em C


🗺️ Mapa Conceitual do Capítulo

graph TD
    A["Controle de Fluxo Condicional em C"] --> B["1. Estruturas if / else"]
    A --> C["2. Seleção switch-case"]
    A --> D["3. Operador Ternário (?:)"]
    A --> E["4. Boas Práticas & Segurança"]

    B --> B1["if simples, if-else binário, if-else if múltiplos caminhos"]
    C --> C1["Chaveamento de inteiros/char, papel do break, default"]
    D --> D1["Atribuição inline, uso em printf, ternários aninhados"]
    E --> E1["Chaves obrigatórias {}, prevenção de Dangling Else, CERT C"]

🔀 1. A Família if, if...else e if...else if...else

Em C, uma condição é uma expressão avaliada como verdadeira (qualquer valor numérico diferente de 0) ou falsa (exatamente igual a 0).

1. if Simples (Decisão Unilateral)

Executa um bloco de instruções apenas se a condição for verdadeira:

if (temperatura > 100.0) {
    printf("Alerta: Temperatura critica atingida!\n");
}

2. if...else (Decisão Binária)

Garante a execução de exatamente um dos dois caminhos mutuamente exclusivos:

if (saldo >= valorSaque) {
    saldo -= valorSaque;
    printf("Saque realizado com sucesso.\n");
} else {
    printf("Saldo insuficiente para a operacao.\n");
}

3. if...else if...else (Múltiplas Faixas de Decisão)

Avalia condições sequencialmente até encontrar a primeira verdadeira. A ordem das condições é crucial:

// ✅ ORDEM CORRETA (Do mais restritivo para o mais amplo)
if (pontuacao >= 90) {
    printf("Classificacao: Ouro 🥇\n");
} else if (pontuacao >= 70) {
    printf("Classificacao: Prata 🥈\n");
} else if (pontuacao >= 50) {
    printf("Classificacao: Bronze 🥉\n");
} else {
    printf("Nao classificado ❌\n");
}

⚠️ 2. Aninhamento de Condicionais & O Problema do Dangling Else

Quando múltiplos if e else são aninhados sem chaves, a linguagem C vincula o else ao if imediatamente anterior, o que pode gerar comportamentos inesperados:

// ❌ CÓDIGO AMBÍGUO (Dangling Else):
if (usuarioAutenticado)
    if (eAdministrador)
        printf("Acesso total concedido.\n");
else
    printf("Acesso negado.\n"); // Esse else pertence ao 'eAdministrador'!

// ✅ CÓDIGO SEGURO E EXPLÍCITO (Com Chaves):
if (usuarioAutenticado) {
    if (eAdministrador) {
        printf("Acesso total concedido.\n");
    }
} else {
    printf("Acesso negado.\n"); // Agora pertence ao 'usuarioAutenticado'!
}

🎯 3. Seleção Múltipla com switch-case

A estrutura switch-case realiza desvios condicionais baseados no valor exato de uma expressão inteira ou caractere (char). Internamente, compiladores modernos geram uma tabela de saltos (Jump Table) em tempo constante $O(1)$:

switch (codigoComando) {
    case 1:
        iniciarProcesso();
        break; // Impede a execução dos casos seguintes (Fall-through)
    case 2:
        pausarProcesso();
        break;
    case 3:
        reiniciarProcesso();
        break;
    default:
        fprintf(stderr, "Comando desconhecido: %d\n", codigoComando);
        break;
}

[!WARNING] O Perigo do Fall-Through: Se você esquecer a instrução break; no final de um case, o programa continuará executando as instruções do próximo case abaixo dele, mesmo que a condição dele não seja correspondente!


⚡ 4. O Operador Condicional Ternário (?:)

O operador ternário é a única operação da Linguagem C que aceita três operandos:

\[\text{Condicao} \quad \mathbf{?} \quad \text{Expressao se Verdadeiro} \quad \mathbf{:} \quad \text{Expressao se Falso}\]

Casos de Uso Mais Frequentes:

  1. Atribuição Direta de Variáveis:
    int maior = (a > b) ? a : b;
    
  2. Uso Inline no printf():
    printf("O sensor esta %s.\n", (sensorAtivo) ? "LIGADO" : "DESLIGADO");
    
  3. Classificação com Ternários Aninhados:
    const char *conceito = (media >= 9.0) ? "Excelente" :
                           (media >= 7.0) ? "Aprovado" :
                           (media >= 5.0) ? "Recuperacao" : "Reprovado";
    

🛡️ 5. Boas Práticas e Segurança de Código (CERT C)

  1. Chaves Obrigatórias em Todos os Blocos: Nunca omita as chaves { ... }, mesmo em comandos de uma única linha. A falha de segurança histórica da Apple (goto fail bug em SSL) ocorreu por falta de chaves em um bloco if.
  2. Nunca use = dentro do if:
    • if (nivelAcesso = 1) atribui 1 e sempre avalia como verdadeiro!
    • if (nivelAcesso == 1) compara o valor corretamente.
  3. Coloque Constantes à Esquerda (Yoda Conditions):
    • Escrever if (1 == nivelAcesso) gera erro de compilação imediato caso você digite acidentalmente um único =, prevenindo bugs silenciosos.

🔍 6. Diagnóstico & Resolução de Problemas (Troubleshooting)

Sintoma Observado Causa Provável Como Resolver
O switch executa todos os blocos de uma vez Esquecimento do comando break; no final dos blocos case. Adicione break; ao término de cada case.
Erro de compilação: switch quantity not an integer Tentativa de usar switch com tipos de ponto flutuante (float, double) ou strings. O switch suporta apenas tipos inteiros e char. Para double ou strings, use if-else if.
O bloco else executa mesmo quando a condição deveria ser verdadeira Ponto e vírgula indevido após o if (ex: if (x > 0); { ... }). Remova o ponto e vírgula ; após o parêntese do if.

🏆 7. Desafio Prático de Consolidação

Enunciado do Desafio: Desenvolva um programa em C chamado classificador_voo.c que simule o sistema de despacho de uma torre de controle:

  1. Solicite ao operador a velocidade atual do vento em km/h (double) e a visibilidade em metros (int).
  2. Utilize if...else if...else com condições compostas (&&, ||) para classificar a pista:
    • Voo Livre (Verde): Vento $< 30$ km/h E Visibilidade $\ge 5000$ m.
    • Voo por Instrumentos (Amarelo): Vento entre $30$ e $60$ km/h OU Visibilidade entre $1500$ e $4999$ m.
    • Pista Fechada (Vermelho): Vento $\ge 60$ km/h OU Visibilidade $< 1500$ m.
  3. Exiba a situação final utilizando um operador ternário formatado no printf.
🔍 Ver Solução Comentada do Desafio
#include <stdio.h>
#include <stdbool.h>

typedef enum {
    MODO_DESLIGADO = 0,
    MODO_RESFRIAMENTO = 1,
    MODO_AQUECIMENTO = 2,
    MODO_EMERGENCIA = 99
} ModoOperacao;

int main(void) {
    double temp = 38.5;
    ModoOperacao modo;

    // Decisao por faixas com if-else e operador ternario
    if (temp > 50.0) {
        modo = MODO_EMERGENCIA;
    } else if (temp > 30.0) {
        modo = MODO_RESFRIAMENTO;
    } else if (temp < 15.0) {
        modo = MODO_AQUECIMENTO;
    } else {
        modo = MODO_DESLIGADO;
    }

    // Processamento com switch-case
    printf("Temperatura Medida: %.1lf C -> ", temp);
    switch (modo) {
        case MODO_RESFRIAMENTO:
            printf("Ativando Refrigeracao Industrial! ❄️\n");
            break;
        case MODO_AQUECIMENTO:
            printf("Ativando Aquecedores de Seguranca! 🔥\n");
            break;
        case MODO_EMERGENCIA:
            printf("ALERTA CRITICO: Desligamento Emergencial! 🚨\n");
            break;
        case MODO_DESLIGADO:
        default:
            printf("Temperatura Estavel. Sistema em Standby. 💤\n");
            break;
    }

    return 0;
}

🧭 Navegação Rápida

| 📖 Teoria | 📊 Slides | 🧠 Quiz | 💻 Exemplos | 🧩 Exercícios | | :— | :— | :— | :— | :— | | Ler Teoria | Ver Slides | Fazer Quiz | Ver Exemplos | Praticar Exercícios |


🧭 Navegação do Capítulo: ⬅️ Capítulo Anterior · 📚 Sumário do Módulo · ➡️ Próximo Capítulo