Created
November 29, 2014 12:00
-
-
Save anonymous/fa127b732f1abb883726 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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