convert infix to postfix and then solve the equation - c++

So, I'm having issues with this program. Can anyone tell me what I'm doing wrong here? The program is supposed to take a simple infix notation mathematical expression (e.g. "5 - 2 + 1") and then convert it to (e.g. "5 2 - 1 +") and then solve it which would be 4. It converts just fine but as soon as it gets into the evaluating part, it doesn't show anything on the command prompt. Can I get some help? Thanks!
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
int priority(string item) //prioritizing the operators
{
if(item == "(" || item == ")")
{
return 0;
}
else if(item == "+" || item == "-")
{
return 1;
}
else //if(item == "/" || item == "*") <-- guess didnt need to define this one
{
return 2;
}
}
void welcome()//welcome text
{
cout << "Welcome to this program!" << endl;
cout << "Please enter your equation" << endl;
}
int main()
{
welcome(); // welcome text
stack <string> myStack; // initializing the stack.
char line[256];
cin.getline( line, 256); // this and the proceeding line get the input.
string exp = line;
string item;
string postFix;
istringstream iss(exp);
iss >> item;
while(iss)
{
if(item != "+" && item != "-" && item != "/" && item != "*" && item != "(" && item != ")") //If the char is a number
{
cout << item;
postFix = postFix + item;
}
else if(myStack.size() == 0) // If the stack is empty
{
myStack.push(item);
}
else if( item == "+" || item == "-" || item == "/" || item == "*") //If the char is an operator
{
if(priority(myStack.top()) < priority(item)) // the item on the stack is greater priority than the array item
{
myStack.push(item);
}
else
{
while(myStack.size() > 0 && priority(myStack.top()) >= priority(item)) //while the stack contains something, and the item on
{
cout << myStack.top();
postFix = postFix + item;
myStack.pop();
}
myStack.push(item);
}
}
else if(item == "(") // left peren
{
myStack.push(item);
}
else if(item == ")") // right peren
{
while(myStack.top() != "(")
{
cout << myStack.top();
postFix = postFix + item;
myStack.pop();
}
myStack.pop();
}
iss >> item;
}
while (myStack.size() > 0 ) //When nothing is left to evaluate
{
cout << myStack.top();
postFix = postFix + myStack.top();
myStack.pop();
}
cout << endl;
//PART 2
int x1;
int x2;
int x3;
stack<int> thirdStack;
string exp2 = postFix;
string item2;
istringstream iss2(exp2);
iss2 >> item2;
while(iss2)
if(item2 != "+" && item2 != "-" && item2 != "/" && item2 != "*") //if its a number
{
int n;
n = atoi(item2.c_str());
thirdStack.push(n);
}
else if( item2 == "+" || item2 == "-" || item2 == "/" || item2 == "*") //if its an operator
{
x1 = thirdStack.top();
thirdStack.pop();
x2 = thirdStack.top();
thirdStack.pop();
if(item2 == "+")
{
x3 = x1 + x2;
thirdStack.push(x3);
}
else if(item2 == "-")
{
x3 = x1 - x2;
thirdStack.push(x3);
}
else if(item2 == "/")
{
x3 = x1 * x2;
thirdStack.push(x3);
}
else if(item2 == "*")
{
x3 = x1 / x2;
thirdStack.push(x3);
}
}
}
cout << "The conversion into infix notation is" + thirdStack.top() << endl;
}

There are a number of problems with this code.
In part 1, while your code appears to write out the correct postfix conversion, the postFix string it builds up isn't the same thing.
For example, in some places you have code like this:
cout << myStack.top();
postFix = postFix + item;
You're writing out myStack.top() but adding item to your postFix result. It should be this:
cout << myStack.top();
postFix = postFix + myStack.top();
In addition, you ought to be including spaces between each item that you add to the postFix string. So your result should be 5 2 - 1 + rather than 52-1+. Otherwise when trying to interpret that expression, the first item is going to be interpreted as 52.
Then in part 2, you're missing a call to iss2 >> item2; at the end of the while loop. You're basically just interpreting the first item over and over again, so the code will end up in an infinite loop.
And in your calculations, you have the operand order incorrect. This doesn't matter for addition and multiplication, but it does for subtraction and division. For example, the substraction calculation should be x3 = x2 - x1; rather than x3 = x1 - x2;.
Finally, when streaming out the result you've got a plus when you should have a stream operator. It should look like this:
cout << "The conversion into infix notation is" << thirdStack.top() << endl;

Related

