Pagini recente » Cod sursa (job #62097) | Cod sursa (job #1263313) | Cod sursa (job #628632) | Cod sursa (job #1401238) | Cod sursa (job #195239)
Cod sursa(job #195239)
/* ========================================================================== */
/* */
/* Evaluarea unei expresii.cpp */
/* (c) 2008 Dr.Optix (Cristian Dinu) */
/* */
/* This program take an arithmetic expresion as input from a file and */
/* return the result. Btw first time i made my own class :D */
/* ========================================================================== */
#include <stdlib.h>
#include <stdio.h>
// Error codes
enum EXPR_EVAL_ERR {
EEE_NO_ERROR = 0,
EEE_PARENTHESIS = 1,
EEE_WRONG_CHAR = 2,
EEE_DIVIDE_BY_ZERO = 3
};
typedef char EVAL_CHAR;
EXPR_EVAL_ERR _err;
EVAL_CHAR* _err_pos;
int _paren_count;
long ParseAtom(EVAL_CHAR*& expr);
long ParseFactors(EVAL_CHAR*& expr);
long ParseSummands(EVAL_CHAR*& expr);
long Eval(EVAL_CHAR* expr);
// ============
// Main program
int main() {
FILE *fin=fopen("evaluare.in","r");
FILE *fout=fopen("evaluare.out","w");
static char buff[100001];
fgets(buff,100001,fin);
// Evaluate the expression
long res = Eval(buff);
fprintf(fout,"%ld",res);
return 0;
}
// Parse a number or an expression in parenthesis
long ParseAtom(EVAL_CHAR*& expr) {
// Skip spaces
while(*expr == ' ')
expr++;
// Handle the sign before parenthesis (or before number)
bool negative = false;
if(*expr == '-') {
negative = true;
expr++;
}
if(*expr == '+') {
expr++;
}
// Check if there is parenthesis
if(*expr == '(') {
expr++;
_paren_count++;
long res = ParseSummands(expr);
if(*expr != ')') {
// Unmatched opening parenthesis
_err = EEE_PARENTHESIS;
_err_pos = expr;
return 0;
}
expr++;
_paren_count--;
return negative ? -res : res;
}
// It should be a number; convert it to double
char* end_ptr;
long res = strtod(expr, &end_ptr);
if(end_ptr == expr) {
// Report error
_err = EEE_WRONG_CHAR;
_err_pos = expr;
return 0;
}
// Advance the pointer and return the result
expr = end_ptr;
return negative ? -res : res;
}
// Parse multiplication and division
long ParseFactors(EVAL_CHAR*& expr) {
long num1 = ParseAtom(expr);
for(;;) {
// Skip spaces
while(*expr == ' ')
expr++;
// Save the operation and position
EVAL_CHAR op = *expr;
EVAL_CHAR* pos = expr;
if(op != '/' && op != '*')
return num1;
expr++;
long num2 = ParseAtom(expr);
// Perform the saved operation
if(op == '/') {
// Handle division by zero
if(num2 == 0) {
_err = EEE_DIVIDE_BY_ZERO;
_err_pos = pos;
return 0;
}
num1 /= num2;
}
else
num1 *= num2;
}
}
// Parse addition and subtraction
long ParseSummands(EVAL_CHAR*& expr) {
long num1 = ParseFactors(expr);
for(;;) {
// Skip spaces
while(*expr == ' ')
expr++;
EVAL_CHAR op = *expr;
if(op != '-' && op != '+')
return num1;
expr++;
long num2 = ParseFactors(expr);
if(op == '-')
num1 -= num2;
else
num1 += num2;
}
}
long Eval(EVAL_CHAR* expr) {
_paren_count = 0;
_err = EEE_NO_ERROR;
long res = ParseSummands(expr);
// Now, expr should point to '\0', and _paren_count should be zero
if(_paren_count != 0 || *expr == ')') {
_err = EEE_PARENTHESIS;
_err_pos = expr;
return 0;
}
if(*expr != '\0') {
_err = EEE_WRONG_CHAR;
_err_pos = expr;
return 0;
}
return res;
}