Desafio C

Tabela de despacho para operações matemáticas

Enunciado

Implemente uma calculadora simples usando uma tabela de despacho (array de ponteiros para função). O programa deve ler um operador (+, -, *, /) e dois números, e então executar a operação correspondente. Se o operador for inválido, imprima Operador invalido. Para divisão, se o divisor for zero, imprima Erro: divisao por zero.

Requisitos

  • Definir funções soma, subtrai, multiplica e divide com assinatura double (double, double).
  • Criar um array de ponteiros para função para as quatro operações.
  • Mapear os caracteres +, -, *, / para índices do array (ex.: usando strchr ou switch).
  • Tratar divisão por zero e operador inválido.
  • Imprimir o resultado com duas casas decimais.

Código inicial

#include <stdio.h>
#include <string.h>

double soma(double a, double b) { return a + b; }
double subtrai(double a, double b) { return a - b; }
double multiplica(double a, double b) { return a * b; }
double divide(double a, double b) { return a / b; }

int main(void) {
    char op;
    double x, y;
    // Leia operador e dois números
    // Use tabela de despacho
    return 0;
}

Saída esperada

Resultado: 8.00
Ver dica

Crie um array double (*ops[4])(double, double) = {soma, subtrai, multiplica, divide}; e uma string char *simbolos = "+-*/";. Use strchr para achar o índice; se não encontrar, operador inválido.

Mostrar solução
#include <stdio.h>
#include <string.h>

double soma(double a, double b) { return a + b; }
double subtrai(double a, double b) { return a - b; }
double multiplica(double a, double b) { return a * b; }
double divide(double a, double b) { return a / b; }

int main(void) {
    // Tabela de despacho: array de ponteiros para função
    double (*ops[4])(double, double) = {soma, subtrai, multiplica, divide};
    const char *simbolos = "+-*/";

    char op;
    double x, y;
    // Lê operador e dois números (ex.: "+ 5 3")
    if (scanf(" %c %lf %lf", &op, &x, &y) != 3) {
        printf("Entrada invalida\n");
        return 1;
    }

    // Encontra o índice do operador na string de símbolos
    const char *pos = strchr(simbolos, op);
    if (pos == NULL) {
        printf("Operador invalido\n");
        return 1;
    }
    int idx = (int)(pos - simbolos);

    // Trata divisão por zero
    if (idx == 3 && y == 0.0) {
        printf("Erro: divisao por zero\n");
        return 1;
    }

    // Executa a operação via tabela
    double resultado = ops[idx](x, y);
    printf("Resultado: %.2f\n", resultado);
    return 0;
}

Passo a passo

  1. Definimos as quatro funções de operação, todas com a mesma assinatura double (double, double).
  2. No main, criamos o array ops com os ponteiros para essas funções. A ordem corresponde aos símbolos em simbolos.
  3. Lemos o operador e os dois números com scanf. O espaço antes de %c ignora espaços em branco.
  4. Usamos strchr para localizar o operador na string "+-*/". Se não encontrar, pos é NULL e imprimimos erro.
  5. Calculamos o índice subtraindo o ponteiro inicial: pos - simbolos.
  6. Verificamos se é divisão (índice 3) e se o divisor é zero, tratando o erro.
  7. Chamamos a função apropriada através de ops[idx](x, y) e imprimimos o resultado formatado.

Por que funciona

A tabela de despacho mapeia um índice (derivado do operador) diretamente para a função correta. Isso elimina uma cadeia de if/else ou switch, tornando o código mais limpo e fácil de estender. O uso de ponteiros para função permite que o array armazene funções e as chame dinamicamente.

Erros comuns

  • Esquecer de tratar strchr retornando NULL; isso causaria acesso inválido ao calcular o índice.
  • Não verificar divisão por zero antes de chamar divide, resultando em inf ou nan.
  • Misturar tipos: as funções devem retornar double e receber double. Se usar int, a tabela não compilará corretamente.
  • Ler o operador com scanf("%c", &op) sem espaço antes pode capturar o \n da leitura anterior.

Outra forma de resolver

Usar switch em vez de tabela:

switch (op) {
    case '+': resultado = soma(x, y); break;
    case '-': resultado = subtrai(x, y); break;
    // ...
}

Prefira a tabela quando houver muitas operações ou quando elas puderem ser configuradas em tempo de execução.

Saída esperada

Resultado: 8.00