Skip to content

Instantly share code, notes, and snippets.

Created November 29, 2014 12:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/fa127b732f1abb883726 to your computer and use it in GitHub Desktop.
Save anonymous/fa127b732f1abb883726 to your computer and use it in GitHub Desktop.
// postfix.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <fstream>
#include <string>
#include "conio.h"
#include <stack>
#include <map>
#include <iostream>
#include <cmath>
#include <deque>
#include <vector>
#include <sstream>
#include <algorithm>
#include <Windows.h>
using namespace std;
enum {OPERATION, LEFT_PARENTHESIS, RIGHT_PARENTHESIS, FUNCTION, RIGHT_BRACKET, LEFT_BRACKET, ARRAY, NUMBER, LETTER};
void read_vars(ifstream& expr_file, map<string,double>& var, map<string,vector<double>>& arr) {
string tmp;
while(getline(expr_file,tmp)) {
string v;
int i=0;
char c=tmp[i];
while(c!='=' && c!='[') {
v+=c;
i++;
c = tmp[i];
}
if(c=='[') {
vector<double> members;
string s = tmp.substr(i+3,tmp.size()-i+1);
stringstream sstr;
sstr<<s;
double num;
while(sstr>>num) {
members.push_back(num);
}
arr[v] = members;
} else if(c=='=') {
string num = tmp.substr(i+1,tmp.size()-i+1);
double n = atof(num.c_str());
var[v] = n;
}
cout<<tmp<<endl;
}
}
bool is_double(string str)
{
char* endptr = 0;
strtod(str.c_str(), &endptr);
if(*endptr != '\0' || endptr == str)
return false;
return true;
}
int priority_of(string token) {
if(token=="+" || token=="-") return 0;
else if(token=="*" || token=="/") return 1;
else if(token=="^") return 2;
else if(token=="sin"||token=="cos"||token=="acos"||token=="asin"||token=="tan"||
token=="cot"||token=="atan"||token=="acot"||token=="exp"||token=="ln"||
token=="sqrt"||token=="sqrt3") return 3;
else if(token=="(" || token==")") return 4;
else if(token=="[" || token=="]") return 5;
else return -1;
}
int mean_of(string token) {
double d = 0.0;
if(token=="+" || token=="-" || token=="*" || token=="/" || token=="^") return OPERATION;
else if(token=="(") return LEFT_PARENTHESIS;
else if(token==")") return RIGHT_PARENTHESIS;
else if(token=="sin"||token=="cos"||token=="acos"||token=="asin"||token=="tan"||
token=="cot"||token=="atan"||token=="acot"||token=="exp"||token=="ln"||
token=="sqrt"||token=="sqrt3") return FUNCTION;
else if(token=="]") return RIGHT_BRACKET;
else if(token=="[") return LEFT_BRACKET;
else if(token[token.size()-1]=='[' || token[token.size()-1]==']') return ARRAY;
else if(is_double(token)) return NUMBER;
else return LETTER;
}
double sqrt3(double x) {
return pow(x,(double)1/3);
}
void print_error(string error) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, 12);
cerr<<"Error: "<<error<<endl;
}
void point_to_error(int i, string error) {
print_error(error);
for(int j=0;j<i+1;j++) {
cout<<" ";
}
cout<<"^"<<endl;
}
deque<string> postfix(string expr) {
stack<string> stack;
deque<string> postfix_expr;
int i=0;
for(;i<expr.size();i++) {
string token;
string curr_symbol;
string next_symbol;
curr_symbol.push_back(expr[i]);
next_symbol.push_back(expr[i+1]);
token.append(curr_symbol);
while((mean_of(curr_symbol)==LETTER || mean_of(curr_symbol)==NUMBER) && (mean_of(next_symbol)==LETTER ||
mean_of(next_symbol)==LEFT_BRACKET || mean_of(next_symbol)==NUMBER) && i<expr.size()-1) {
token.append(next_symbol);
i++;
curr_symbol = next_symbol;
if(i<expr.size()) next_symbol = expr[i+1];
}
if(mean_of(token) == LETTER || mean_of(token) == NUMBER) {
postfix_expr.push_back(token);
} else if(mean_of(token) == FUNCTION) {
stack.push(token);
} else if(mean_of(token) == ARRAY) {
if(mean_of(next_symbol) == RIGHT_BRACKET) { // a[]
point_to_error(i,"Out of range");
getch();
exit(1);
}
token+="]";
stack.push(token);
} else if(mean_of(token) == RIGHT_BRACKET) {
if(i != expr.size()-1 && mean_of(next_symbol) != OPERATION &&
mean_of(next_symbol) != RIGHT_PARENTHESIS && mean_of(next_symbol) != RIGHT_BRACKET) { // a[b]c
point_to_error(i,"Syntax error");
getch();
exit(1);
}
while(!stack.empty() && mean_of(stack.top()) != ARRAY) {
postfix_expr.push_back(stack.top());
stack.pop();
};
if(stack.empty()) {
point_to_error(i,"Lost left bracket"); // a]
getch();
exit(1);
}
if(!stack.empty() && mean_of(stack.top()) == ARRAY) {
postfix_expr.push_back(stack.top());
stack.pop();
}
} else if(mean_of(token) == OPERATION) {
if(i == expr.size()-1 || next_symbol == ")" || next_symbol == "]") { // a+ || (a+) || a[b+]
point_to_error(i,"Wrong operation");
getch();
exit(1);
}
if(mean_of(next_symbol) == OPERATION) { // a++b
point_to_error(i,"Two operations");
getch();
exit(1);
}
if(token == "-" && (i==0 || expr[i-1]=='(')) {
postfix_expr.push_back("0");
}
while(!stack.empty() && mean_of(stack.top()) == OPERATION && priority_of(token) <= priority_of(stack.top())) {
postfix_expr.push_back(stack.top());
stack.pop();
}
stack.push(token);
} else if(mean_of(token) == LEFT_PARENTHESIS) {
if(mean_of(next_symbol) == RIGHT_PARENTHESIS) { // a()
point_to_error(i,"Wrong parameter");
getch();
exit(1);
}
stack.push(token);
} else if(mean_of(token) == RIGHT_PARENTHESIS) {
if(i != expr.size()-1 && mean_of(next_symbol) != OPERATION &&
mean_of(next_symbol) != RIGHT_PARENTHESIS && mean_of(next_symbol) != RIGHT_BRACKET) { // sqrt(a)b
point_to_error(i,"Syntax error");
getch();
exit(1);
}
while(!stack.empty() && mean_of(stack.top()) != LEFT_PARENTHESIS) {
postfix_expr.push_back(stack.top());
stack.pop();
}
if(stack.empty()) { // a)
point_to_error(i,"Lost left parenthesis");
getch();
exit(1);
}
stack.pop();
if(!stack.empty() && mean_of(stack.top()) == FUNCTION) {
postfix_expr.push_back(stack.top());
stack.pop();
}
}
}
while(!stack.empty()) {
if(mean_of(stack.top()) == LEFT_PARENTHESIS) { // a(b
point_to_error(i,"Lost right parenthesis");
getch();
exit(1);
}
if(mean_of(stack.top()) == ARRAY) { // a[b
point_to_error(i,"Lost right bracket");
getch();
exit(1);
}
postfix_expr.push_back(stack.top());
stack.pop();
}
return postfix_expr;
}
double compute(deque<string> postfix_expr, map<string,double>& var, map<string,vector<double>>& arr) {
stack<double> stack;
for(int i=0;i<postfix_expr.size();i++) {
string token;
token = postfix_expr[i];
if(mean_of(token) == NUMBER) {
stack.push(atof(token.c_str()));
}
if(mean_of(token) == LETTER) {
if(var.find(token) == var.end()) {
print_error("Wrong variable name");
getch();
exit(1);
}
stack.push(var[token]);
} else if(mean_of(token) == OPERATION) {
double right = stack.top();
stack.pop();
double left = stack.top();
stack.pop();
double result = 0;
if(token=="+") result = left+right;
if(token=="-") result = left-right;
if(token=="/") {
if(right == 0) {
print_error("Division by zero");
getch();
exit(1);
}
result = left/right;
}
if(token=="*") result = left*right;
if(token=="^") result = pow(left,right);
stack.push(result);
} else if(mean_of(token) == FUNCTION) {
double arg = stack.top();
stack.pop();
double result = 0;
if(token=="sin") result = sin(arg);
if(token=="cos") result = cos(arg);
if(token=="asin") result = asin(arg);
if(token=="acos") result = acos(arg);
if(token=="tan") result = tan(arg);
if(token=="cot") result = 1/tan(arg);
if(token=="atan") result = atan(arg);
if(token=="acot") result = 1/atan(arg);
if(token=="exp") result = exp(arg);
if(token=="ln") {
if(arg==-1) {
print_error("Log of -1");
getch();
exit(1);
}
result = log(arg);
}
if(token=="sqrt") {
if(arg<0) {
print_error("Root of negative number");
getch();
exit(1);
}
result = sqrt(arg);
}
if(token=="sqrt3") result = sqrt3(arg);
stack.push(result);
} else if(mean_of(token) == ARRAY) {
double arg = stack.top();
stack.pop();
double result = 0;
string arr_name;
for(int i=0;token[i]!='[';i++) {
arr_name+=token[i];
}
if(arr.find(arr_name) == arr.end()) {
print_error("Wrong array name");
getch();
exit(1);
}
if(arg>=arr[arr_name].size() || arg<0) {
print_error("Out of range");
getch();
exit(1);
}
if(arg - (int)arg != 0) {
print_error("Wrong parameter of array");
getch();
exit(1);
}
result = arr[arr_name][arg];
stack.push(result);
}
}
return stack.top();
}
void print_postfix(deque<string>& postfix) {
for(auto it = postfix.begin(); it != postfix.end(); it++) {
cout<<*it<<" ";
}
}
int _tmain(int argc, _TCHAR* argv[])
{
ifstream expr_file("expression.txt");
string infix_expr;
getline(expr_file,infix_expr);
infix_expr.erase(remove_if(infix_expr.begin(), infix_expr.end(), isspace), infix_expr.end());
cout<<infix_expr<<" = ";
deque<string> postfix_expr = postfix(infix_expr);
print_postfix(postfix_expr);
cout<<endl;
map<string,double> var;
map<string,vector<double>> arr;
read_vars(expr_file,var,arr);
print_postfix(postfix_expr);
cout<<"= ";
double result = compute(postfix_expr, var, arr);
cout<<result<<endl;
expr_file.close();
getch();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment