Programm get string like:VARIABLE=EXPRESSION.
where VARIABLE is some letters and numbers, starting letter
and EXPRESSION is mathematical expression that can include:
1) + or *
2) ( or )
3) numbers (for example, 5; 3.8; 1e+18, 8.41E-10)
4) another names of variables.
I need to turn this into the tree (just in memory) using one regular exprassion.
How can i do this?
Was proposed method:
search for = out of ()
search for + out of ()
search for * out of ()
if somethig found - break expression in 2 parts, else we got number or variable.
Looks pretty simple, but i can't create this expressions.
I'm alse found how to put conditional operator into regular expression.
Mostly, i just need 3 regular exprassions for =, + and *.
Example:
http://i.stack.imgur.com/I8R12.png
As stated by n.m., regular expressions can't deal with nested parentheses. However there are simple alternatives that can parse nested parenthesis, such as recursive descent parsers.
Example:
enum TokenType
{
TTId,
TTNumber,
TTPlus,
TTMinus,
TTTimes,
TTDivide,
TTLParen,
TTRParen,
TTEndOfInput
};
TokenType token = TTEndOfInput;
string tokenValue;
int peekChar();
void nextChar();
void error(string msg); // doesn't return
Value *createConstant(string value);
Value *createReadVariable(string name);
Value *createAdd(Value *l, Value *r);
Value *createSubtract(Value *l, Value *r);
Value *createMultiply(Value *l, Value *r);
Value *createDivide(Value *l, Value *r);
Value *createNegate(Value *l, Value *r);
Value *expression();
void getToken()
{
token = TTEndOfInput;
tokenValue = "";
if(peekChar() == EOF)
return;
if(isalpha(peekChar()))
{
while(isalnum(peekChar()))
{
tokenValue += (char)peekChar();
nextChar();
}
token = TTId;
return;
}
if(isdigit(peekChar()) || peekChar() == '.')
{
while(isdigit(peekChar()))
{
tokenValue += (char)peekChar();
nextChar();
}
if(peekChar() == '.')
{
tokenValue += (char)peekChar();
nextChar();
while(isdigit(peekChar()))
{
tokenValue += (char)peekChar();
nextChar();
}
if(tokenValue == ".")
error("missing digit");
}
if(peekChar() == 'e')
{
tokenValue += (char)peekChar();
nextChar();
if(peekChar() == '+' || peekChar() == '-')
{
tokenValue += (char)peekChar();
nextChar();
}
if(!isdigit(peekChar()))
error("missing digit");
while(isdigit(peekChar()))
{
tokenValue += (char)peekChar();
nextChar();
}
}
token = TTNumber;
return;
}
switch(peekChar())
{
case '+':
token = TTPlus;
nextChar();
return;
case '-':
token = TTMinus;
nextChar();
return;
case '*':
token = TTTimes;
nextChar();
return;
case '/':
token = TTDivide;
nextChar();
return;
case '(':
token = TTLParen;
nextChar();
return;
case ')':
token = TTRParen;
nextChar();
return;
default:
error("invalid charater");
}
}
Value *topLevel()
{
Value *retval;
switch(token)
{
case TTId:
retval = createReadVariable(tokenValue);
getToken();
return retval;
case TTNumber:
retval = createConstant(tokenValue);
getToken();
return retval;
case TTLParen:
getToken();
retval = expression();
if(token != TTRParen)
error("expected )");
getToken();
return retval;
case TTMinus:
getToken();
return createNegate(topLevel());
default:
error("unexpected token");
}
}
Value *mulDiv()
{
Value *retval = topLevel();
while(token == TTTimes || token == TTDivide)
{
TokenType operation = token;
getToken();
Value *rhs = topLevel();
if(operation == TTTimes)
{
retval = createMultiply(retval, rhs);
}
else // operation == TTDivide
{
retval = createDivide(retval, rhs);
}
}
return retval;
}
Value *addSub()
{
Value *retval = mulDiv();
while(token == TTPlus || token == TTMinus)
{
TokenType operation = token;
getToken();
Value *rhs = mulDiv();
if(operation == TTPlus)
{
retval = createAdd(retval, rhs);
}
else // operation == TTMinus
{
retval = createSubtract(retval, rhs);
}
}
return retval;
}
Value *expression()
{
return addSub();
}
void error(string msg)
{
cerr << "error : " << msg << endl;
exit(1);
}
int main()
{
getToken();
Value *expressionTree = expression();
// ...
return 0;
}
Related
this is data structure (stack) question. in c++. (no use STL)
i want input Infix Formula file(txt, if there is not file, input is user's typing.)
and convert Postfix Formula, then caculate formula.
how can i input Postfix Formula in caculate fuction ?
i try make file and read file, but is not work. (i try change endl position(delete), also not work.)
ArrayStack.h
#include <iostream>
#include <cstdlib>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
inline void error(const char *message)
{
cout << message << endl;
exit(1);
}
const int MAX_STACK_SIZE = 20;
class ArrayStack
{
private:
int top;
int data[MAX_STACK_SIZE];
public:
ArrayStack()
{
top = -1;
}
~ArrayStack()
{
}
bool isEmpty()
{
return top == -1;
}
bool isFull()
{
return top == MAX_STACK_SIZE - 1;
}
void push(int e)
{
if (isFull())
error("스택 포화 에러");
data[++top] = e;
}
int pop()
{
if (isEmpty())
error("스택 공백 에러");
return data[top--];
}
int peek()
{
if (isEmpty())
error("스택 공백 에러");
return data[top];
}
void display()
{
printf("[스택 항목의 수 = %2d] ==> ", top + 1);
for (int i = 0; i < top; i++)
printf("<%2d>", data[i]);
printf("\n");
}
};
pg1_stack.cpp
#pragma warning(disable:4996)
#include "ArrayStack.h"
#include <string.h>
#include <fstream>
inline static int precedence(char op)
{
switch (op) {
case '(': case ')': return 0;
case '+': case '-': return 1;
case '*': case '/': return 2;
}
return -1;
}
void infixToPostfix(FILE *fp = stdin)
{
char c, op;
double val;
ArrayStack stack;
ofstream os;
os.open("stack_Data.txt");
while ((c = getc(fp)) != '\n')
{
if ('0' <= c && c <= '9')
{
ungetc(c, fp);
fscanf_s(fp, "%lf", &val);
printf("%4.1f ", val);
os << val;
}
else if (c == '(')
stack.push(c);
else if (c == ')')
{
while (!stack.isEmpty())
{
op = stack.pop();
if (op == '(') break;
else
printf("%c ", op);
os << op;
}
}
else if (c == '+' || c == '-' || c == '*' || c == '/')
{
while (!stack.isEmpty())
{
op = stack.peek();
if (precedence(c) <= precedence(op))
{
printf("%c ", op);
os << op;
stack.pop();
}
else break;
}
stack.push(c);
}
}
while (!stack.isEmpty()) {
char c2 = stack.pop();
os << c2;
printf("%c ", c2);
}os << endl;
os.close();
printf("\n");
}
double calcPostfixExpr(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (fp == NULL)
error("Error: 파일 존재하지 않습니다.\n");
char ch;
ArrayStack stack;
while ((ch = getc(fp)) != '\n')
{
if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
{
double right = stack.pop();
double left = stack.pop();
switch (ch) {
case '+':
stack.push(left + right);
break;
case '-':
stack.push(left - right);
break;
case '*':
stack.push(left * right);
break;
case '/':
stack.push(left / right);
break;
}
}
else if ('0' <= ch && ch <= '9')
{
ungetc(ch, fp);
double val;
fscanf_s(fp, "%lf", &val);
stack.push(val);
}
}
fclose(fp);
return stack.pop();
}
void main() {
infixToPostfix();
double res = calcPostfixExpr("stack_Data.txt");
printf("%f", res);
system("Pause");
}
this is before try make file and read file way
#pragma warning(disable:4996)
#include "ArrayStack.h"
#include <string.h>
#include <fstream>
inline static int precedence(char op)
{
switch (op) {
case '(': case ')': return 0;
case '+': case '-': return 1;
case '*': case '/': return 2;
}
return -1;
}
void infixToPostfix(FILE *fp = stdin)
{
char c, op;
double val;
ArrayStack stack;
while ((c = getc(fp)) != '\n')
{
if ('0' <= c && c <= '9')
{
ungetc(c, fp);
fscanf_s(fp, "%lf", &val);
printf("%4.1f ", val);
}
else if (c == '(')
stack.push(c);
else if (c == ')')
{
while (!stack.isEmpty())
{
op = stack.pop();
if (op == '(') break;
else
printf("%c ", op);
}
}
else if (c == '+' || c == '-' || c == '*' || c == '/')
{
while (!stack.isEmpty())
{
op = stack.peek();
if (precedence(c) <= precedence(op))
{
printf("%c ", op);
stack.pop();
}
else break;
}
stack.push(c);
}
}
while (!stack.isEmpty()) {
char c2 = stack.pop();
printf("%c ", c2);
}
printf("\n");
}
double calcPostfixExpr(FILE* fp = stdin)
{
char ch;
ArrayStack stack;
while ((ch = getc(fp)) != '\n')
{
if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
{
double right = stack.pop();
double left = stack.pop();
switch (ch) {
case '+':
stack.push(left + right);
break;
case '-':
stack.push(left - right);
break;
case '*':
stack.push(left * right);
break;
case '/':
stack.push(left / right);
break;
}
}
else if ('0' <= ch && ch <= '9')
{
ungetc(ch, fp);
double val;
fscanf_s(fp, "%lf", &val);
stack.push(val);
}
}
return stack.pop();
}
void main() {
infixToPostfix();
system("Pause");
}
I am very new to C++ and am attempting to create a simple calculator which follows mathematical conventions (BODMAS or PEMDAS). I made a function calculator, but then decided to go further and accept variables, at which point I kept receiving C2280 error.
The error is:
token_stream::token_stream(void): attempting to reference a deleted function
I simply dont understand what this means and have no idea what to do to fix it.
Here is the token_stream class:
class token_stream { //creates a stream of tokens
public:
Token get(); //call to get token function
void putback(Token t); //call to token putback function
void ignore(char a); // call to ignore bad tokens function
private:
bool full{ false }; //is there a token in the buffer?
Token buffer; //this is where putback token is stored
};
Here is the entire calculator code:
#include "../../std_lib_facilities.h"
//---------------------------------------------------------------------------------------------------
class Token //user defined type with two member functions
{
public:
char kind;
double value;
string name;
Token(char ch) : kind{ ch } {} //initialize kind with ch
Token(char ch, double val) : kind{ ch }, value{ val } {} //initialize kind and value
Token(char ch, string name) : kind{ ch }, name{ name } {} //initialize kind and name
};
class token_stream { //creates a stream of tokens
public:
Token get(); //call to get token function
void putback(Token t); //call to token putback function
void ignore(char a); // call to ignore bad tokens function
private:
bool full{ false }; //is there a token in the buffer?
Token buffer; //this is where putback token is stored
};
class Variable {
public:
string name;
double val;
};
//---------------------------------------------------------------------------------------------------
const char number = '8'; //t.kind==number means that t is a number token
const char quit = 'q'; //t.kind==quit means that t is a quit token
const char print = ';'; //t.kind==print means that t is a print token
const char name = 'a';
const char let = 'L';
const string declr_key = "let";
vector<Variable> var_table;
token_stream ts;
//---------------------------------------------------------------------------------------------------
void token_stream::putback(Token t) {
if (full) error("putback() is full"); //tests precondition to see if buffer is full
buffer = t;
full = true;
}
void token_stream::ignore(char c) {
if (full && c == buffer.kind) {
full = false;
return;
}
char ch{ 0 };
while (cin >> ch) {
if (c == ch)
return;
}
}
Token token_stream::get() { //creates a token from inputs
if (full) { //checks if we have a token ready
full = false;
return buffer;
}
char ch;
cin >> ch;
switch (ch) {
case print:
case quit:
case '(':
case ')':
case '+':
case '-':
case '*':
case '/':
case '%':
return Token{ ch }; break; //let each character represent itself
case '.': // floatng point literal can start with a dot
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
cin.putback(ch); //putback the digit into input stream
double val;
cin >> val; //read a floating point number
Token t{ number,val };
return t;
break;
}
default:
if (isalpha(ch)) {
string s;
s += ch;
while (cin.get(ch) && (isalpha(ch) || isdigit(ch))) s += ch;
cin.putback(ch);
if (s == declr_key) return Token{ let };
return Token{ name, s };
}
error("Error in Input: Token Invalid"); break;
}
}
double get_value(string s) { //gets the value for a given variable
for (int i = 0; i < var_table.size(); i++)
if (s == var_table[i].name) return var_table[i].val;
error("Undefined variable: ", s);
}
void set_value(string s,double d) { // sets the value for a pre-defined variable
for (int i = 0; i < var_table.size(); i++)
if (s == var_table[i].name) {
var_table[i].val = d;
return;
}
error("Undefined variable: ", s);
}
//---------------------------------------------------------------------------------------------------
double primary(); //declaration so that term can call primary()
double term() { //does multiplication, division, and modulo
double left = primary();
Token t = ts.get();
while (true)
{
switch (t.kind) {
case '*':
{
left *= primary();
t = ts.get();
break;
}
case '/': {
double d = primary();
if (d == 0) error("Divide by 0!"); //non-zero denom check
else {
left /= d;
t = ts.get();
}
break;
}
case '%': {
double d = primary();
if (d == 0)error("Divide by 0!"); //non-zero denom check
else {
left = fmod(left, d);
t = ts.get();
}
break;
}
default: ts.putback(t); //put back in token strem if none of the other options
return left; break;
}
}
}
double expression() { //handles +, -
double left = term();
Token t = ts.get();
while (true) {
switch (t.kind) {
case '+':
{
left += term();
t = ts.get();
break; }
case '-': {
left -= term();
t = ts.get();
break; }
default: ts.putback(t); //put back into token stream if none of the options above
return left;
break;
}
}
}
double primary() {
Token t = ts.get();
switch (t.kind) {
case '(':
{
double d = expression();
t = ts.get();
if (t.kind != ')') error("Expected a ')'");
return d;
break;
}
case number:
return t.value;
break;
case '-': //handles negative numbers
return - primary();
break;
case '+': //handles positive numbers which are preceded by '+'
return primary();
break;
default: error("primary expected: no value after operator given. check input");
}
}
void check_var(string name) {
for (int i = 0; i < var_table.size(); i++)
if (name == var_table[i].name)
error("Variable name already exists");
}
double define_name(string name, double num) {
check_var(name);
var_table.push_back(Variable{ name, num });
return num;
}
double declaration() {
// assume we have seen a 'let'
// handles: name=expression
// declare a variable called 'name' with value 'val'
Token t = ts.get();
if (t.kind != name) error("Expected a variable name"); //throws an error if no variable name given
string var_name = t.name;
t = ts.get();
if (t.kind != '=')error("No '=' sign present in declaration of ", var_name);
double d = expression();
define_name(var_name, d);
return d;
}
double statement() {
Token t = ts.get();
switch (t.kind) {
case let:
return declaration();
default:
ts.putback(t);
return expression();
}
}
void clean_up_mess() {
ts.ignore(print);
}
void calculate() { //expression evaluation loop
while (cin)
{
try {
Token t = ts.get();
if (t.kind == print) t = ts.get(); //first discard all 'prints'
if (t.kind == quit) {
return;
}
ts.putback(t);
cout << "Answer: " << statement() << "\n";
}
catch (exception&e) {
cout << "Error: " << e.what() << "\n";
clean_up_mess();
}
}
}
//---------------------------------------------------------------------------------------------------
int main()
{
try {
cout << "Enter an expression to solve: \n"; //user prompt
calculate();
keep_window_open();
}
catch(...) {
cout << "Error of Unknown origin.\n";
}
}
Any help is really appreciated!
As Token doesn't have a default constructor (a constructor which can be called without any parameters), and token_stream contains Token, the compiler cannot generate default constructor for token_stream.
Two possible solutions:
Add a default constructor to Token
Add a default constructor to token_stream, which initializes buffer to some value
I am a beginner using the stack so I been trying to do different exercises on it. I'm trying to convert infix->postfix. The xcode debugger says "Use of class template 'stack'requires template arguments'. Here is my code.
#include<iostream>
#include<stack>
#include<string>
using namespace std;
bool IsOperand(char ch)
{
if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
return true;
}
return false;
}
bool IsOperator(char C)
{
if (C == '+' || C == '-' || C == '*' || C == '/' || C == '^') {
return true;
}
return false;
}
bool IsLeftParenthesis(char ch)
{
if (ch == '(') {
return true;
}
return false;
}
bool IsRightParenthesis(char ch)
{
if (ch == ')') {
return true;
}
return false;
}
bool Flag(char ch)
{
if (!IsOperand(ch) || !IsOperator(ch) || !IsLeftParenthesis(ch) || !IsRightParenthesis(ch)) {
return false;
}
return true;
}
int IsRightAssociative(char op)
{
if (op == '^') {
return true;
}
return false;
}
int GetOperatorWeight(char op)
{
int weight = -1;
switch (op) {
case '+':
case '-':
weight = 1;
break;
case '*':
case '/':
weight = 2;
break;
case '^':
weight = 3;
break;
}
return weight;
}
bool HasHigherPrecedence(char op1, char op2)
{
int op1Weight = GetOperatorWeight(op1);
int op2Weight = GetOperatorWeight(op2);
// If operators have equal precedence, return true if they are left associative.
// BUT REMEMBER...return false, if right associative.
// if operator is left-associative, left one should be given priority.
if (op1Weight == op2Weight) {
if (IsRightAssociative(op1)) {
return false;
}
else {
return true;
}
}
return op1Weight > op2Weight ? true : false;
}
string InfixToPostfix(string expression)
{
stack S;
string postfix = "";
for (auto& elem : expression) {
if (Flag(elem)) {
continue;
}
// If character is operator, pop two elements from stack, perform operation and push the result back.
else if (IsOperator(elem)) {
while (!S.empty() && S.top() != '(' && HasHigherPrecedence(S.top(), elem)) {
postfix += S.top();
S.pop();
}
S.push(elem);
}
else if (IsOperand(elem)) {
postfix += elem;
}
else if (elem == '(') {
S.push(elem);
}
else if (elem == ')') {
while (!S.empty() && S.top() != '(') {
postfix += S.top();
S.pop();
}
S.pop();
}
}
while (!S.empty()) {
postfix += S.top();
S.pop();
}
return postfix;
}
int main()
{
// std::string expression = "54/(5^2)+(6^2^3)";
std::string expression = "A+(BC-(D/E^F)G)H";
std::string postfix = InfixToPostfix(expression);
std::cout << "Output = " << postfix << "\n";
}
Here specificially where the error is happening.
string InfixToPostfix(string expression)
{
stack S;
It says
Stack S -> Use of class template 'stack'requires template arguments'
Stack is a container, you need to specify the type of the container like:
stack <int> S;
or in you case it is stack of char:
stack <char> S;
We are required to parse out a given program code. Example of code:
procedure example1 {
x = 0;
z = y + x;
a =1;
while a{
x = z + x;
while x {
c = a + b;
}
}
}
What I have tried:
The example code is in a text file, so i open it and then i pass the info to a vector, after which, i get the tokens from the vector one by one and analyse it looking for the keyword. Currently, my code keeps displaying the error message in the Error method, and i can't see to understand why. This is a school assignment. My code is given below. Any and all help is appreciated.
vector<string> tokens;
SimpleParser::SimpleParser()
{
cout << "Please enter a file name: ";
cin >> userInput;
cout << "fILENAME: " + userInput;
openFile(userInput);
}
SimpleParser::~SimpleParser()
{
}
void SimpleParser::openFile(string fileName) {
ifstream myfile(fileName);
if (myfile.is_open())
{
while (getline(myfile, currLine))
{
size_t comments = currLine.find("//");
if (comments != string::npos)
{
currLine = currLine.erase(comments);
allLines += " " + currLine;
}
else {
allLines += " " + currLine;
}
}
myfile.close();
fillVector(allLines);
}
else
{
cout << "Unable to open file";
}
}
//check if line is proc, while,assign
void SimpleParser::fillVector(string line) {
istringstream iss(line);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter(tokens));
next_token = getToken();
procedure();
}
void SimpleParser::procedure() {
Match("procedure");
//string proc_name = next_token;
//Match(proc_name);
Match("{");
stmtLst();
Match("}");
}
void SimpleParser::stmtLst() {
cout << "All lines : "+ allLines;
}
void SimpleParser::Match(string token) {
if (next_token.compare(token) == 0) {
next_token = getToken();
}
else {
Error();
}
}
string SimpleParser::getToken() {
string t = "";
if (countOfVecs < tokens.size()) {
t = tokens[countOfVecs];
}
countOfVecs++;
return t;
}
void SimpleParser::Error() {
cout << "Error parsing!";
//exit(0);
}
void SimpleParser::Stmt() {
string var_name = next_token;
Match(var_name);
Match("=");
Match(next_token);
}
As I can see, the problem is related either to your get or your:
void SimpleParser::Match(string token) {
// compare token with next_token
if (next_token.compare(token) == 0){
// if they match assign next_token to the next token
next_token = getToken();
}else{
// if they don't compare equal throw an error
Error();
}
}
What exactly is the purpose of the above function?
In general there is no need to waste so much memory and read all the file, you can parse it word by word till you get the needed key word. Thus, here is a slightly different implementation of class that will actually parse without copying all the file contents.
class Token{
public:
// data members for the three types of tokens:
// algebraic operator, number, and user defined variable(name, value)
char kind;
double value;
string name;
// constructors for each of the three tokens
Token(char ch): kind(ch), value(0) { }
Token(char ch, double val) :kind(ch), value(val) { }
Token(char ch, string n) :kind(ch), name(n) { }
};
// class used as an input stream for tokens
class Token_stream {
public:
// constructor
Token_stream() :full(false), buffer(0) { }
// member functions
Token get();
private:
// data members defining the Token_stream buffer
bool full;
Token buffer;
};
const string firstKeyword = "key1";
// get function implementation
Token Token_stream::get(){
if (full) {
full=false;
return buffer;
}
char ch;
// to read from file change cin to the relevant input stream object
cin.get(ch);
switch (ch){
// if the token some of the above symbols: return it
case '(': case ')': case '+': case '-': case ',': case '!':
case '*': case '/': case '%': case 'Q': case '=':
return Token(ch);
// if the token a number int of float: return it as "number token"
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
cin.putback(ch);
double val;
cin >> val;
return Token(number,val);
}
case '\n': case '\r':
return Token(print);
default:
{
if (isspace(ch)) // skips whitespaces; taking up this funciton from the replaced 'cin'
{
while(isspace(ch)) cin.get(ch);
}
if (isalpha(ch) || ch == '_' || ch == '#') {
string s;
s += ch;
while(cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_' || ch == '#')) s += ch;
cin.putback(ch);
// if the token is some of the predefined "Keywords": return it as the respective token
if (s == firstKeyword) return Token(keyToken);
if (s == secondKeyword) return Token(sekondKeyToken);
if (s == thirdKeyword) return Token(thirdKeyToken);
return Token(name,s);
}
error("bad input token!", ch);
}
}
}
Problem Statement :
Write a C++ program to evaluate postfix expressions. Your program should take postfix expression as an input, process it with the help of stack and display the result after performing required calculations.
Only following Binary operators are allowed for this program:
+, -, *, /, ^ [addition, subtraction, multiplication, division, exponentiation]
If some error occurs while processing postfix expression, your program should display a meaningful message, like:
Error: Division by zero not allowed
Error: Two operands required for __ operator
Error: Invalid postfix expression
Help me with it, My program is generating errors This is my try:
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#define MAX_SIZE 20
using namespace std;
template<class T>
class Stack
{
private:
T item[MAX_SIZE];
int top;
public:
Stack()
{
top = -1;
}
void push(T data)
{
if(!this->is_full())
item[++top] = data;
else
{
cout<<"Stack Error"<<endl;
exit(10);
}
}
T pop()
{
if(!this->is_empty())
return item[top--];
else
{
cout<<"Stack is Empty"<<endl;
exit(11);
}
}
int size()
{
return top+1;
}
bool is_empty()
{
if(top==-1)
return true;
else
return false;
}
bool is_full()
{
if(top==MAX_SIZE-1)
return true;
else
return false;
}
void display()
{
for(int i=0; i<this->size(); i++)
{
cout<<item[i]<<" ";
}
cout<<endl;
}
T return_top()
{
return item[top];
}
};
class Convert
{
private:
bool num_flag;
bool tow_digit_flag;
public:
Convert();
string return_with_bracket(string infix);
void to_Postfix(string infix,char postfix[]);
bool prcd(char op1, char op2);
int isOperand(char op);
int isOperator(char op);
bool return_flag()
{
return num_flag;
}
};
Convert::Convert()
{
this->num_flag = false;
this->tow_digit_flag = false;
}
string Convert::return_with_bracket(string infix)
{
return("(" + infix + ")");
}
bool Convert::prcd(char op1, char op2)
{
if((op1=='+' || op1=='-' || op1=='*' || op1=='/') && op2=='(' )
return true;
if(op1=='+' && op2=='+')
return true;
if(op1=='-' && op2=='-')
return false;
if(op1=='-' && op2=='+')
return false;
if(op1=='+' && op2=='-')
return false;
if(op1=='/' && op2=='/')
return false;
if(op1=='/' && (op2=='-' || op2=='+'))
return true;
if(op1=='*' && (op2=='+' || op2=='-'))
return true;
if((op1 == '-' || op1 == '+') && (op2 =='*' || op2 == '/'))
return false;
if((op1=='$' || op1 == '+') && (op2 =='*' || op2 == '/' || op2=='-'))
return true;
if((op1 == '-' || op1 == '+' || op1 =='*' || op1 == '/')&& op2=='^')
return false;
if(op1 == '^' && ( op2 == '+' || op2 =='*' || op2 == '/' || op2=='-'))
return false;
}
int Convert::isOperand(char op)
{
return(op>= '0' && op <= '9');
}
int Convert::isOperator(char op)
{
return(op=='+' || op=='-' || op == '/' || op=='*' || op=='^');
}
void Convert::to_Postfix(string infix, char postfix[])
{
int position, outpos=0;
char c;
int count = 0;
char temp;
char stacktop ;
Stack<char> stack;
for(position = 0; (c = infix[position])!='\0'; position++)
{
if(this->isOperand)
{
postfix[outpos++] = c;
this->num_flag = true;
count++;
if(count>=2)
{
this->tow_digit_flag = true;
}
}
else if(this->isOperator©)
{
count = 0;
if(isOperator(infix[position]) && isOperator(infix[position+1]))
{
cout<<"\aMissing argument in between "<<infix[position]<<" and "<<infix[position+1]
<<" in column "<< position+1<<endl;
exit(9);
}
if(this->prcd(c, stacktop))
{
stacktop=stack.return_top();
stack.push©;
stacktop = c;
}
else
{
while(true)
{
temp = stack.pop();
postfix[outpos++] =temp;
stacktop = stack.return_top();
if(prcd(c, stacktop) || stacktop=='(')
break;
}
stack.push©;
stacktop = stack.return_top();
}
}
else if(c=='(')
{
count = 0;
stack.push©;
stacktop = stack.return_top();
}
else if(c==')')
{
count = 0;
while(1)
{
if(stack.size()==0)
{
cout<<"Warning!! Number of ')' is greater than '('" <<endl;
exit(2);
}
temp = stack.pop();
if(temp!='(')
{
postfix[outpos++] = temp;
}
else
{
break;
}
}
stacktop =stack.return_top();
}
else
{
cout<<"Invalid input";
exit(3);
}
if(infix[position]==')' && infix[position+1]=='(')
{
stack.push('*');
stacktop = stack.return_top();
}
}
if(stack.size()!=0)
{
cout<<"Warning!!Number of '(' is greater than ')'"<<endl;
// exit(6);
}
if(!this->return_flag())
{
cout<<"You must Enter Numeric value for calculation"<<endl;
cout<<"This program cannot perform operations on variables";
exit(5);
}
if(this->tow_digit_flag)
{
cout<<"Sory! Althoug u may have entered right string"<<endl;
cout<<"this program is only for single digit operation"<<endl;
exit(8);
}
postfix[outpos] = '\0';
}
class Evaluate
{
public:
double eval(char expr[], Convert &Wink;
double oper(int symb, double op1, double op2);
};
double Evaluate::oper(int symb, double op1, double op2)
{
switch(symb)
{
case '+':
return (op1 + op2);
case '-':
return (op1 - op2);
case '*':
return (op1 * op2);
case '/':
return (op1 / op2);
case '^':
return (pow(op1, op2));
}
}
double Evaluate::eval(char expr[],Convert &convert)
{
int c, position;
char temp1;
int count = 0;
double opnd1, opnd2, value;
Stack<double> stack;
for(position = 0; (c = expr[position])!='\0'; position++)
{
if(convert.isOperand©)
{
temp1 = double(c-'0');
stack.push(temp1);
}
else
{
opnd2 = stack.pop();
if(stack.size()==0)
{
cout<<"This program cannot process unary operation";
exit(1);
}
opnd1 = stack.pop();
value = oper(c, opnd1, opnd2);
stack.push(value);
}
}
if(stack.size()>=2)
{
cout<<"Sory! this program cannot calculate this"<<endl;
cout<<"Enter +, *, /, - or ^ between bracket"<<endl;
exit(4);
}
return (stack.pop());
}
int main()
{
Convert convert;
Evaluate evaluate;
string bracketted_infix;
char infix[50], postfix[50];
char choice;
while(1)
{
cout<<"Enter operation: ";
cin>>infix;
cout<<endl;
cout<<"Entered operation: "<<infix<<endl;
bracketted_infix = convert.return_with_bracket(infix);
convert.to_Postfix(bracketted_infix, postfix);
cout<<"Equivalent Postfix operation: "<<postfix<<endl;
cout<<"RESULT: ";
cout<<evaluate.eval(postfix, convert);
cout<<"\nCalculate another operation?(y/n) ";
cin>>choice;
cout<<endl;
if(choice=='n')
break;
}
return 0;
}
To get it actually compiling you need to fix two syntax errors;
On line 154 you are calling a method with no parameter,
but the only declaration of this method takes 1 parameter.
if (this->isOperand) {
I believe you may have meant:
if (this->isOperand(c)) {
Also on line 255 you have a missing bracket before the semicolon:
double eval(char expr[], Convert &Wink;
When I actually ran your code it failed at runtime, with VS2010 giving an error "string subscript out of range".
If you're not already, I would recommend using a good IDE (such as Visual C++) when developing; the syntax colouring and support for dynamic debugging (i.e. breakpoints and watches) would be very helpful to debug a program like this.
Here is the final solution
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#define MAX_SIZE 20
using namespace std;
template<class T>
class Stack
{
private:
T item[MAX_SIZE];
int top;
public:
Stack()
{
top = -1;
}
void push(T data)
{
if(!this->is_full())
item[++top] = data;
else
{
cout<<"Stack Error"<<endl;
exit(10);
}
}
T pop()
{
if(!this->is_empty())
return item[top--];
else
{
cout<<"Stack is Empty"<<endl;
exit(11);
}
}
int size()
{
return top+1;
}
bool is_empty()
{
if(top==-1)
return true;
else
return false;
}
bool is_full()
{
if(top==MAX_SIZE-1)
return true;
else
return false;
}
void display()
{
for(int i=0; i<this->size(); i++)
{
cout<<item[i]<<" ";
}
cout<<endl;
}
T return_top()
{
return item[top];
}
};
class Convert
{
private:
bool num_flag;
bool tow_digit_flag;
public:
Convert();
string return_with_bracket(string infix);
void to_Postfix(string infix,char postfix[]);
bool prcd(char op1, char op2);
int isOperand(char op);
int isOperator(char op);
bool return_flag()
{
return num_flag;
}
};
Convert::Convert()
{
this->num_flag = false;
this->tow_digit_flag = false;
}
string Convert::return_with_bracket(string infix)
{
return("(" + infix + ")");
}
bool Convert::prcd(char op1, char op2)
{
if((op1=='+' || op1=='-' || op1=='*' || op1=='/') && op2=='(' )
return true;
if(op1=='+' && op2=='+')
return true;
if(op1=='-' && op2=='-')
return false;
if(op1=='-' && op2=='+')
return false;
if(op1=='+' && op2=='-')
return false;
if(op1=='/' && op2=='/')
return false;
if(op1=='/' && (op2=='-' || op2=='+'))
return true;
if(op1=='*' && (op2=='+' || op2=='-'))
return true;
if((op1 == '-' || op1 == '+') && (op2 =='*' || op2 == '/'))
return false;
if((op1=='$' || op1 == '+') && (op2 =='*' || op2 == '/' || op2=='-'))
return true;
if((op1 == '-' || op1 == '+' || op1 =='*' || op1 == '/')&& op2=='^')
return false;
if(op1 == '^' && ( op2 == '+' || op2 =='*' || op2 == '/' || op2=='-'))
return false;
}
int Convert::isOperand(char op)
{
return(op>= '0' && op <= '9');
}
int Convert::isOperator(char op)
{
return(op=='+' || op=='-' || op == '/' || op=='*' || op=='^');
}
void Convert::to_Postfix(string infix, char postfix[])
{
int position, outpos=0;
char c;
int count = 0;
char temp;
char stacktop ;
Stack<char> stack;
for(position = 0; (c = infix[position])!='\0'; position++)
{
if (this->isOperand(c))
{
postfix[outpos++] = c;
this->num_flag = true;
count++;
if(count>=2)
{
this->tow_digit_flag = true;
}
}
else if(this->isOperator(c))
{
count = 0;
if(isOperator(infix[position]) && isOperator(infix[position+1]))
{
cout<<"\aMissing argument in between "<<infix[position]<<" and "<<infix[position+1]
<<" in column "<< position+1<<endl;
exit(9);
}
if(this->prcd(c, stacktop))
{
stacktop=stack.return_top();
stack.push(c);
stacktop = c;
}
else
{
while(true)
{
temp = stack.pop();
postfix[outpos++] =temp;
stacktop = stack.return_top();
if(prcd(c, stacktop) || stacktop=='(')
break;
}
stack.push(c);
stacktop = stack.return_top();
}
}
else if(c=='(')
{
count = 0;
stack.push(c);
stacktop = stack.return_top();
}
else if(c==')')
{
count = 0;
while(1)
{
if(stack.size()==0)
{
cout<<"Warning!! Number of ')' is greater than '('" <<endl;
exit(2);
}
temp = stack.pop();
if(temp!='(')
{
postfix[outpos++] = temp;
}
else
{
break;
}
}
stacktop =stack.return_top();
}
else
{
cout<<"Invalid input";
exit(3);
}
if(infix[position]==')' && infix[position+1]=='(')
{
stack.push('*');
stacktop = stack.return_top();
}
}
if(stack.size()!=0)
{
cout<<"Warning!!Number of '(' is greater than ')'"<<endl;
// exit(6);
}
if(!this->return_flag())
{
cout<<"You must Enter Numeric value for calculation"<<endl;
cout<<"This program cannot perform operations on variables";
exit(5);
}
if(this->tow_digit_flag)
{
cout<<"Sory! Althoug u may have entered right string"<<endl;
cout<<"this program is only for single digit operation"<<endl;
exit(8);
}
postfix[outpos] = '\0';
}
class Evaluate
{
public:
double eval(char expr[], Convert &Wink);
double oper(int symb, double op1, double op2);
};
double Evaluate::oper(int symb, double op1, double op2)
{
switch(symb)
{
case '+':
return (op1 + op2);
case '-':
return (op1 - op2);
case '*':
return (op1 * op2);
case '/':
return (op1 / op2);
case '^':
return (pow(op1, op2));
}
}
double Evaluate::eval(char expr[],Convert &convert)
{
int c, position;
char temp1;
int count = 0;
double opnd1, opnd2, value;
Stack<double> stack;
for(position = 0; (c = expr[position])!='\0'; position++)
{
if(convert.isOperand(c))
{
temp1 = char(c-'0');
stack.push(temp1);
}
else
{
opnd2 = stack.pop();
if(stack.size()==0)
{
cout<<"This program cannot process unary operation";
exit(1);
}
opnd1 = stack.pop();
value = oper(c, opnd1, opnd2);
stack.push(value);
}
}
if(stack.size()>=2)
{
cout<<"Sory! this program cannot calculate this"<<endl;
cout<<"Enter +, *, /, - or ^ between bracket"<<endl;
exit(4);
}
return (stack.pop());
}
int main()
{
Convert convert;
Evaluate evaluate;
string bracketted_infix;
char infix[50], postfix[50];
char choice;
while(1)
{
cout<<"Enter operation: ";
cin>>infix;
cout<<endl;
cout<<"Entered operation: "<<infix<<endl;
bracketted_infix = convert.return_with_bracket(infix);
convert.to_Postfix(bracketted_infix, postfix);
cout<<"Equivalent Postfix operation: "<<postfix<<endl;
cout<<"RESULT: ";
cout<<evaluate.eval(postfix, convert);
cout<<"\nCalculate another operation?(y/n) ";
cin>>choice;
cout<<endl;
if(choice=='n')
break;
}
return 0;
}