I am building a program in OOP C++ that will convert an Infix to Postfix expression using predefined Stackitem and Stack classes ( these two classes work fine). But I have some problems in the implementation of conversion algorithm. I cannot get the expected output for some inputs.
I have tried to implement the following algorithm:
Basic steps, while parsing the infix expression:
if the item is an operand, output immediately
if the item is a left parenthesis, push onto the stack
if the item is a right parenthesis pop the stack and output the contents until a left parenthesis (parenthesis is popped but not output)
if the item is an operator, pop and output all the operators with higher or equal precendence, then push the item onto the stack
just push the item onto the stack, if the stack is empty or the top element is a left parenthesis or if the top element has a lower precendence.
Stackitem class implementation which helps in decesiding wheather the item is operator, operand, and its precedence (by giving an integer)
#include "StackItem.h"
StackItem::StackItem(bool isOp, int i) {
init(isOp, i);
next = 0;
}
StackItem::StackItem(string item) {
if(item.compare("+") == 0)
init(true, OPERATOR_PLUS);
else if(item.compare("-") == 0)
init(true, OPERATOR_MINUS);
else if(item.compare("*") == 0)
init(true, OPERATOR_MULTIPLICATION);
else if(item.compare("/") == 0)
init(true, OPERATOR_DIVISION);
else if(item.compare("(") == 0)
init(true, OPERATOR_LEFTPAR);
else if(item.compare(")") == 0)
init(true, OPERATOR_RIGHTPAR);
else
init(false, atoi(item.c_str()));
}
void StackItem::init(bool isOp, int i) {
isOperator = isOp;
if(isOp)
op = i;
else
n = i;
}
string StackItem::toString() {
stringstream ss;
if(!isOperator) {
ss << n;
} else {
switch(op) {
case OPERATOR_MINUS:
ss << "-";
break;
case OPERATOR_PLUS:
ss << "+";
break;
case OPERATOR_DIVISION:
ss << "/";
break;
case OPERATOR_MULTIPLICATION:
ss << "*";
break;
case OPERATOR_LEFTPAR:
ss << "(";
break;
case OPERATOR_RIGHTPAR:
ss << ")";
break;
}
}
return ss.str();
}
And here is the problematic code ( for conversion ). I am suspecting that the problem is with my ( fifth and sixth point of the algorithm steps)
#include "Calculator.h"
#include <iostream>
Calculator::Calculator( string expression ) {
infixExpression = expression;
stack = new Stack();
istringstream iss( expression );
string token;
iss >> token;
postfixExpression = "";
while ( token.compare( ";" ) != 0 ) {
cout << "token:" << token << endl;
StackItem *item = new StackItem( token );
if ( !item->isOperator ) {
postfixExpression += item->toString() + " ";
} else {
if ( item->op == OPERATOR_LEFTPAR )
stack->push( item );
else if ( item->op == OPERATOR_RIGHTPAR ) {
while ( !stack->isEmpty() && stack->top() != OPERATOR_LEFTPAR ) {
string s = stack->top()->toString();
delete stack->pop();
postfixExpression += s + " ";
}
string s = stack->top()->toString();
delete stack->pop();
} else {
while ( !stack->isEmpty() && ( item->op <= stack->top()->op ) ) {
if ( stack->top()->isOperator ) {
string s = stack->top()->toString();
delete stack->pop();
postfixExpression += s + " ";
}
break;
}
while ( ( stack->isEmpty() ) || ( stack->top()->op == OPERATOR_LEFTPAR ) || ( stack->top()->op < item->op ) ) {
stack->push( item );
}
}
}
iss >> token;
}
while ( !stack->isEmpty() ) {
string s = stack->top()->toString();
delete stack->pop();
postfixExpression += s + " ";
}
postfixExpression += ";";
}
string Calculator::getPostfix() {
return postfixExpression;
}
The required inputs and outputs has to be parsed according to ";" at the end and a white space has to be left between each input and output part.
Example:
Input: 1 + 2 + 3 ;
Output: 1 2 + 3 + ; ( this works fine)
However,
Input : ( 1 + 2 ) ;
Output : Nothing ( it gives return some memory address)
Also for:
Input : 10 + 10 * 40 - 45 / 5 ;
Output : 10 10 4 * 45 5 / + ;
Which is a wrong order!
Edit: The operator defines are as follows:
#define OPERATOR_LEFTPAR 0
#define OPERATOR_RIGHTPAR 1
#define OPERATOR_MINUS 2
#define OPERATOR_PLUS 3
#define OPERATOR_DIVISION 4
#define OPERATOR_MULTIPLICATION 5
Edit: This new code solved many problems with basic and short inputs, still very large and complicated expressions crash in the output.
#include "Calculator.h"
#include <iostream>
Calculator::Calculator(string expression)
{
infixExpression=expression;
stack = new Stack();
istringstream iss(expression);
string token;
iss >> token;
postfixExpression="";
while(token.compare(";") != 0)
{
//cout << "token:"<<token << endl;
StackItem* item=new StackItem(token);
if(!item->isOperator){
postfixExpression += item->toString() + " ";
}
else
{
if(item->op == OPERATOR_LEFTPAR)
stack->push(item);
else if(item->op == OPERATOR_RIGHTPAR)
{
while(!stack->isEmpty()&& stack->top()->op != OPERATOR_LEFTPAR)
{
string s = stack->top()->toString();
delete stack->pop();
postfixExpression +=s+" ";
}
string s = stack->top()->toString();
delete stack->pop();
}
else
{
while((!stack->isEmpty()) && item->op <= stack->top()->op)
{
string s = stack->top()->toString();
delete stack->pop();
postfixExpression +=s+" ";
}
while((stack->isEmpty()) || item->op > stack->top()->op || stack->top()->op==OPERATOR_LEFTPAR)
{
stack->push(item);
}
}
}
iss >> token;
}
while(!stack->isEmpty())
{
string s = stack->top()->toString();
delete stack->pop();
postfixExpression +=s+" ";
}
postfixExpression += ";";
}
string Calculator::getPostfix()
{
return postfixExpression;
}
Related
I am solving a question in which I have to check if the input string of parentheses are balanced or not,
and if not, code is expected to return the 1-based index of unmatched closing parenthesis, and if not found, return the 1-based index of the opening parenthesis. My code runs fine if I implement only the parenthesis checking part, but as I try to implement the returning index part, the code starts giving 'success' output for all the input.
Here is the code:
#include<iostream>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
int process_input( string value );
bool closing_bracket_match(char opening_bracket, char closing_bracket);
bool closing_bracket_match(char opening_bracket , char closing_bracket){
if( (opening_bracket == '{' && closing_bracket == '}') || (opening_bracket == '(' && closing_bracket == ')') || (opening_bracket == '[' &&
closing_bracket == ']') ){
return true;
}
else{
return false;
}
}
int process_input( string value ){
stack<char> processed_input{};
int unmatched_index{};
for( size_t i{}; i< value.size() ; ++i ){
if( value.at(i) == '{' || value.at(i) == '(' || value.at(i) == '[' ){ // check for opening brackets
processed_input.push(value.at(i)); // Appending opening bracket into the stack
}
else if( (value.at(i) == '}' || value.at(i) == ')' || value.at(i) == ']') && (processed_input.empty() == false) &&
closing_bracket_match(processed_input.top(),value.at(i)) ){ // the bracket in stack would be popped
processed_input.pop(); // matching brackets ar removed
}
}
if( processed_input.empty()==true ){
return 0;
}//This part is causing the bug
if(processed_input.empty() == false){
auto it = find( value.begin(), value.end(), processed_input.top() );
if( it!= value.end() ){
unmatched_index = distance(value.begin() , it)+1; //returning the 1 -based index of unmatched bracket
}
return unmatched_index;
}
}
int main(){
string input{};
cout<<"Please enter the code here: "; // debug line
cin>> input;
int result{};
result = process_input(input);
if( result == 0 ){
cout<<"Success";
}
else{
cout<<result;
}
}
If you want to return a position of the last (innermost) unmatched paren, you need to store it together with its position on the stack. Seeking for it leads to errors.
Which of potentially several items equal to the one you seek will find() find?
For example, in "(((" there are three unmatched opening parentheses, and all of them are equal to '('. Which one do you want to return as a result? Which one do you actually return?
And how about this input: "()("...?
Added
Here is a possible solution. Please note how it does not find() anything, but it stores on a stack all information necessary to produce the desired output.
#include<iostream>
#include<string>
#include<stack>
using std::string;
using std::stack;
bool is_opening(char c) {
return c == '(' || c == '[' || c == '{';
}
bool is_closing(char c) {
return c == ')' || c == ']' || c == '}';
}
bool is_matching(char opn, char cls) {
switch(opn) {
case '(': return cls == ')';
case '[': return cls == ']';
case '{': return cls == '}';
}
return false;
}
int process_input( string value )
{
stack<char> opn_parens{};
stack<size_t> positions{};
for( size_t i{}; i < value.size() ; ++i )
{
const char ch = value.at(i);
if( is_opening(ch) )
{
opn_parens.push(ch);
positions.push(i);
}
else if( is_closing(ch) )
{
if( opn_parens.empty() ) // a closing paren with no unmatched opening one
return i + 1;
const char opn_ch = opn_parens.top();
const size_t opn_pos = positions.top();
if( ! is_matching(opn_ch, ch) ) // unmatched closing paren
return opn_pos + 1;
opn_parens.pop(); // remove a matched paren
positions.pop();
}
}
if( ! positions.empty() ) // some unmatched parens remain
return positions.top() + 1;
return 0;
}
int main(){
std::cout << process_input("hello(mum[]{(dad()[bro!])})") << std::endl;
std::cout << process_input("))") << std::endl;
std::cout << process_input("([") << std::endl;
std::cout << process_input("([)") << std::endl;
std::cout << process_input("([{") << std::endl;
}
You can see it working at https://godbolt.org/z/e8fYW5fKz
I have a QTableWidget where the user inputs complex numbers in various styles.
For example, the complex number (-15 + 8.14i) can be written like:
-15 + 8.14i
-15+8.14j
-15 +j 8,14
-15+ i8,14
i can also be j!
Both values can be big (they are saved as double) and also negative. They can be written with "," and "." (so 3.14 and 3,14 are ment to be equal). There should be an error message when the user enters the number incorrectly.
CKomplex fromString(QString str) { // ckomplex is my custom class for complex numbers
double numReal, numImag;
QString strNew = "";
// delete all spaces
for (int i= 0; i< str.length(); i++) {
if (!str[i].isSpace()) {
strNew += str[i];
}
}
QString part1 = "";
int index;
// get the first number
for (int i= 0; i < strNew.length(); i++) { // iterate string
if (strNew[i] != '+' && strNew[i] != '-') {
part1 += strNew[i];
} else { // e.g.: 5 + 3j -> the loop is at the "+"
if (i != 0) {
index = i; // save index at "+" to start for next number
break;
}
}
}
numReal = part1.toDouble();
QString part2 = "";
// get the second number
for (int i= index; i < strNew.length(); i++) {
if (strNew[i].isDigit() || strNew[i] == '+' || strNew[i] == '-' || strNew[i] == '.' || strNew[i] == ',') { // ignore j or i
part2 += strNew[i];
}
}
numImag = part2.toDouble();
return CKomplex(numReal, numImag);
}
This does work for basic input. But is not very fast or readable or useful. And it does cover just few possibilities of input (stuff like "-3 - 5,14" doesnt work). Is there an easier way to convert the string into a complex number without having so much loops and variables?
A single regular expression could parse each of the lines:
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <regex>
#include <iostream>
#include <iomanip>
#include <exception>
class CKomplex {
public:
CKomplex(double numReal, double numImag) : numReal{numReal}, numImag{numImag} {}
double numReal;
double numImag;
};
auto input_text{
R"(-15 + 8.14i
-15+8.14j
-15 +j 8,14
-15+ i8,14
bad line here
+23.4-j24
-35+42.3j
+24i
+2.342j
+24.523-i 432,52
24.523-i 432,52
23.4-j24
35+42.3j
24i
2.342j)"};
CKomplex fromString(std::string str) {
double numReal{};
double numImag{};
std::regex r{R"(([+-]?) *([ij]?) *(\d+)[.,]?(\d*)([ij])?)"}; // 6 groups
std::istringstream iss(str);
auto it = std::sregex_iterator(str.begin(), str.end(), r);
auto end = std::sregex_iterator();
if(it == end || it->size() != 6)
throw std::runtime_error("Could not parse line containing the following text: " + str);
for(; it != end; ++it) {
auto match = *it;
auto sign = match[1].str();
auto iorj_pre = match[2].str();
auto decimal = match[3].str();
auto fraction = match[4].str();
auto iorj_post = match[5].str();
double val{sign == "-" ? -1.F : 1.F};
val *= std::stod(decimal + "." + fraction);
if(iorj_pre == "i" || iorj_pre == "j" || iorj_post == "i" || iorj_post == "j")
numImag += val;
else
numReal += val;
}
return{numReal,numImag};
}
std::ostream& operator<<(std::ostream& os, const CKomplex& complex_number)
{
os << std::showpos << "(" << complex_number.numReal << " " << complex_number.numImag << "i)";
return os;
}
int main()
{
std::istringstream input_stream{input_text};
for(std::string line{}; std::getline(input_stream, line);) {
try { std::cout << std::setw(20) << line << ": " << fromString(line) << '\n'; }
catch(std::exception& e) { std::cout << e.what() << '\n'; }
}
return 0;
}
Produces (live demo):
-15 + 8.14i: (-15 +8.14i)
-15+8.14j: (-15 +8.14i)
-15 +j 8,14: (-15 +8.14i)
-15+ i8,14: (-15 +8.14i)
Could not parse line containing the following text: bad line here
+23.4-j24: (+23.4 -24i)
-35+42.3j: (-35 +42.3i)
+24i: (+0 +24i)
+2.342j: (+0 +2.342i)
+24.523-i 432,52: (+24.523 -432.52i)
24.523-i 432,52: (+24.523 -432.52i)
23.4-j24: (+23.4 -24i)
35+42.3j: (+35 +42.3i)
24i: (+0 +24i)
2.342j: (+0 +2.342i)
Hello I have written a postfix calculator using vectors (which is required) and have run into trouble. When I enter two operands in a row, it won't give the correct answer. For example, "5 4 + 3 10 * +" gives the answer "36" when it should give 39. I understand why it isn't working I just can't think of a way to do it where it handles that case. Can someone give me a hand?
Code:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
//splits the string into different parts seperated by space and stores in tokens
void SplitString(string s, char delim, vector<string> &tokens)
{
stringstream ss;
ss.str(s);
string item;
while(getline(ss, item, delim))
{
tokens.push_back(item);
}
}
//preforms the operation denoted by the operand
void operation(string operand, vector<int> &eqVec)
{
int temp1 = eqVec.at(0);
int temp2 = eqVec.at(1);
if(operand == "+")
{
eqVec.push_back(temp1 + temp2);
}
else if(operand == "-")
{
eqVec.push_back(temp1 - temp2);
}
else if(operand == "*")
{
eqVec.push_back(temp1 * temp2);
}
else if(operand == "/")
{
eqVec.push_back(temp1 / temp2);
}
}
int main()
{
const char DELIM = ' ';
int total;
string eq;
vector <int> eqVec;
vector<string> tokens;
cout<<"Welcome to the postfix calculator! " << endl;
cout<<"Please enter your equation: ";
//gets the input and splits into tokens
getline(cin, eq);
SplitString(eq, DELIM, tokens);
//cycles through tokens
for(int i = 0; i < tokens.size(); ++i)
{
//calls operation when an operand is encountered
if(tokens.at(i) == "+" || tokens.at(i) == "-" || tokens.at(i) == "*" || tokens.at(i) == "/")
{
operation(tokens.at(i), eqVec);
}
//otherwise, stores the number into next slot of eqVec
else
{
//turns tokens into an int to put in eqVec
int temp = stoi(tokens.at(i));
eqVec.push_back(temp);
}
}
//prints out only remaining variable in eqVec, the total
cout<<"The answer is: " << eqVec.at(0) << endl;
return 0;
}
After taking a break and coming back I found a way to solve it. Posting here in case anyone in the future has the same problem. The following block of code is now at the beginning of the operation function before the series of if statements.
int temp1, temp2;
int size = eqVec.size();
if(size > 2)
{
temp1 = eqVec.at(size - 1);
temp2 = eqVec.at(size - 2);
eqVec.pop_back();
eqVec.pop_back();
}
else
{
temp1 = eqVec.at(0);
temp2 = eqVec.at(1);
eqVec.pop_back();
eqVec.pop_back();
}
novice coder here and I've been asking around how I should go about creating a two stack algorithm for calculating simple expressions (Dijkstra's Two Stack Algorithm) in C++. A quick refresher for anybody that need it:
Two Stack Algorithm:
Value - Push onto value stack
Operator - Push onto operator stack
Left Parenthesis - Ignore
Right Parenthesis - Pop two values from value stack and one value from operator stack and push the result
It appears that using istringstream, which was recommended to me, should allow me to separate the user inputted expression into basic, doubles, and non-doubles. This should allow me to populate my vals and ops stack respectively, however upon debugging, I realized that my vals stack ended up empty at the end (causing a segmentation fault)
I've got no idea what I'm doing wrong, and any help would be appreciated! Keep in mind I am relatively new to coding and my syntax is probably horrible, therefore any type of criticism is welcome.
For reference an input of:
( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )
Should output:
101
Thus far my code looks like this:
stack<string> ops;
stack<double> vals;
string input;
getline(cin, input);
istringstream scanner(input);
while(true){
double num;
scanner >> num;
if(scanner.fail() && scanner.eof()) break;
else if(!scanner.fail()) vals.push(num);
else{
scanner.clear();
string token;
scanner >> token;
if(token == "(") ;
else if(token == "+") ops.push(token);
else if(token == "*") ops.push(token);
/*Add more operations here (Log, sin, cos...)*/
else if(token == ")"){
string op = ops.top();
ops.pop();
if(op == "+"){
double a, b;
a = vals.top();
vals.pop();
b = vals.top();
vals.pop();
vals.push(a+b);
}
else if(op == "*"){
double a, b;
a = vals.top();
vals.pop();
b = vals.top();
vals.pop();
vals.push(a*b);
}
/*Add more operations here*/
}
}
return vals.top();
}
Thank you for your help!
Turns out the problem was with this:
scanner >> num;
if (scanner.fail() && scanner.eof()) break;
else if (!scanner.fail()) vals.push(num);
Changing it to the following fixed the problem:
if (scanner >> num) vals.push(num);
if (scanner.fail() && scanner.eof()) break;
else {
// ...
}
And putting the return statement below the loop also helped.
Live example
Not a straightforward answer to what you asked, but I reworked your example with out the use of stringstreams, which might be confusing to you. You can use the following code as an alternative:
#include <iostream>
#include <string>
#include <stack>
#include <ctype.h>
double parseExpression(std::string const &expr)
{
std::stack<char> ops;
std::stack<double> vals;
std::string num;
for (auto c : expr) {
if (c == '+' || c == '*') {
if(!num.empty()) vals.push(std::stod(num));
num.clear();
ops.push(c);
} else if (c == ')') {
if (!num.empty()) vals.push(std::stod(num));
num.clear();
char op = ops.top();
ops.pop();
switch (op) {
case '+': {
double tmp = vals.top();
vals.pop();
tmp += vals.top();
vals.pop();
vals.push(tmp);
} break;
case '*': {
double tmp = vals.top();
vals.pop();
tmp *= vals.top();
vals.pop();
vals.push(tmp);
} break;
};
num.clear();
} else if(isdigit(c) || c == '.') {
num.push_back(c);
} else if (isspace(c)) {
if (!num.empty()) vals.push(std::stod(num));
num.clear();
} else if(c != '(') {
throw std::runtime_error("Unknown character in expression!");
}
}
return vals.top();
}
int main()
{
std::string expr("( 1.00 + ( ( 2.000000 + 3.00 ) * ( 4.00 * 5.00 ) ) )");
std::cout << expr << " = " << parseExpression(expr) << std::endl;
return 0;
}
HTH
I have found conversion from infix to prefix and am trying to follow it but am having trouble. I have most of it, but am having trouble comparing operator hierarchy. Example compare \ to *. * get has higher hierarchy. Here is the code. I put ?? around the part I am having trouble with. The language I am using is c++.
string s;
stack<char>operatorStack;
stack<char>operandStack;
char rightOperand;
char leftOperandd;
char operand;
char opera
s = "1 + 2 * ( 1 - 2 - 3 - 4 ) ";
for (int i=0; i<s.length(); i++) {
if (s[i]!=' ') {
int arr= s[i];
cout << arr<<" ";
if (arr>=48) {
operandStack.push(s[i]);
}else {
if (s[i]=='(' || operatorStack.empty()||??(OperatorHierarchy(token) > OperatorHierarchy(OperatorStack.Top()) )??
operandStack.push(s[i]);
else if(s[i]==')'){
while (operandStack.top()!='(') {
opera=operatorStack.top();
operatorStack.pop();
rightOperand=operandStack.top();
operandStack.pop();
leftOperandd=operandStack.top();
operandStack.pop();
operand=opera+rightOperand+leftOperandd;
operandStack.push(operand);
}
operatorStack.pop();
}else if (?? operator hierarchy of token is less than or equal to hierarchy of top of the operator stack ??) {
while (!operatorStack.empty() && ??OperatorHierarchy(token) lessThen Or Equal to OperatorHierarchy(OperatorStack.Top()) ) ?? ) {
opera=operatorStack.top();
operatorStack.pop();
rightOperand=operandStack.top();
operandStack.pop();
leftOperandd=operandStack.top();
operandStack.pop();
operand=opera+rightOperand+leftOperandd;
operandStack.push(operand);
}
operatorStack.push(s[i]);
}
}
}
}
while (!operatorStack.empty()) {
opera=operatorStack.top();
operatorStack.pop();
rightOperand=operandStack.top();
operandStack.pop();
leftOperandd=operandStack.top();
operandStack.pop();
operand=opera+rightOperand+leftOperandd;
operandStack.push(operand);
}
cout << operatorStack.top();
operatorStack.pop();
return 0;
}