Algoritmo para expressões numéricas simples

C / C++
Enviado por thotypous em Ter, 08/11/2005 - 15:08.C / C++

Exemplo implementado em C de um algoritmo simples para resolver expressões numéricas simples, contendo as operações *, /, + e -. Bom para treinar conceitos de recursão.

Bom... o algoritmo é extremamente simples:

    calcular(s):   Procurar o caracter '+' em s. Se achar:     Separar a string antes e depois do '+'.     Chamar calcular() para cada uma delas e somar.     Retornar o valor.   Procurar o caracter '-' em s. Se achar:     Separar a string antes e depois do '-'.     Chamar calcular() para cada uma delas e subtrair.     Retornar o valor.   Procurar o caracter '*' em s. Se achar:     Separar a string antes e depois do '*'.     Chamar calcular() para cada uma delas e multiplicar.     Retornar o valor.   Procurar o caracter '/' em s. Se achar:     Separar a string antes e depois do '/'.     Chamar calcular() para cada uma delas e dividir.     Retornar o valor.   Retornar o valor de s convertido para número.

O funcionamento do algoritmo será o seguinte: a função recursiva calcular() vai quebrar a string na seguinte ordem: primeiro somas, depois subtrações, depois multiplicações, depois divisões, e ir calculando. Por exemplo, se entrarmos com a expressão "1+2*2-3", acontecerá o seguinte:

  • A função quebra a string no '+':
      "1" + "2*2-3"
  • Agora a função será chamada para o primeiro pedaço e para o segundo. No segundo pedaço, ela quebra no '-':
      1 + "2*2" - "3"
  • Agora a função será chamada para o segundo e para o terceiro pedaço. No segundo pedaço, ela quebra no '*':
      1 + "2" * "2" - 3
  • Bom, hora das funções retornarem, não? Agora elas vão retornar na ordem inversa à ordem que quebraram a string. Ou seja, efetuaram primeiro a multiplicação:
      1 + 4 - 3
  • Então, a subtração:
      1 + 1
  • E, finalmente, a soma, que foi quebrada primeiro:
      2

Como você pôde perceber, a idéia é quebrar a string na prioridade inversa à que as operações devem ser realizadas, porque é do argumento com o qual a função é chamada por último que o retorno é obtido primeiro. Vamos à implementação em linguagem C:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. int calcular(char *s)
  6. {
  7.   char *p;
  8.   if((p = strchr(s, '+')))
  9.   {
  10.     *p = 0;
  11.     return calcular(s) + calcular(p+1);
  12.   }
  13.   if((p = strchr(s, '-')))
  14.   {
  15.     *p = 0;
  16.     return calcular(s) - calcular(p+1);
  17.   }
  18.   if((p = strchr(s, '*')))
  19.   {
  20.     *p = 0;
  21.     return calcular(s) * calcular(p+1);
  22.   }
  23.   if((p = strchr(s, '/')))
  24.   {
  25.     *p = 0;
  26.     return calcular(s) / calcular(p+1);
  27.   }
  28.   return atoi(s);
  29. }
  30.  
  31. int main(int argc, char **argv)
  32. {
  33.   printf("%d\n", calcular(argv[1]));
  34.   return 0;
  35. }
  36.  

E, é claro, o teste:

    paulo@antartica:~ $ gcc expr.c paulo@antartica:~ $ ./a.out 1+2*2-3 2 paulo@antartica:~ $ ./a.out 2*2+1-3 2 paulo@antartica:~ $ ./a.out 1-3+2*2 2 paulo@antartica:~ $ ./a.out -222+11*2 -200