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.
Related
This is my first time on this web site. I have been having a problem but I haven`t been able to figure it out. I have been trying to implement a predefined function into my code but I am not sure how to do so. In my Task I was given an open brief asking me simply to design a password protected calculator. I designed the calculator and handed it in to my teacher. He then asked me to add a predefined function. Now I am not sure how to do this or even how I would start. Could any one give me some example of a predefined function similar to my code.
#include <iostream>
using namespace std;
int main()
{
char op;
float num1, num2;
int correct_password = 1998;
int password = 0;
int counter = 0;
int attempt = 0;
while (attempt <= 3) {
cout << "Enter your password: ";
cin >> password;
attempt = attempt + 1;
if (password != correct_password) {
cout << "Incorrect password combination. Please try again." << "\n" << endl;
} else {
break;
}
}
if (attempt >= 3) {
return 0;
}
cout << "Access granted." << endl;
//Asks you to enter an operator to use in your calculation
cout << "Enter operator either + or - or * or /: ";
cin >> op;
//Asks you to enter 2 numbers
cout << "Enter two operands: ";
cin >> num1 >> num2;
//Searches for which operator you have selected and Either *-+/ the number depending on choice
switch (op) {
case '+':
cout << num1 + num2;
break;
case '-':
cout << num1 - num2;
break;
case '*':
cout << num1 * num2;
break;
case '/':
cout << num1 / num2;
break;
//If entered operator is incorrect closes down the program
default:
cout << "Error! operator is not correct";
break;
}
return 0;
}
Sorry for the trouble. I am not quite sure if I am going about asking this the right way. so I will apologies before hand if I am not specific enough or if I am doing ti wrong :).
(edit:: added some explanation)
I can't know what exactly your teacher wanted, but it might be something like this:
void foo(float a, float b){
return a+4*b;
}
Allowing your calculator to use a function like that would work in the following way:
... //Your previous code here
switch(op){
... // Your other switches here
case 'f':
cout<<foo(num1,num2)<<endl;
break;
}
... //Your following code here
The 'f' here stands for the command "EXECUTE PREDEFINED FUNCTION" instead of '+' for "ADD" or '-' for "SUBTRACT".
That way you could have a predefined function and execute that on your numbers.
In this case we would see the entred number num1 be added to four times the entered number num2
I hope it helped :)
these function are in library #include<math.h> You need to use this header file in order to use those function in your code .
It includes predefined functions such as
sqrt(number);
This function is used to find square root of the argument passed to this function.
pow(number);
This is used to find the power of the given number.
trunc(number);
This function truncates the decimal value from floating point value and returns integer value
// FILE: calc.h
#include <iostream>
#include <stack> // Uses STL
#include <string> // Uses STL
using namespace std;
void evaluate_stack_tops(stack<double> & numbers, stack<char> & operations);
double read_and_evaluate(string line)
{
const char RIGHT_PARENTHESIS = ')';
stack<double> numbers; // local stack object
stack<char> operations; // local stack object
double number;
char symbol;
size_t position = 0;
while (position < line.length())
{
if (isdigit(line[position]))
{
number = line[position++] - '0'; // get value
numbers.push(number);
}
else if (strchr("+-*/", line[position]) != NULL)
{
symbol = line[position++];
operations.push(symbol);
}
else if (line[position] == RIGHT_PARENTHESIS)
{
position++;
evaluate_stack_tops(numbers, operations);
}
else
position++;
}
if (!operations.empty())
evaluate_stack_tops(numbers, operations);
return numbers.top();
}
void evaluate_stack_tops(stack<double> & numbers, stack<char> & operations)
{
double operand1, operand2;
operand2 = numbers.top();
numbers.pop();
operand1 = numbers.top();
numbers.pop();
switch (operations.top())
{
case '+': numbers.push(operand1 + operand2); break;
case '-': numbers.push(operand1 - operand2); break;
case '*': numbers.push(operand1 * operand2); break;
case '/': numbers.push(operand1 / operand2); break;
}
operations.pop();
}
// FILE: Use_Stack.cpp
#include <iostream>
using namespace std;
#include "calc.h"
int main()
{
double answer;
string line;
cout << "Type a fully parenthesized arithmetic expression (SINGLE DIGITS ONLY!):\n";
getline(cin, line);
answer = read_and_evaluate(line);
cout << "That evaluates to " << answer << endl;
system("pause");
return 0;
}
Everything works and i can input simple things like "2 4 3 * + 7 – 2 +" but if i wanted to input something like "123 60 +" it would not work. i separated it in two header files. Can someone give me a hint on how to accept multi-digit integers?
One way to solve the problem is where you discover an number, instead of assuming it is only one digit long, use a loop to collect all the other digits that are part of the number. The loop would terminate when it encounters a non-digit, or a space.
A better way to do it would be to tokenize the input string using stringstream. In this scenario, you would put the entire line of input into a string and then use a while loop similar to the following:
stringstream ss(line);
string token;
while (ss >> token) {
// do stuff with token
}
RPN works by having a stack of values which you manipulate. Given input "13", the manipulation needed to go from top=1 to top=13 is fairly straightforward: top = 10 * top + digit
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());
I'm trying to make a calculator in VC++ and even though it runs, it keeps reading memory that I haven't told it to, and I don't know how to make it stop.
#include <iostream>
#include <ctype.h>
int main(){
char equation[4];
equation[3] = '\0'; //string terminator
int result;
bool wantsToContinue = true;
char yesOrNo;
equationPrompt:
std::cout << "Enter Equation: ";
std::cin >> equation;
while(wantsToContinue){
switch(equation[1]){
case '+':
result = int(equation[0]) + int(equation[2]);
break;
case '-':
result = int(equation[0]) - int(equation[2]);
break;
case '*':
result = int(equation[0]) * int(equation[2]);
break;
case '/':
result = int(equation[0]) / int(equation[2]);
break;
}
std::cout << std::endl << "Your answer is " << result << std::endl;
exitPrompt:
std::cout << "Exit? Y/N: ";
std::cin >> yesOrNo;
if(tolower(yesOrNo) == 'n'){
wantsToContinue = true;
goto equationPrompt;
}
else if (tolower(yesOrNo) == 'y')
wantsToContinue = false;
else{
std::cout << std::endl << "Unknown response." << std::endl;
goto exitPrompt;
}
}
return 0;
}
You make it stop by not writing an arcane Frankenstein language mix of C and C++, but instead using real C++ string types:
#include <string>
#include <istream>
#include <iostream>
int main()
{
std::string equation;
std::cin >> equation;
// now equation[0] is the first character
}
Note that int(equation[0]) is almost guaranteed not to be what you think. What you want is something like int x = std::atoi(equation[0]); or std::strtol(), but that only works for single digits. Probably much simpler to just stream into an integer, which performs an actual text-to-integer conversion:
int x, y;
std::string operand;
std::cin >> x >> operand >> y;
equation is an array of 4 chars.
std::cin >> equation;
reads an arbitrarily long string into that array. Type too much, and it will overflow, stepping on adjacent memory.
As #Kerrek SB says, you're better off using std::string, which doesn't have that problem.
#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'...