Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

b2code

[Resolvido] [Código]Calculadora básica

Recommended Posts

Em resposta a esse tópico criei uma versão extremamente simplificada e bem falha de uma calculadora simples interpretada.Não aceita parenteses e só aceita operadores binários.A função pow deve ser ou definida ou linkada.

Interpreta strings simples como: 2^2+2*10+10-1+2>1

Segue:

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

extern double pow(double base, double expoent);

//DEFINICAO UTILITARIA DE TIPO BOOLEANO
typedef char mBool;

//Macros utilitarios
#define TRUE 1
#define FALSE 0
#define MATH_EXPR_SIZE 50
#define I_ERROR_STR_SIZE 50

#define IF_ERROR(action) ({ \
   if(error) action; \
});

//Retira espacos em branco e etc da string.Modifica a propria string
void formatToInterpreter(char * str, size_t len, size_t * newLen)
{
   if(str == NULL) {
       *newLen = 0;
       return;
   }
   char * temp = malloc(len);
   unsigned it = 0;
   unsigned tempIt = 0;
   for(;it < len;++it) {
       char cur = str[it];
       if(cur == ' ' || cur == '\r' || cur == '\n' || cur == '\t')
           continue;
       if(cur == 0x00)
           break;
       temp[tempIt] = cur;
       ++tempIt;
   }
   *newLen = tempIt;
   strncpy(str, temp, tempIt);
   str[tempIt] = 0x00;
   free(temp);
}

//Funcao que diz a precedencia dos operadores binarios
unsigned precedence(char op)
{
   if(op == '*' || op == '/' || op == '%')
       return 1;
   if(op == '>' || op == '<' || op == '|' || op == '&')
       return 2;
   return 0;
}

//Como os operadores binarios devem ser executados
mBool opExecute(char op, float n1, float n2, float * res, char * error)
{
   *res = 0;
   switch(op)
   {
       case '|':
           n1 = (n1 || n2);
           break;
       case '&':
           n1 = (n1 && n2);
           break;
       case '>':
           n1 = (n1 > n2);
           break;
       case '<':
           n1 = (n1 < n2);
           break;
       case '^':
           n1 = pow(n1, n2);
           break;
       case '+':
           n1 += n2;
           break;
       case '-':
           n1 -= n2;
           break;
       case '*':
           n1 *= n2;
           break;
       case '/':
           if(n2 == 0) {
               IF_ERROR(strcpy(error, "Divisao por zero."));
               return FALSE;
           }
           n1 /= n2;
           break;
       case '%':
           if((int)n2 == 0) {
               IF_ERROR(strcpy(error, "Modulo por zero."));
               return FALSE;
           }
           n1 = (int)n1%(int)n2;
           break;
       default:
           IF_ERROR(sprintf(error, "Operador '%c' eh desconhecido.", op));
           return FALSE;
   }
   *res = n1;
   return TRUE;
}

//Interpretador
mBool execute(char * str, size_t len, float * res, char * error)
{
   *res = 0;
   if(len == 0)
       return TRUE;
   float n1;
   float n2;
   char op1;
   char op2;
   //FORMATO IDEAL:NUMERO OPERADOR NUMERO OU NUMERO
   unsigned r = sscanf(str, "%f%c%f%c", &n1, &op1, &n2, &op2);
   if(r < 3) {
       //Formato:NUMERO
       if(r == 1) {
           *res = n1;
           return TRUE;
       } else if(r == 0) { //FORMATO:VAZIO
           IF_ERROR(strcpy(error, "Esperava um numero."));
       } else if(r == 2) { //FORMATO:NUMERO OPERADOR
           IF_ERROR(sprintf(error, "Esperava um numero depois do operador '%c'.", op1));
       }
       return FALSE;
   }
   //So 1 operacao,ja retornamos
   if(!op2)
       return opExecute(op1, n1, n2, res, error);
   char curOp = op1;
   char *op1Pos = strchr(str, op1);
   char *op2Pos = strchr(op1Pos+(op1 == op2), op2);
   unsigned pos = 0;
   if(precedence(op1) > precedence(op2)) {
       curOp = op2;
       pos = op2Pos-str;
       //FORMATO: NUMERO OPERADOR
       if(len-pos-1 == 0) {
          IF_ERROR(sprintf(error, "Esperava um numero depois do operador '%c'.", op2));
          return FALSE;
       }
       if(!opExecute(op1, n1, n2, &n1, error))
           return FALSE;
   } else {
       pos = op1Pos-str;
   }
   ++pos;
   if(!execute(str+pos, len-pos, &n2, error))
       return FALSE;
   if(!opExecute(curOp, n1, n2, res, error))
       return FALSE;
   return TRUE;
}

//Programa
int main()
{
   char mathExpression[MATH_EXPR_SIZE];
   char interpreterError[i_ERROR_STR_SIZE];
   size_t mathExprLen;
   float r;

   puts("---b2code calculator");
   while(1) {
       printf(">");
       fgets(mathExpression, MATH_EXPR_SIZE, stdin);
       if(strcmp(mathExpression, "quit\n") == 0)
           break;
       formatToInterpreter(mathExpression, MATH_EXPR_SIZE, &mathExprLen);
       if(!execute(mathExpression, mathExprLen, &r, interpreterError))
           printf("%s\n", interpreterError);
       else
           printf("%g\n", r);
   }
   return 0;
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.