b2code 0 Denunciar post Postado Janeiro 24, 2011 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