Why does cin.peek() == '\n' work for '+' and '-', but not for '*', '/', and '^'?

I'm doing a calculator in replit. Why does my cin.peek() == '\n' work when I enter + and - but it doesn't work when I enter *, /, or ^?
#include <iostream>
#include <math.h>
#include <vector>
#include <istream>
using namespace std;
float hasil;
vector<float> num;
vector<char> op;
void calc(float x, float y, char z) {
if (z == '+') {
hasil = x + y;
}
else if (z == '-') {
hasil = x - y;
}
else if (z == '*') {
hasil = x * y;
}
else if (z == '/') {
hasil = x / y;
}
else if (z == '^') {
hasil = pow(x,y);
}
else {
cout<< "wrong operator";
}
}
void input () {
float in;
char ch;
for (int i = 0;;i++) {
if(cin.peek() == '\n') {
break;
}
else if(cin.peek() == '+') {
op.push_back('+');
}
else if(cin.peek() == '-') {
op.push_back('+');
}
else if(cin.peek() == '*') {
op.push_back('*');
}
else if(cin.peek() == '/') {
op.push_back('/');
}
else if(cin.peek() == '^') {
op.push_back('^');
}
cin >> in;
num.push_back(in);
}
for (auto i = num.begin(); i != num.end(); ++i) {
cout << *i << " ";
}
for (auto i = op.begin(); i != op.end(); ++i) { //this is just so I can see what is in the vectors
cout << *i << " ";
}
calc(num.at(0),num.at(1),op.at(0));
for (int i = 2; i < num.size(); i++)
calc(hasil,num.at(i),op.at(i-1));
}
int main() {
cout << "rumus = ";
input();
cout << " = ";
cout << hasil;
}
When I enter 1+2+3+4 it works fine, but the for loop doesn't break when I, for example, enter 1/3 or 2/3.
if(cin.peek() == '\n') {
break;
}
Why doesn't this run when there is a /, *, or ^ in what I enter?
Sorry if I have bad grammar. English is not my first language, and I am very new to C++ and coding in general. I don't know much about coding.
If you enter "4-2", you might notice that the numbers are 4 and -2, and the operator is +.
It produces the correct result by mistake because of if(cin.peek() == '-') { op.push_back('+'). (Copy-paste bug?)
You never actually read an operator, you only read floats.
"+2" and "-2" are valid inputs when reading a number, and peek leaves the character in the stream.
Thus, "1+2" is read as "1" and "+2", "1-2" as "1" and "-2".
None of the other operators can prefix a number, so in all those cases the stream enters an error state, never reads anything, and you're stuck in a loop.
I will leave fixing the bug as an exercise.

Recieving error "cannot dereference out of range deque iterator" when utilizing top()

I'm creating a simple program to evaluate post fix expressions but it won't run after successfully compiling due to "Expression: cannot dereference out of range deque iterator" whenever it reaches the assignment of the operand variables on lines 24 & 26. Why won't it run correctly when the program only reaches that point after filling the stack with number values?
#include <iostream>
#include <stack>
#include <string>
#include <cctype>
using namespace std;
int main()
{
stack<int> mystack;
string answer;
int result;
string done = "Y";
while (done == "Y" || done == "y") {
cout << "Please enter the RPN expression to be evaluated: ";
getline(cin,answer);
for(int i = 0; i < answer.length(); i++) {
if(answer[i] == ' ' || answer[i] == ':') {
continue;
}
if (isdigit(answer[i]) == false) {
cout << "Token = " << answer[i];
int operand2 = mystack.top();
mystack.pop();
int operand1 = mystack.top();
mystack.pop();
cout << " Pop " << operand2 << " Pop " << operand1;
if(answer[i] == '+') { //operation statements
result = operand1 + operand2;
}
else if(answer[i] == '-') {
result = operand1 - operand2;
}
else if(answer[i] == '*') {
result = operand1 * operand2;
}
else if(answer[i] == '/') {
result = operand1 / operand2;
}
mystack.push(result); //result returns to stack
cout << " Push " << result << endl;
}
else if(isdigit(answer[i]) == true){
int operand = 0;
while(i < answer.length() && isdigit(answer[i]) == true) {
operand = (operand*10) + (answer[i] - '0');
i++;
}
i--;
mystack.push(operand);
cout << "Token = " << operand << " Push " << operand << endl;
}
}
cout << "Token = Pop " << mystack.top() << endl << endl;
mystack.pop();
cout << "type 'Y' or 'y' to continue or type any other letter to quit: ";
getline(cin, done);
}
}
Here is a simple solution to the problem. This version uses ints and uses a stack of strings. This can easily be converted to doubles by replacing int with double throughout the file,
This uses getline() and istringstream to parse the input.
It also uses stringstream to convert numbers to strings and back.
You have to be careful when parsing multiple words from each line. This codes redirects the input line to ss, an istringstream object, and then takes tokens from that object.
Also, this will print the stack if you type "s".
Finally, you can arbitrarily load the stack with a series of space-separated numbers, or you can enter numbers one at a time. The stack is used when an operator is entered.
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
///////////////////////
/// top_and_pop()
/// Save the top value from a stack, and then pop the stack
/// If the stack is empty, return the string "0".
/// If the stack was not empty, return the popped element.
std::string top_and_pop(std::stack<std::string> &stack)
{
std::string return_string;
if (stack.empty()) {
return_string = "0";
std::cout << "Stack Empty, returning 0" << std::endl;
} else {
return_string = stack.top();
std::cout << "Popping " << return_string << std::endl;
stack.pop();
}
return return_string;
}
//////////////////////
/// is_number
/// Parse number into a int using std::stringstream.
/// If successful, then, the stringstream will be empty.
/// Return: true if the str would successfully parse as a int
bool is_number(const std::string &str)
{
std::istringstream ss(str);
int number;
ss >> number;
if (!ss.fail() && ss.eof())
return true;
ss >> std::ws; // not needed in this program, because we already parsed the
// input to a single word without whitespace. Needed for parsing a single line
// that may contain any set of chars.
return !ss.fail() && ss.eof();
}
/////////////////////
/// is_operator
/// return false if str is not a single character or if an operator is not found
/// acceptable operators are anyof "+-*/"
bool is_operator(const std::string &str)
{
return (str.length() == 1 &&
str.find_first_not_of("+-*/") == std::string::npos);
}
/////////////////////
/// string_to_int
/// convert string to int
/// Check to be sure string can convert to a int before calling
/// if conversion fails, return 0;
int string_to_int(const std::string &str)
{
std::stringstream stream;
int number = 0;
stream << str;
stream >> number;
return number;
}
//////////////////////
/// stack_to_string
///
/// print elements of stack
std::string stack_to_string(std::stack<std::string> stack)
{
std::string return_string;
while (!stack.empty()) {
return_string += stack.top() + " ";
stack.pop();
}
return return_string;
}
int main()
{
std::stack<std::string> mystack;
std::string input_line;
bool done = false; /// flag to indicate that calcualtor is closing
std::string token_str;
int operand1, operand2, result;
std::cout
<< "Please enter an RPN expression. Expression may consist of any \n"
"combination of space-separated numbers or operators.\n"
"Operators may include '+', '-', '*', '/'. The stack is initialized\n"
"with an unlimited supply of zeroes.\n\n"
"Type 's' to print the current stack.\n"
"To exit, type a 'y'" << std::endl;
do {
getline(std::cin, input_line);
std::stringstream ss(input_line);
/// loop through all tokens in this input line
while (ss >> token_str) {
// Only numbers are allowed on the stack.
// If the current token is a number, push it on the stack as a string
if (is_number(token_str)) {
mystack.push(token_str);
} else if (is_operator(token_str)) {
operand2 = (int) string_to_int(top_and_pop(mystack));
operand1 = (int) string_to_int(top_and_pop(mystack));
// switch does not accept string as a type, and we checked to ensure
// it is a single character operand that is handled in the switch
switch (token_str[0]) {
case '+':result = operand1 + operand2;
break;
case '-':result = operand1 - operand2;
break;
case '*':result = operand1 * operand2;
break;
case '/':
if (operand2 == 0) {
std::cout << "Error: Cannot divide by zero" << std::endl;
continue; // don't push result, take new input.
} else {
result = operand1 / operand2;
}
break;
// default case not needed as we already checked operator, but
// for error checking, we include it
default:std::cout << "Operator not found" << std::endl;
continue;
}
mystack.push(std::to_string(result));
std::cout << " Push result " << result << " " << std::endl;
} else if ("Y" == token_str || "y" == token_str) {
done = true;
} else if ("stack" == token_str || "s" == token_str) {
std::cout << "stack: ";
std::string stack_dump = stack_to_string(mystack);
std::cout << stack_dump << std::endl;
} else {
std::cout << "Invalid input." << std::endl;
}
}
}
while (!done);
}

issue Adding strings to string

I am trying to put tokens into a queue. However, when I try to put in a number that has more than one digit (i.e., 10, 123 ) it reads them as separate digits. Can someone tell me what I'm doing wrong? I've tried string insert and append and none of them seem to work
queue <string> getTokens(string token){
int a = (int) token.length();
string temp;
queue <string> numbers;
char t;
for (int i =0; i <a; i++){
t = token[i];
while (!isdigit(t)){
if (t=='+' || t=='-' || t=='/' || t=='*' || t=='^'){
string temp1;
temp1 += t;
numbers.push(temp1);
temp1.clear();
}
else if (t=='(' || t==')'){
string temp1;
temp1 += t;
numbers.push(temp1);
temp1.clear();
}
else if (!isalpha(token[i-1]) && t == 'e' && !isalpha(token[i+1])){
string e = "2.718";
numbers.push(e);
}
else if (!isalpha(token[i-1]) && t == 'p' && token[i+1]== 'i' && !isalpha(token[i+2])){
string pi = "3.14169";
numbers.push(pi);
}
break;
}
//if it is one single number
if (!isdigit(token[i-1]) && isdigit(t) && !isdigit(token[i+1])){
string tt;
tt += t;
numbers.push(tt);
}
//if there is more than one number
else if ((isdigit(t) && isdigit(token[i+1])) || (isdigit(token[i-1]) && isdigit(t))){ //if it is a number
string temp2;
string temp3="k";
string temp4;
//cout << t;
//int j=1;
if( isdigit(token[i])){
temp2 += t;
cout<<"temp2 : "<<temp2<<endl;
cout <<"temp3 :" << temp3<<endl;
//temp2.clear();
temp3 +=temp2;
}
temp4.append(temp3);
temp4 +=temp3;
//cout<<"hi"<<endl;
cout << "This is temp4: " << temp4 <<endl;
//cout << "this is temp3: " << temp3<< endl;
//temp2.clear();
//cout<<temp2 << "yo";
//temp3.assign(temp2);
//cout << "temp3 is : "<< temp3;
}
else
continue;
}
return numbers;
}
int main (){
string expression;
getline(cin,expression);
cout << expression;
queue <string> ts;
ts= getTokens(expression);
}
At every Iteration temp2 temp3 temp4 variable's value will get reset
so it does not hold previous iteration's value.
I think this is where you might be facing problem.
try to declare it outside for loop and clear it after you obtain desirable output, for next use
//if there is more than one number
else if ((isdigit(t) && isdigit(token[i+1])) || (isdigit(token[i-1]) && isdigit(t))){
//if it is a number
string temp2;
string temp3="k";
string temp4;
I hope this might help

Infix to Postfix to Answer Program (thought process right?)

I'm aware that there's already stuff here regarding this but I'm just posting to check if my logic lines up with my code (if I'm thinking about this whole infix Postfix thing the way I should be).
The code I've seen regarding this topic on this site look a little different from mine. I'm kind of a novice at C++. Anyway, my code so far looks like it is just fine and should work just fine but it's not working the way it should. I've included my thought process as comments in the code below. Please let me know if what I'm thinking is okay.
Here's the code:
#include <iostream>
#include <stack>
#include <sstream>
#include <string>
using namespace std;
int priority (string item)
{
int prior = 0;
if (item == "(")
{
prior = 1;
}
if ((item == "+") || (item == "-"))
{
prior = 2;
}
else if ((item == "*") || (item == "/"))
{
prior = 3;
}
else
{
prior = 4;
}
return prior;
}
int main()
{
stack<string> st;
string output;
cout << "Welcome. This program will calculate any arithmetic expression you enter" << endl;
cout << "Please enter an arithmetic expression below: " << endl;
char line[256];
cin.getline(line, 256);
string exp;
exp = line;
cout << "This is the expression you entered: ";
cout << exp << endl;
string item;
istringstream iss(exp);
iss >> item;
// While there are still items in the expression...
while ( iss )
{
// If the item is a number
if (isdigit('item') == true)
{
output = output + " " + item;
}
// If the stack is empty
else if (st.size() == 0)
{
st.push(item);
}
// If the item is not a number
else if (isdigit('item') == false)
{
// convert that item in the expression to a string
atoi(item.c_str());
int prior1 = 0;
int prior2 = 0;
// If that string is a LEFT PARENTHESIS
if (item == "(")
{
st.push(item);
}
// If that string is a RIGHT PARENTHESIS
else if (item == ")")
{
while ((st.empty() == false) && (st.top() != "("))
{
output = st.top() + " ";
st.pop();
}
st.pop();
}
else
{
// store what is returned from "priority" in "prior1"
prior1 = priority(item);
// pass item on top of the stack through "priority"
// store that in "prior2;
prior2 = priority(st.top());
// while loop here, while item has a higher priority...
// store numbers in a variable
while (prior1 > prior2)
{
output = output + " " + st.top();
st.pop();
prior2 = priority(st.top());
}
}
}
}
while (st.empty() == false)
{
output = st.top() + " ";
st.pop();
}
cout << "Here's the postfix: " << output << endl;
}
This is for evaluating postfix to an actual answer:
// EVALUATE POSTFIX
stack<int> st2;
string output2;
istringstream iss2(exp);
iss2 >> item;
while (iss)
{
// If the item is a number
if (isdigit('item') == true)
{
st.push(item);
}
if (isdigit('item') == false)
{
// store item in a variable
// pop another item off the stack
// store that in a variable.
// apply operator to both.
// push answer to the top of the stack.
int m = 0;
int n = 0;
int total = 0;
m = st2.top();
st2.pop();
n = st2.top();
st2.pop();
if (item == "+")
{
total = m + n;
st2.push(total);
}
else if (item == "-")
{
total = m - n;
st2.push(total);
// add the thing you popped of the stack with the first thing on the stack
}
else if (item == "*")
{
total = m * n;
st2.push(total);
}
else if (item == "/")
{
total = m / n;
st2.push(total);
}
}
}
cout << "Here's your answer: " << st2.top() << endl;
}
Am I thinking about this whole infix-postfix thing the way I should be? Am I on track to solving this problem? My apologies if this question seems simple. I'm kind of a novice at this. Thank you very much.

