Evaluate postfix using a stack in C++ - c++

#include <iostream>
#include <sstream>
#include <stack>
#include <limits>
#include <string>
using namespace std;
int main()
{
string input;
cout << "Enter a postfix expression: " << endl;
getline(cin, input);
int operand1, operand2, result,number;
stack<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;
}
I've changed the code and managed to obtain the "pop" value, but the operation didn't work.

You probably meant
switch(input[i])
instead
switch(operation.top())

Update response to code changes
I can confirm you changed the code, but not in a good way.
The code mostly has all the flaws it already had, and a few more.
What good is that you now combine the operands into a stringstream?
You now switch on (operand1,operand2)...
both are uninitialized
(operand1,operand2) means basically (operand2) in this context (sequence operator)
your branch labels are ... operators (+-/*)
you now print a final result which is the concatenation of all digits in the input (if you ever reach the end of the program without crashing)?
Among the things that were wrong before, and should still be fixed
the mental model of a stack calculator.
numbers (integers) are the operands (so 9, 100, 39829 are valid operands)
+-/* are the operators (operators operate on the operands)
the stack is an operand stack, not an operator stack (operators do not have to be remembered, because they are evaluated immediately)
numbers consist of 1 or more digits (0123456789) in a row; so you'd need to read several characters before you can 'push' a number on the operand stack
the operators +-/* take 2 operands, so any operation on a stack of size<2 is an error (you need to check that or the program will crash while trying to access memory that doesn't exist or contains rubbish).
That should be enough to get you started.
Two things I do think are positive:
You program compiles. +1 for you actually using a compiler there :)
You took the repeated operation.push(result) out of the switch so it isn't duplicated anymore. +1 for coding style ...
I hope you can gather from this that the code isn't very good (to put it mildly), and I really think some basic exercises are in order:
1. write a simple for loop that prints numbers 1 to 10 to the console
1. write a simple while loop that prints words entered by the user
1. use a simple loop to print all numbers between 1 and 50 that are multiples of 7
1. use a switch statement to print "yes" whenever the user enters one of the letters a, b, k, or z
2. make a simple loop that only prints the input character for every character that follows the identical (so 'abccdefgghijkllmabcdd' would become 'cgld')
1. use the same loop but this time print every word that immediately follows the identical word (so "no, no, you should not pop, pop, but push, pop" becomes "no pop")
That should give you a feel for how things really work, without the guesswork or the 'magic factor'.
Oh, and don't forget, I implemented the whole thing for you below. I don't suggest you blindly copy it (it will be rather obvious to your teacher :)) but it is there for you to take a peek if you want to know, what I mean with all my words above :)
You are pushing loose digits, not parsed numbers
In line 31 you pop a possibly empty stack (resulting in segfault unless you use the debug-mode STL flags on your compiler)
Just for fun:
#include <iostream>
#include <stack>
#include <vector>
#include <limits>
#include <string>
#include <stdexcept>
#include <iterator>
#include <fstream>
using namespace std;
template <class T>
static void dumpstack(std::stack<T> s/*byval!*/)
{
std::vector<T> vec;
while (!s.empty())
{
vec.push_back(s.top());
s.pop();
}
std::copy(vec.rbegin(), vec.rend(), std::ostream_iterator<int>(std::cout, " "));
}
class calc
{
private:
std::stack<int> _stack;
int _accum;
bool _pending;
void store(/*store accumulator if pending*/)
{
if (_pending)
{
_stack.push(_accum);
_pending = false;
_accum = 0;
}
}
public:
calc() : _accum(0), _pending(false)
{
}
void handle(char ch)
{
switch (ch)
{
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
_pending = true;
_accum *= 10;
_accum += ch-'0';
break;
case '+': case '-': case '/': case '*':
{
store();
if (_stack.size()<2)
throw std::runtime_error("stack underflow");
int op2 = _stack.top(); _stack.pop();
int op1 = _stack.top(); _stack.pop();
switch (ch)
{
case '+': _stack.push(op1 + op2); break;
case '-': _stack.push(op1 - op2); break;
case '/': _stack.push(op1 / op2); break;
case '*': _stack.push(op1 * op2); break;
}
// feedback to console:
std::cout << std::endl << "(evaluated: " << op1 << " " << ch << " " << op2 << " == " << _stack.top() << ")" << std::endl;
dump();
}
break;
default:
store(); // todo: notify of ignored characters in input?
}
}
void dump() const
{
dumpstack(_stack);
}
};
int main()
{
cout << "Enter postfix expressions: " << endl;
calc instance;
try
{
while (std::cin.good())
{
char ch = std::cin.get();
instance.handle(ch);
}
std::cout << "Final result: ";
instance.dump();
return 0;
} catch(const std::exception& e)
{
std::cerr << "E: " << e.what() << std::endl;
return 255;
}
}
Test output: (note that you can continue with the remaining, partially evaluted, stack after pressing carriage return)
Enter postfix expressions:
1 2 3 +4 * - / 1333 *
(evaluated: 2 + 3 == 5)
1 5
(evaluated: 5 * 4 == 20)
1 20
(evaluated: 1 - 20 == -19)
-19 E: stack underflow

