The program analyzes the entered expression, converts it into reverse Polish notation and calculates the result.My program works correctly with expressions without brackets, but if I use an expression with brackets, I get an error: "Op" was nullptr. I have no idea why as my Stack "Op" must be initialized.(I marked where the error occurs in the code).
My code:
#include <iostream>
#include <string>
#include <iomanip>
struct Stack {
char info;
Stack* next;
} *begin;
int Prior(char);
Stack* InStack(Stack*, char);
Stack* OutStack(Stack*, char&);
double Result(char*);
double mas[201];
Stack* InStack(Stack* p, char in) {
Stack* t = new Stack;
t->info = in;
t->next = p;
return t;
}
Stack* OutStack(Stack* p, char& in) {
Stack* t = p;
in = p->info;
p = p->next;
delete t;
return p;
}
int Prior(char a) {
switch (a) {
case '^': return 4;
case '*': case '/': return 3;
case '-': case '+': return 2;
case '(': return 1;
}
return 0;
}
double Result(char* str) {
int i;
char ss, ss1, ss2, ssR = 'z' + 1;
double op1, op2, res = 0, mas[200];
std::cout << "Input data:" << std::endl;
for (i = 0; str[i] != '\0'; ++i)
{
ss = str[i];
if (ss >= 'a' && ss <= 'z')
{
std::cout << ss << " = ";
std::cin >> mas[int(ss)];
}
}
for (i = 0; str[i] != '\0'; ++i)
{
ss = str[i];
if (!(ss == '+' || ss == '-' || ss == '*' || ss == '/'))
{
begin = InStack(begin, ss);
}
else
{
begin = OutStack(begin, ss2);
begin = OutStack(begin, ss1);
op2 = mas[int(ss2)];
op1 = mas[int(ss1)];
switch (ss)
{
case'+':res = op1 + op2; break;
case'-':res = op1 - op2; break;
case'*':res = op1 * op2; break;
case'/':res = op1 / op2; break;
}
mas[int(ssR)] = res;
begin = InStack(begin, ssR);
ssR++;
}
}
return res;
}
int main()
{
Stack* t, * Op = NULL;
char a;
char In[81], Out[81];
int k = 0, l = 0;
std::cout << "Input form: " << std::endl;
std::cin >> In;
while (In[k] != '\0')
{
if (In[k] >= 'a' && In[k] <= 'z')
{
Out[l++] = In[k];
}
if (In[k] == '(')
{
Op == InStack(Op, In[k]);
}
if (In[k] == ')')
{
while ((Op->info) != '(') //ERROR HERE
{
Op = OutStack(Op, a);
if (!Op)
{
a = '\0';
}
Out[l++] = a;
}
t = Op;
Op = Op->next;
delete t;
}
if (In[k] == '+' || In[k] == '-' || In[k] == '*' || In[k] == '/')
{
while (Op != NULL && Prior(Op->info) >= Prior(In[k]))
{
Op = OutStack(Op, a);
Out[l++] = a;
}
Op = InStack(Op, In[k]);
}
k++;
}
while (Op != NULL)
{
Op = OutStack(Op, a);
Out[l++] = a;
}
Out[l] = '\0';
std::cout << "\nPolish: " << Out << std::endl;
std::cout << "\nRes = " << Result(Out) << std::endl;
}
Related
I am trying previous year's codejam question of round 1A
link to question
i have submitted this code(start reading from main method, for ease)-
#include <bits/stdc++.h>
using namespace std;
#define range(t) for (int i = 0; i < t; i++)
#define rangeG(i, t) for (i = 0; i < t; i++)
#define printVec(vec) \
for (auto c : vec) \
{ \
cout << c << endl; \
}
vector<string> separate(string s)
{
vector<string> result;
range(s.size())
{
if (s[i] == '*')
{
string temp = s.substr(0, i + 1);
if (temp.size() > 1)
{
result.push_back(temp);
}
s = s.substr(i, s.size());
i = 0;
}
else if (i == (s.size() - 1))
{
string temp = s.substr(0, i + 1);
result.push_back(temp);
s = s.substr(i, s.size());
}
}
return result;
}
void removeAsterisk(string &s)
{
s.erase(remove(s.begin(), s.end(), '*'), s.end());
}
bool setStart(string s, string &start)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), start.size()))
{
if (s[i] != start[i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= start.size())
{
start = s;
}
}
return possible;
}
bool setEnd(string s, string &end)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), end.size()))
{
if (s[s.size() - 1 - i] != end[end.size() - 1 - i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= end.size())
{
end = s;
}
}
return possible;
}
void solve()
{
int n;
cin >> n;
vector<string> allS;
bool possible = 1;
string start = "";
string end = "";
string middle = "";
string result = "";
while (n--)
{
string str;
cin >> str;
if (count(str.begin(), str.end(), '*') == 0)
{
result = str;
}
vector<string> temp = separate(str);
for (string s : temp)
{
if (s[0] != '*')
{
possible = setStart(s, start);
}
if (s[s.size() - 1] != '*')
{
possible = setEnd(s, end);
}
if (possible && count(s.begin(), s.end(), '*') == 0)
{
result = s;
break;
}
if (s[0] == '*' && s[s.size() - 1] == '*')
{
removeAsterisk(s);
middle += s;
}
}
}
if (possible)
{
if (result.size() == 0)
{
result = start + middle + end;
}
cout << result << "\n";
}
else
{
cout << "*\n";
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t = 0;
cin >> t;
range(t)
{
cout << "Case #" << i + 1 << ": ";
solve();
}
return 0;
}
it seems correct to me and i have tested many times for many examples, but it is losing in test set-1(exactly one * (asterisk) character and and always the first character of string). Can anyone tell what's wrong?
you can consider code of first ranked here (it has all solutions,check only for "pattern matching" task) for help. I know that the wrong answer is an edge case and if it passes test set 1 then it will pass others.
I'm not too sure if questions of this sort is allowed on stackoverflow but here it goes. I finished up this assignment to calculate reverse polish expressions with a small set of operators. All the tests passed and I have already submitted the assignment. I was wondering if you guys had any suggestions where I could improve on the code that could be applied to my future assignments/projects.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class TheStack
{
public:
void push(double d1);
double pop();
int getNodeTracker();
private:
struct Node
{
double data;
Node* next;
};
Node* bottom = NULL;
Node* top = NULL;
Node* newP = NULL;
int nodeTracker = 0;
};
void TheStack::push(double d1)
{
newP = new Node;
newP->data = d1;
newP->next = NULL;
if (bottom == NULL)
{
bottom = top = newP;
top->next = NULL;
}
else
{
newP->next = top;
top = newP;
}
nodeTracker += 1;
}
double TheStack::pop()
{
Node* tempP;
double tempD;
if (top == NULL)
{
cout << "The stack is empty." << endl;
}
else
{
tempP = top;
tempD = tempP->data;
top = top->next;
delete(tempP);
nodeTracker -= 1;
return(tempD);
}
}
int TheStack::getNodeTracker()
{
return nodeTracker;
}
bool isOperand(string s1);
bool isOperator(string s1);
double operate(string s1, double d1, double d2);
int processor(string str);
bool validString(string str);
int main()
{
// getting user input
string str;
getline(cin, str);
// input loop
while (str != "0")
{
processor(str);
cout << endl;
getline(cin, str);
}
// end program
return 0;
}
bool isOperand(string s1)
{
try
{
stod(s1);
}
catch (...)
{
return false;
}
return true;
}
bool isOperator(string s1)
{
string validOps[4] = { "+", "-", "*", "/" };
for (int i = 0; i < 4; i++)
{
if (s1 == validOps[i])
{
return true;
}
}
return false;
}
double operate(string s1, double d1, double d2)
{
char op = s1[0];
switch (op)
{
case '+':
return d1 + d2;
case '-':
return d1 - d2;
case '*':
return d1 * d2;
case '/':
return d1 / d2;
}
}
bool validString(string str)
{
for (int i = str.size()-1; i >= 0; i--)
{
if (str[i] == '=')
{
return true;
}
}
return false;
}
int processor(string str)
{
TheStack stacklist;
istringstream iss(str);
string streamVar;
iss >> streamVar;
// checks if expression has = sign
if (!validString(str))
{
cout << "Error: Please input valid expression." << endl;
return -1;
}
// builds and operates upon stack
while (streamVar != "=")
{
if (isOperand(streamVar))
{
stacklist.push(stod(streamVar));
}
else if (isOperator(streamVar))
{
if (stacklist.getNodeTracker() > 1)
{
double d2 = stacklist.pop();
double d1 = stacklist.pop();
if (streamVar == "/" && d2 == 0)
{
cout << "Error: Division by 0." << endl;
return -1;
}
double result = operate(streamVar, d1, d2);
stacklist.push(result);
}
else
{
cout << "Error: Too many operators." << endl;
return -1;
}
}
iss >> streamVar;
}
// operand error case
if (stacklist.getNodeTracker() > 1)
{
cout << "Error: Too many operands." << endl;
return -1;
}
// output
cout << stacklist.pop() << endl;
return 0;
}
I've got a few different functions that on their own work fine. Now I am trying to put them together into one file. My debugger is throwing segmentation faults in the infixToPostfix function.
When I watch the ns variable, it does not show anything getting assigned to it, but it prints out the postfix expression when I actually run the code. When ns passes into PostfixEvaulation, it runs to the top member function of TemplateStack and crashes with:
terminate called after throwing an instance of "std::string"
This only happens when I pass a string with an operator. When I pass a string of just numbers, everything runs fine,
but it still does not seem to call PostfixEvaluation.
#include <iostream>
#include <sstream>
#include <string>
#include <typeinfo>
using namespace std;
//Class Template Stack declaration
template <class T>
class TemplateStack {
public:
typedef T type;
TemplateStack()
{
max_size_ = 50;
TopOfStack = 0;
data_ = new T[max_size_];
} //Default Constructor taking no parameters
void push(T element)
{
if (TopOfStack == max_size_)
throw string("Stack's underlying storage is overflow");
TopOfStack++;
data_[TopOfStack] = element;
}
void pop() {
if (TopOfStack == -1)
throw string("Stack is empty");
TopOfStack--;
}
T top() {
if (TopOfStack == -1)
throw string("Stack is empty");
return data_[TopOfStack];
}
private:
int TopOfStack; //Generic data type for the top element of stack
size_t max_size_;
T* data_;
};
//Function to Evauluate the Postfix notation expresion
int PostfixEvaulation(string input){
//string input;
int operand1, operand2, result,number;
TemplateStack<char>operation;
stringstream temp;
int i=0;
while (i < input.length())
{
if (isdigit(input[i]))
{
operation.push(input[i]);
}
else
{
operand2 = operation.top();
temp << operation.top();
operation.pop();
operand1 = operation.top();
temp << operation.top();
operation.pop();
switch(operand1,operand2)
{
case '+': result=operand1 + operand2;
break;
case '-': result=operand1 - operand2;
break;
case '*': result=operand1 * operand2;
break;
case '/': result=operand1 / operand2;
break;
}
operation.push(result);
}
i++;
}
cout << "The result is: "<<temp.str()<<endl;
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
return 0;
}
//Function to return precedence of operators
int prec(char c)
{
if(c == '^')
return 3;
else if(c == '*' || c == '/')
return 2;
else if(c == '+' || c == '-')
return 1;
else
return -1;
}
//Function: Convert Infix to Postfix
void infixToPostfix(string s)
{
TemplateStack<char> st;
st.push('N');
int l = s.length();
string ns;
for (int i = 0; i < l; i++) {
// If the scanned character is an operand, add it to output string.
if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
ns += s[i];
}
// If the scanned character is an ‘(‘, push it to the stack.
else if (s[i] == '(') {
st.push('(');
}
// If the scanned character is an ‘)’, pop and to output string from the stack
// until an ‘(‘ is encountered.
else if (s[i] == ')') {
while (st.top() != 'N' && st.top() != '(') {
char c = st.top();
st.pop();
ns += c;
}
if (st.top() == '(') {
char c = st.top();
st.pop();
}
}
//If an operator is scanned
else {
while (st.top() != 'N' && prec(s[i]) <= prec(st.top())) {
char c = st.top();
st.pop();
ns += c;
}
st.push(s[i]);
}
}
//Pop all the remaining elements from the stack
while (st.top() != 'N') {
char c = st.top();
st.pop();
ns += c;
}
cout << "Here is the ns variable: "<< ns << endl;
PostfixEvaulation(ns);//Call the PostFixEvaluationFunction with the ns (postfix notation) variab
}
//Function: User inputs Expression
void GetInput(){
string input;
cout << "Enter Infix Expression: ";
getline(cin, input);
infixToPostfix(input);
}
int main()
{
GetInput();
}
I'm trying to transmission parameters onto my function to excute
Here's my stack.h file
#ifndef stackarray_h
#define stackarray_h
#include<iostream>
#include<string>
using namespace std;
const int MAX_SIZE = 100;
typedef string Type;
class Stack{
private:
Type item[MAX_SIZE];
int top;
public:
Stack();
bool isEmpty()const;
void push(Type value);
void pop();
Type getTop();
};
Stack::Stack(){
top = -1;
}
bool Stack::isEmpty()const{
if (top == -1)
return true;
else
return false;
}
void Stack::push(Type value){
item[++top] = value;
}
void Stack::pop(){
if (top != -1){
top = top - 1;
}
}
Type Stack::getTop(){
return item[top];
}
#endif
Here's my source.cpp file. My problem that i can't transmission parameters string into stack to my push function.
#include<iostream>
using namespace std;
#include<string>
#include<fstream>
#include"stack.h"
void readFile(char* file,string &str);
void convertFromInfixToPostfix(string &str);
int evaluatingPostfix(string str);
int convert(int value);
string convertToString(int value);
int main(){
string str;
readFile("Text.txt",str);
cout<<str<<endl;
convertFromInfixToPostfix(str);
cout << "Output: ";
cout << str << endl;
cout << "Result: ";
cout << evaluatingPostfix(str) << endl;
return 0;
}
void readFile(char* file,string &str){
ifstream read(file);
if (!read.is_open()){
cout << "Error!.File wasn't opened." << endl;
}
else
{
getline(read, str);
}
read.close();
}
void convertFromInfixToPostfix(string &str){
Stack _stack;
string output="";
int i = 0;
while (i < str.length()){
if (str[i] == '(' || str[i] == '+' || str[i] == '-'
|| str[i] == '*' || str[i] == '/' || str[i] == '%'){
_stack.push(str[i]);
}
else {
//excute character )
if (str[i] == ')'){
while (!_stack.isEmpty()){
char top = _stack.getTop();
output += top;
_stack.pop();
}
}else
//excute character digit
output = output + str[i];
}
// excute end of string
if (_stack.getTop() == '('){
_stack.pop();
}
i++;
}
str = output;
}
int evaluatingPostfix(string str){
int result;
Stack _stack;
int op1, op2;
int i = 0;
int index;
string temp;
char next_ch;
while (i < str.length()){
next_ch = str[i];
if (next_ch == '+' || next_ch == '-'
|| next_ch == '*' || next_ch == '/'
){
//excute operator
op1 = _stack.getTop();
_stack.pop();
// convert op1 to integer
op1 = convert(op1);
op2 = _stack.getTop();
_stack.pop();
// convert op2 to integer
op2 = convert(op2);
if (next_ch == '+'){
index = op2 + op1;
// convert index from integer to char
temp = convertToString(index);
_stack.push(temp);
}
if (next_ch == '-'){
index = op2 - op1;
// convert index from integer to char
temp = convertToString(index);
_stack.push(temp);
}
if (next_ch == '*'){
index = op2 * op1;
// convert index from integer to char
temp = convertToString(index);
_stack.push(temp);
}
if (next_ch == '/'){
index = op2 / op1;
// convert index from integer to char
temp = convertToString(index);
_stack.push(temp);
}
}
else {
// excute integer
_stack.push(next_ch);
}
i++;
}
// push the result onto the _stack
result = _stack.getTop();
// _stack is empty
_stack.pop();
return result;
}
int convert(int value){
int result;
result = value - 48;
return result;
}
string convertToString(int value){
string result ;
int n = value;
do{
n = n % 10;
result = result + (char)(n + 48);
} while (n>0);
return result;
}
There are error:
Error 4 error C2664: 'void Stack::push(stackItemType)' : cannot
convert argument 1 from 'std::string' to 'stackItemType'
At line _stack.push(temp);
I'm sorry because my english isn't good.
I'm pretty green at C++, and I have to make an infix to postfix calculator that supports sin() and cos(), and it has to be a 2 variable function, something like z=3x*sin(3+4y), I already got the parser from infix to postfix, but I don't know how to implement sin and cos, I've been told that I could set them as operator, like +, -, /, etc. and to set a specific token for them, like "s" for sin() and "c" for cos() but I don't exactly know how, and I don't know either how to implement the variables x & y, I know that this is not something I should be asking, but I'm just tired and desperate.
Here's the code I have. I'm using Ubuntu 11:
#include <iostream>
#include <cmath>
#include <cstdlib>
#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 two_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->two_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->two_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->two_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 &);
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 = 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 string: ";
cin >> infix;
cout << endl;
cout << "Entered String: " << infix << endl;
bracketted_infix = convert.return_with_bracket(infix);
convert.to_Postfix(bracketted_infix, postfix);
cout << "Equivalent Postfix string: " << postfix << endl;
cout << "RESULT: ";
cout << evaluate.eval(postfix, convert);
cout << "\nCalculate another string?(y/n) ";
cin >> choice;
cout << endl;
if(choice == 'n')
break;
}
return 0;
}