eval()

eval()

por José Coelho de Pina -
Número de respostas: 3

Salve,

O que vocês acham da seguinte tentativa de solução do exercício 12 da página de Pilhas de Paulo Feofiloff http://www.ime.usp.br/~pf/algoritmos/aulas/pilha.html ?

float 
eval (char posf[]) 
{
    int   n = strlen(posf);

    /* pilha de caracteres */
    char  pilha[MAX];
    int   topo = 0;

    int   i;
    float resultado = 0;

    for (i = 0; i < n; i++)
    {
      if ('A' <= posf[i] && posf[i] <= 'Z')
      {
          pilha[topo++] = posf[i];
      }
      else 
      {
          float valor1 = tabela[pilha[--topo]];
          float valor2 = tabela[pilha[--topo]];
          if (posf[i] = '+') 
          {
              resultado += valor1 + valor2;
          }
          else if  (posf[i] = '-')
          {
              resultado += valor1 - valor2;
          } 

          else if (posf[i] = '/')
          {
              /* supoe valor2 != 0 */
              resultado += valor1 / valor2;
          }

          else if (posf[i] = '*')
          {
              resultado += valor1 * valor2;
          }
      }
    }
      
    return resultado;
}

Em resposta à José Coelho de Pina

Re: eval()

por Thiago Pereira Bueno -

O resultado de cada operação intermediária deveria ser empilhado e não acumulado na variável 'resultado', para ao final do for loop ser desempilhado o resultado geral da expressão 'posf ', não?

Além disso, acho que já que " tabela[0] é o valor da variável A, ... ", o acesso aos valores das variáveis empilhadas deveria ser via algo como "tabela['A' - pilha[--topo]]", certo?

Por fim, as comparações nos if-elses estão usando operador de atribuição(=) em vez do operador de comparação (==)... o que dá calafrios... rs...

[]s

Em resposta à Thiago Pereira Bueno

Re: eval()

por José Coelho de Pina -

O resultado de cada operação intermediária deveria ser empilhado e não acumulado na variável 'resultado'

Bingo!
Esse não tem jeito... é meio grave. É conceitual  ... triste

Além disso, acho que já que " tabela[0] é o valor da variável A, ... ", o acesso aos valores das variáveis empilhadas deveria ser via algo como "tabela['A' - pilha[--topo]]", certo?

Bingo novamente.
Esse não e um problema grave, precisava apenas entender como a tabela ASCII codifica caracteres. tímido

Por fim, as comparações nos if-elses estão usando operador de atribuição(=) em vez do operador de comparação (==)... o que dá calafrios... rs..

Esse e tipo erro besta de digitação e cut-and-paste corado As opções de compilação "padrão" fornecem um aviso e se realmente desejamos escrever uma atribuição deveríamos escrever:

if ( (posf[i] = '+') ) ... 

Isso deixaria o compilador feliz. Bem, no caso era erro mesmo.

A seguir esta uma versão corrigida.


/* eval() supoe que a expressao posfixa esta correta 
          e nao ocorrera divisao por zero */

float 
eval (char posf[]) 
{
    int n = strlen(posf);
    int i;

    /* pilha de execucao */
    float *pilha = malloc(n * sizeof(float)); /* ou sizeof(double) */
    int    topo = 0;
    
    float resultado; /* ou double */

    for (i = 0; i < n ; i++)
    {
      if ('A' <= posf[i] && posf[i] <= 'Z')
      {
          pilha[topo++] = tabela[posf[i]-'A']; /* valor da variavel */
      }
      else 
      {
          float valor1 = pilha[--topo];
          float valor2 = pilha[--topo];
          if (posf[i] == '+') 
          {
              pilha[topo++] = valor1 + valor2;
          }
          else if  (posf[i] == '-')
          {
              pilha[topo++] = valor1 - valor2;
          } 

          else if (posf[i] == '/')
          {
              /* supoe valor2 != 0 */
              pilha[topo++] = valor1 / valor2;
          }

          else if (posf[i] == '*')
          {
              pilha[topo++] = valor1 * valor2;
          }
      }
    }
    
    resultado = pilha[topo--]; /* se tudo estiver ok é pilha[0] */
    free(pilha);
    return resultado;
}

/* 
   Esta versao explora mais claramente que posf e um ponteiro 
*/

float 
eval2 (char posf[]) /* o Kernighan e Ritchie preferem (char *posf) */
{
    /* pilha de execucao */
    float *pilha = malloc(strlen(posf) * sizeof(float));
    int    topo = 0;
    
    float resultado;

    for ( ; *posf; posf++) /* usa que '\0' == 0 */
    {
      if ('A' <= *posf && *posf <= 'Z')
      {
          pilha[topo++] = tabela[*posf-'A']; /* valor da variavel */
      }
      else 
      {
          float valor1 = pilha[--topo];
          float valor2 = pilha[--topo];
          if (*posf == '+') 
          {
              pilha[topo++] = valor1 + valor2;
          }
          else if  (*posf == '-')
          {
              pilha[topo++] = valor1 - valor2;
          } 

          else if (*posf == '/')
          {
              /* supoe valor2 != 0 */
              pilha[topo++] = valor1 / valor2;
          }

          else if (*posf == '*')
          {
              pilha[topo++] = valor1 * valor2;
          }
      }
    }
    
    resultado = pilha[topo--]; /* se tudo estiver ok é pilha[0] */
    free(pilha);
    return resultado;
}