My mathematical expression converter doesn't print correctly

So, I am writing a program which takes the input (a mathematical expression) and converts it into postfix notation and then print it out to the user. When I perform this program on simple mathematical expressions (i.e. 5 + 1 - 3 * 2) it works great. The problem is when I include parentheses. It prints all of the mathematical operators on the last line instead of their proper place. I need the mathematical operators to be in their proper spot. (i. e. 5 1 + 3 - 2 *). Any suggestions?
The real output of this statement 5 - ( 2 * 3 ) + 5 is 5 2 3 5 * - + I need it to look like 5 2 3 * - 5 +
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
using namespace std;
int priority(string item) //prioritizing the operators
{
if(item == "(" || item == ")")
{
return 0;
}
else if(item == "+" || item == "-")
{
return 1;
}
else if(item == "/" || item == "*")
{
return 2;
}
}
void welcome()
{
cout << "blah blah!" << endl;
}
int main()
{
welcome(); // welcome text
stack <string> myStack;
char line[256];
cin.getline( line, 256);
string exp = line;
string item;
string output = "";
istringstream iss(exp);
iss >> item;
while(iss)
{
if(item != "+" && item != "-" && item != "/" && item != "*" && item != "(" && item != ")") //If the char is a number
{
cout << item << endl;
}
else if(myStack.size() == 0) // If the stack is empty
{
myStack.push(item);
}
else if( item == "+" || item == "-" || item == "/" || item == "*") //If the char is an operator
{
if(priority(myStack.top()) < priority(item)) // the item on the stack is greater priority than the array item
{
myStack.push(item);
}
else
{
while(myStack.size() > 0 && priority(myStack.top()) >= priority(item)) //while the stack contains something, and the item on
{
string dpu = myStack.top();
myStack.pop();
output = output + dpu + " ";
}
myStack.push(item);
}
}
else if(item == "(") // left peren
{
myStack.push(item);
}
else if(item == ")") // right peren
{
while(myStack.top() != "(")
{
string dpu = myStack.top();
myStack.pop();
output = output + dpu + " ";
}
myStack.pop();
}
iss>> item;
}
while (myStack.size() > 0 )
{
string dpu = myStack.top();
output = output + dpu + " ";
myStack.pop();
}
cout<< output << endl;
}
well... in your code the numbers are always printed before anything else:
if (item != "+" && item != "-" && item != "/" && item != "*" && item != "(" && item != ")") //If the char is a number
{
cout << item << endl;
}
I'm not familiar with the notation you are requesting, but a stack doesn't seem to me the right datastructure for this task... using a tree seems better to me, since you are parsing