There are many things wrong with the code, starting with parsing of the input expression. The actual crash is most probably due to the fact that if you input something like "12+" you will push '1' and '2' into the stack (note: characters 1 and 2, not values 1 and 2!!!) and then try to extract two operands and an operator that you never inserted into the stack.
On parsing the input, you are reading character by character, and only using the first digit, the parsing is not able to handle spaces or any other separator... Try to break the problem in two: parsing and processing. The problem of parsing can be tackled by not using the actual values read, but just printing them (or storing in some form and then printing the whole read expression), and can be a first step. Ensure that the parser is able to deal with common expressions like "1 2 +", "10 20 +", "1 2+", " 1 2 + " (note the different positions of spaces) in a robust way. And that it fails gracefully to parse expressions like " +", "1 +", "1 2 ++"... You can never trust user input, they will make mistakes and that should not bring your program to its knees.
Once you are sure that you are able to parse the input, start on the actual algorithm. Make it robust against invalid user inputs that you might have not been able to tackle before, like "10 0 /" and do the actual processing.
Learn to use the debugger, it will help you understand when things go south what are the reasons. The debugger would take less than one second to point at the specific problem in your code above, it will not tell you why it died, but it will show you how it died and what the state of the program was there. If my hunch is correct, then it will point you at the operation.top() instruction as the culprit, and you will be able to see that you were trying to extract more elements than were inserted. Execute a part of your program step by step to understand what it is actually doing, and you will notice that when you read "12+" you are actually storing two seemingly unrelated integers into the stack (the ASCII values of '1' and '2'...

Related

Unable to detect enter key in C++

Now, before this question gets marked for duplicate. I have already gone through most of the questions and their relative answers of C++. These are the links that I have tried and none of them work for me. It maybe because they are using an older version of C++, and I have the latest version of C++. Here are the links that I have tried:
Detecting ENTER key in C++
https://www.sololearn.com/Discuss/1863352/how-can-i-check-that-user-press-enter-key-in-c
http://www.cplusplus.com/forum/beginner/2624/
https://www.dreamincode.net/forums/topic/398680-detect-enter-key/
Now, with the duplicates out of the way. I am making an expression calculator. So, for example if the user input is: 2+2*6*9/9, then the output should be 14.
The code where I suspect that the problem lies is in:
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::string;
using std::vector;
void clear();
void error(string message);
int main() {
cout << "Enter an expression: ";
double l_Value = 0, r_Value = 0, result = 0, count = 0, previous_number;
char op;
while (cin >> l_Value) { // 1+2*3+6-4/2+3
if (!cin) {
error("Invalid operand entered!");
}
else {
bool is_Error = 0; // false
vector<double> numbers;
numbers.push_back(l_Value);
previous_number = l_Value;
while (cin >> op) {
if (op == '\0') {
break;
}
cin >> r_Value;
switch (op)
{
case '+':
numbers.push_back(r_Value);
previous_number = r_Value;
break;
case '-':
numbers.push_back((-1 * r_Value));
previous_number = (-1 * r_Value);
break;
case '*':
numbers.pop_back(); // take out the number
r_Value *= previous_number;
numbers.push_back(r_Value);
previous_number = r_Value;
break;
case '/':
if (r_Value == 0) {
error("Sorry, division by zero has occured. Please re-evaluate your expression!\n");
is_Error = 1; // true
break;
}
else {
numbers.pop_back(); // take out the number
previous_number /= r_Value;
numbers.push_back(previous_number);
break;
}
}
}
if (!is_Error) {
for (int i = 0; i < numbers.size(); i++) {
result += numbers[i];
}
cout << result << '\n';
}
numbers.clear();
result = 0;
l_Value = 0;
r_Value = 0;
}
cout << "Enter an expression: ";
}
clear();
return 0;
}
None of the links above seemed to work for me.
When I press the Enter key, it expects me to give another input, and that is not supposed to happen. So when I used cin.get() == 'n' or cin.get() == (int)'\n', it expects for another input. But, when I have an 'x' at the end of the expression, it works perfectly fine. So, I need the "cin" operator to help me detect an Enter character at the end of the expression and then terminate the program.
Here, is a sample run of a program with 'x':
[![running as x-terminator][1]][1]
[1]: https://i.stack.imgur.com/ORPQa.png
When I try the above solution such as "cin.get() == '\n':
Then, I thought that maybe it is reading the null character and so, I tried if (op == '\0'):
For the enter key and null character I had to press Ctrl+Z to terminate the program. Please help!
As, mentioned by user #idclev, I already have a string program that works, but I am trying to avoid using string to calculate any expressions! So, if I could detect an enter key pressed using a character datatype that would be great!
I avoided strings to avoid parsing through the text
That argument is moot. What you can read from cin you can also read from a std::string, no difference whatsoever. You just need to add one step:
#include <iostream>
#include <string>
#include <sstream>
int main( ){
std::string x;
std::cin >> x;
if (x == "") {
std::cout << "user pressed enter (and nothing else)";
} else {
double y;
std::stringstream ss{x};
ss >> y;
std::cout << y;
}
}
This will read one std::string. If user only hit enter then the string will be empty. If the user entered something the else branch will be taken and you can extract the number from the string in the same way you did extract the number from cin (via using a std::stringstream).
If you have more than one number in the input you need to use getline to read the string, because cin will (by default) only read till the next whitespace.
Again...
If I used a string, I would have a tough time in extracting single-digit and two-digit or n-number of digits in a string. The double data type does that for me
You can read single-digit or any number of digits from a stringstream in exactly the same way as you read them from cin.
I already made a program with string in it. I was trying to avoid string to see how much faster would it be without string.
It won't be any faster. Constructing the string and the stringstream is maybe in the order of microseconds. A user entering input is in the order of seconds, maybe milliseconds when they are typing very fast.
Your approach cannot work because hitting enter is not considered as a character. Trying to read a character when there is none in the stream will fail. It will not set the character to \n or \r.
On the outer loop, you are trying to read a double, but you keep pressing enter. There is no input to evaluate, so it keeps trying to read a double. You can get out of it by ending the input stream with ^Z, or you can give it any actual content to read, and it will try to make it into a double (which is what your code explicitly told it to wait for).
Basically, when you press enter, it's ignoring it because
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
Extracts as many characters as possible from the stream and inserts them into the output sequence controlled by the stream buffer object pointed by sb (if any), until either the input sequence is exhausted or the function fails to insert into the object pointed by sb.
Try experimenting with this to see what is happening.
#include <iostream>
#include <vector>
#include <string>
int main() {
double x;
std::cin >> x;
std::cout << "read this value: " << x << std::endl;
// this is what while or if will look at
bool success = !std::cin.fail();
if (success)
std::cout << "success" << std::endl;
else
std::cout << "failure, loop will exit" << std::endl;
return 0;
}
What you should want (in my opinion) is a function that takes the expression as a string, and returns the result, so you can write unit tests, and make sure the function works. You can use this function with any expression that you can put in a string. It doesn't HAVE to be typed in by a user.
If you want the user to type in the experession, it's a lot easier to just use getline() then pass the string to your function. The big problem with using cin on each variable and character is that the user has no idea which datetype is expected right then. Granted, it's not hard to guess with an expression, but you wrote it and debugged it and still didn't know which cin you were failing to get the right datatype to. (this is normal, btw -- been there, which is why I getline and parse separately)

12 days of Christmas C++ using functions

I am in a beginner C++ course and I am trying to create a program that outputs the 12 days of Christmas song using the two given function calls show_ordinal(int) and show_verse(int) as an assignment. It is supposed to call the verse and show the day with it's ordinal suffix and then loop the remaining verses depending on where the user decides to start from, so if it was show_verse(3) it would be on the 3rd day of Christmas... all the way to the pear tree. I started writing for the function to get the ordinal but kept getting segmentation fault errors.
#include <iostream>
using namespace std;
string show_ordinal(int);
void show_verse(int);
int main()
{
cout << show_ordinal(2) << endl;
return 0;
}
string show_ordinal(int x)
{
switch (x % 10)
{
case 1:
if (x % 10 == 1)
{
cout << x << "st";
}
break;
case 2:
if (x % 10 == 2)
{
cout << x << "nd";
}
break;
case 3:
if (x % 10 == 3)
{
cout << x << "rd";
}
break;
case 4:
if (x % 10 != 1 || x % 10 != 2 || x % 10 != 3)
{
cout << x << "th";
}
break;
}
}
Testing the function by trying to call it with an int value of 2 in main,I have been working on it for awhile and cannot get it to work any help would be greatly appreciated.
show_ordinal returns nothing for
cout << show_ordinal(2) << endl;
to print out. It promises to return a string, but it never does. This is bad form. When a function has a non-void return type it must return a result on all code paths or the function, and the program, is ill formed. A crash or other segfault is a common result, but you could get silent corruption of data, and that is much harder to track down.
Rather than couting all of your results, assign the results to a string and return the string.
You never return a string from show_ordinal(), you just output to cout. Instead of using cout, I think you want to contsruct a string using x and your computed suffix and return that:
string show_ordinal(int x) {
string out;
switch (x % 10) {
case 1:
out = to_string(x) + "st";
break;
case 2:
out = to_string(x) + "nd";
break;
case 3:
out = to_string(x) + "rd";
break;
default:
out = to_string(x) + "th";
break;
}
return out;
}
You should probably count yourself lucky that you experienced a seg fault, because what you are doing is producing undefined behavior. If you don't believe me, check out what OnlineGDB does to your code.
The problem is that you define show_ordinal with a return value of std::string, but never return anything from the function. This produces undefined behavior in the C++ specification. To fix it you can do one of these two things:
Actually return a string. Rather than shifting into std::cout within the function, shift into an std::ostringstream instead, then return the stringified version:
#include<string>
#include<sstream>
std::string show_ordinal(int x) {
std::ostringstream oss;
switch (x % 10) {
case 1:
// Note: I got rid of your extraneous "if" statement.
// "switch" is already doing that work for you.
oss << x << "st";
break;
/* more cases here */
}
return oss.str();
}
Define the function to return nothing. If you really want the function to handle the shifting to std::cout, define it with a void return signature and don't shift the output to std::cout in main:
#include<iostream>
#include<string>
void show_ordinal(int x);
int main() {
show_ordinal(2);
}
void show_ordinal(int x) {
switch (x % 10) {
case 1:
std::cout << x << "st\n";
break;
/* more cases here */
}
}
Either of these should solve your problem.
Note: A few more things:
Please include all the headers for the standard libraries you are using. Add #include<string>.
You don't need those extra if statements in the case blocks. If your code made it to case 1, then x % 10 == 1 is guaranteed, so don't check it again.
show_ordinal won't do anything for x % 10 > 4. Consider replacing case 4 with default. See the documentation for the switch statement.
Please get out of the habit of using namespace std. It will get you in trouble in the future.

Code stops/ends after each case selected in nested switch and error C4244 conversion from double to float in c++

I have made a calculator( code below ) and it seems to run smoothly, except for 6 C4244 errors which don't seem to effect the way it runs. The only problem that I have now is that after you select any case, the program runs that part of the case and exits, but I want it to return to the main switch after it runs the case selected.How can that be done and why am i getting the errors?
void main(void)
{
int c;
printf("Enter the number of the type of operation you would like to perform:\n\n");
printf("1.Basic Mathematical Operations\n2.Trignometric Operations\n3.Quadratic Operations\n4.Lograthimic Operations\n5.Matrix Operations\n\nNumber selected: ");
scanf_s("%d",&c);
switch(c)
{
case 1:
int m;
printf("\n\nEnter the number of the operation you would like to perform:\n");
printf("1.Addition\n2.Subtraction\n3.Multiplication\n4.Division\n5.Exponent\n6.Square Root\n7.Inverse\n\nNumber selected: ");
scanf_s("%d",&m);
switch(m)
{
case 1:
add();
break;
case 2:
sub();
break;
case 3:
mul();
break;
case 4:
div();
break;
case 5:
exp();
break;
case 6:
sqrt();
break;
case 7:
inv();
break;
}
break;
}
One of the C4244 errors is in the following function,in the line "r=sin(a*Pi/180.0);" and the function is called in another nested switch case:
void sind(void)
{
float a, r;
printf("enter angle");
scanf_s("%f",&a);
r=sin(a*Pi/180.0);
printf("The sine of %f degrees is %f.\n", a, r );
_getch();
}
Your conversion error of double to float is most likely due to the use of 180.0 which is automatically interpreted as double. You have to add an 'f' as suffix to specify a float like this 180.0f. Also you have to pay attention to your declaration of 'Pi' which should also be a float number.
You asked two questions, so I don't know which one is relevant to your post. However, I will answer the one where you are having trouble getting the code to go back to the beginning to request subsequent choices to the user.
The easiest way to accomplish the loop is to break up your code into functions. Having switch statements that are so many lines long is not maintainable, and the logic gets all lost.
Also, the main() function returns int, not void.
For example:
#include <iostream>
using namespace std;
int promptAndGetOperation()
{
int op;
cout << "Enter the number of the type of operation you would like to perform:\n\n";
cout << "1.Basic Mathematical Operations\n2.Trignometric Operations\n3.Quadratic "
"Operations\n4.Lograthimic Operations\n5.Matrix Operations\n\n"
"6. Exit\n\nNumber selected: ";
cin >> op;
return op;
}
void performOperation(int op)
{
// fill this in
}
int main(void)
{
int operation;
do
{
operation = promptAndGetOperation();
if ( operation >= 1 && operation <= 5)
performOperation(operation);
else
if ( operatiom < 1 )
cout << "Illegal operation. Try again\n\n";
}
while (operation != 6 );
}
This is a basic skeleton of what you should be doing. See how simple the main program becomes? The do-while loop is the main driver.

RPN calculator doesn't perform calculations correctly

I have a program that is supposed to convert an expression into reverse polish notation, and then display the answer after performing the calculations. Right now it doesn't perform calculations correctly. For example, if I enter 5+2+5, it only registers the 5+2 for some reason. Can anyone tell me what I did wrong?
#include <iostream>
#include <stack>
void calculation(int, int, char);
using namespace std;
stack<int> a;
void main(void)
{
bool expression = false;
char ch;
char done;
int op1, op2;
cout << "Reverse Polish Notation : " << endl;
cout << "Enter expression: " << endl;
while (!expression)
{
cin >> op1;
cin >> op2;
cin >> ch;
calculation(op1, op2, ch);
if (!cin)
expression = false;
else
{
expression = true;
calculation(op1, op2, ch);
}
}
cout << "Your expression is " << a.top() << endl;
}
void calculation(int oper1, int oper2, char chr)
{
switch (chr)
{
case '+':
a.push(oper1 + oper2);
break;
case '-':
a.push(oper1 - oper2);
break;
case '*':
a.push(oper1 * oper2);
break;
case '/':
a.push(oper1 / oper2);
break;
}
}
Your program does not convert anything. It is a very simple RPN calculator that takes a single term consisting of two operands and a binary operation and calculate the results.
If you need it to take more complex RPN inputs, you need to re-design the input and calculation logic.
If you want to input infix expressions like 5+4 but keep the internal representation as an RPN-stack, you will also have to write a parser which does that.
All operations should be to and from the stack. Your main loop should look more like
while not eol
if reading an operator
push result of applying operator to top two stack elements
else if reading an integer
read it and push it on to the stack
else
print an error message
print value at top of stack
I omitted a pile of stack depth checks.

How to properly return an operator (*,/,-,+) in C++?

EDIT - thank you all for the help. I didnt even think of doing the switch statement. For some reason I keep thinking C++ is a lot different than Java... it makes a lot of sence with a switch.. thanks for bringing that to my attention.
How would I properly return an operator and use it once returned? I wrote a function to grab the operator from the input and check to make sure that its valid input.. this is the code I wrote for that (i called it doctor because I guess operator is a reserved name in C++ and doctors do operations haha... sorry.. just being silly)...:
string doctor()
{
string getDoc;
cin >> getDoc;
if (getDoc == "*")
return "*";
if (getDoc == "/")
return "/" ;
if (getDoc == "-")
return "-" ;
if (getDoc == "+")
return "+" ;
else
{
cout << "You entered " << getDoc << " please only use +,-,*,/ : ";
return doctor();
}
}
when the value is returned I have my main () do the following (it returns it into the "operation" variable...:
cout << firstNum << operation << secondNum << " is " << answer;
I have everything working except for that operator... how do I make that do what it needs to do.. in other words if its a * then multiply etc...
sorry if this is basic, but I am new to C++, and googling for this didnt yield results...
thanks!
Well, you have to compare chars anyway. But the shorter way is to use (if you have sign in char)
switch(sign) {
case '*':
case '/':
case '+':
case '-':
string str; str += sign;
return str;
default:
return "error message";
}
OR
if(sign == "+" || sign == "-" || sign == "/" || sign == "*")
return sign;
else
return "Error message";
A classic approach is to use switch-case construction here. You are given an '*', multiply arguments, if you're given a '/', then divide.
double doctored(char operation, double arg1, double arg2) {
switch (operation) {
case '+': return arg1+arg2;
case '-': return arg1-arg2;
case '*': return arg1*arg2;
case '/': return arg1/arg2;
default: // ignore
return arg1;
}
}
You can case it the same way you have done in the function getting the input stream:
float result;
switch(operation) {
case '*':
result = firstNum * secondNum;
break;
case '/':
result = firstNum / secondNum;
break;
case '+':
result = firstNum + secondNum;
break;
case '-':
result = firstNum - secondNum;
break;
}
cout << firstNum << operation << secondNum << " is " << result;
From the returned string, you can choose a function or callable object (functor). For example, you can use if-else for that, or you can use a std::map. Then with the function or callable object, just call it.
You could do the operation just like you already did the validation, i.e.
if (operation == "*")
answer = firstNum *secondNum;
etc. (or better yet, do both in switch-cases, like proposed by my fellow answerers), though a better approach would be to create a class that parses the string and stores the operator information (as an enum) internally. Give it a method that applies the operation on two numbers and returns the result, and implement another method to return the textual representation as a string. Then you have decoupled your data from the visual presentation. (Don't forget the method that takes a string and extracts the desired operator from it ;))
usage of doctor(operator) depends on operands, if they are instances of classes - you have to overload operator for them, otherwise I think you can write one function per operator which takes 1,2,3 arguments. When use switch statement in which according to the value of operation needed function is called and needed result is returned
write another method doing your calculations and call it:
float doDoctoryStuff(float a, float b, const char op)
{
switch(op) {
case '*':
return a * b:
break;
...
...
...
}
}
in your main
cout << firstNum << operation << secondNum << " is ";
cout << doDoctoryStuff(firstNum, secondNum, doctor().c_str());