terça-feira, 5 de março de 2013

Rotinas para pós-fixa.

CÓDIGO-FONTE: https://github.com/r-bauer/postfix/archive/master.zip


Utilizando os arquivos da pilha genérica, as rotinas a seguir apresentam a passagem do algoritmo para código em “C” da avaliação feita anteriormente, bastando alterar o tipo de dado que será usado pela analise de expressão no arquivo stackapp. h,  a informação do valor  inserido.

...
typedef struct tagDATA
{
    float     fVal;
} SDATA;
...

Novamente o arquivo stackdrv.c é utilizado para a aplicação, a rotina recebe como entrada a expressão que foi passada através da linha de comando, o que torna toda a expressão em caracteres de uma string com dígitos e símbolos, a única novidade em relação ao texto anterior sobre a avaliação de uma expressão fica por conta da conversão do valor de entrada, argc tem o total de argumentos que foi passado e cada elemento de argv aponta para uma string com o operador ou símbolo, usando as funções IsNumber e IsOperator para identificar e decidir qual tratamento, abaixo segue a versão da rotina simplificada para facilitar o entendimento, a rotina completa incluída os comentários e tratamentos de erro estão disponíveis no github.

int StackDriver(int argc, char *argv[])
{
    SDATA sdEl;      // dado temporario,
    SSTACK *stk;     // a pilha que serah usada
    int iCnt;        // para ser usado como contador de loop
    float fRes;

    stk = appCreateStack(argc);       // cria e inicializa a pilha

    for (iCnt = 1; iCnt < argc; ++iCnt)
    {
        if ( IsNumber(argv[iCnt]) )
        {
            sdEl.fVal = (float) Atoi(argv[iCnt]);
            appPushData(stk, &sdEl);
        }
        else if ( IsOperator(argv[iCnt][0]) )
        {
            float fVal1, fVal2;

            appPopData(stk, &fVal2);
            appPopData(stk, &fVal1);

            switch (argv[iCnt][0])
            {
                case '+':    
                    sdEl.fVal = fVal1 + fVal2;
                    break;

                case '-':    
                    sdEl.fVal = fVal1 - fVal2;
                    break;

                case '/':    
                    sdEl.fVal = fVal1 / fVal2;
                    break;

                case '*':    
                    sdEl.fVal = fVal1 * fVal2;
                    break;

                case '$':    
                    sdEl.fVal = Expon(fVal1, (int)fVal2);
                    break;
            }

            // salva o resultado na pilha
            appPushData(stk, &sdEl);
        }
    }

    appPopData(stk, &fRes);

    return (EXIT_SUCCESS);
}

               Para a nossa aplicação foram adicionadas uma série de rotinas para ajudar no suporte da avaliação, apesar de varias delas terem equivalentes na biblioteca padrão do“C”, a opção de incluir serve para ilustrar os passos necessários para a resolução e perceber as limitações que o programa possui, a principal em si é a incapacidade de detectar e corrigir um erro, caso seja digitada uma expressão invalida, que não respeite o espaçamento entre símbolos e dígitos. Outros problemas que podem acontecer como a operação para converter string em um valor numérico suporta apenas números inteiros e a função exponencial não aceita expoente negativo.

LOCAL BOOL IsDigit(char c)
{
      return (c >= '0' && c <= '9');
}

LOCAL BOOL IsNumber(char *pStr)
{
      while (*pStr) {
            if (!IsDigit(*pStr)) {
                  return FALSE;
            }
            pStr++;
      }
      return TRUE;
}

LOCAL int Atoi(char *pStr)
{
      int iRet = 0;

      while (*pStr) {
            iRet *= 10;
            iRet += (*pStr++ & 0xF);
      }
      return (iRet);
}

LOCAL BOOL IsOperator(char c)
{
      char cOp[] = {"+-/*$"};
      char *ptr;

      ptr = cOp;
      while (*ptr) {
            if (*ptr++ == c)
                  return TRUE;
      }
      return FALSE;
}

LOCAL float Expon(float fBas, int iExp)
{
      float fRes;

      fRes = fBas;
      while (--iExp)
            fRes *= fBas;

      return fRes;
}

Nenhum comentário:

Postar um comentário