RPN calculator / post fix calculator - c++

So, i have to make a postfix calculator or a RPN calculator, the question goes like
The task is to write a simplified calculator that works only on integers. Your code has to provide a function called evaluate, which takes one argument: a std::string and returns an integer. The calculator has to work in the following way:
it reads a string character by character,
if it reads a digit it puts it on its own internal stack,
if it reads a space it has to ignore it,
if it reads a character +,-, * or / it performs the operation on two topmost elements of the stack, deletes them and puts the result on the stack,
when it reaches the end of the std::string argument it returns the top of the stack.
Code:
using namespace std;
int evaluate(string);
bool isdigit(char c);
bool isOp(char c);
bool isdigit(char c)
{
if (c >= '0' && c <= '9')
{
return true;
}
return false;
}
int main()
{
string str;
cout << "\n Enter the input : ";
cin >> str;
evaluate(str);
}
int evaluate(string str)
{
stack<int> mystack;
stack<int> vals;
for (int i = 0; i < str.size(); i++)
{
char c = str[i];
if (isdigit(c))
{
vals.push(c);
}
else if (c == ' ')
{
c = ' ';
cout << str;
}
else
{
int value1, value2, result;
value2 = vals.top();
vals.pop();
value1 = vals.top();
vals.pop();
switch (str[i])
{
case '+':
result = value1 + value2;
mystack.push(result);
break;
case '-':
result = value1 - value2;
mystack.push(result);
break;
case '*':
result = value1 * value2;
mystack.push(result);
break;
case '/':
result = value1 / value2;
mystack.push(result);
break;
}
cout << "result is " << mystack.top();
}
}
}
i expect the actual answers, but i guess the program is not ignoring
the space and when i input the string without spaces theres still a
wrong output

Pay attention that the provided algorithm works only if it gets postfix expression, and not a infix expression.
First problem:
Now, have a look on the following line:
vals.push(c);
c is a char, and vals is an integers stack. When c presenting 1 in your code, the c++ compiler actually see '0' + 1. For example:
For the input 23+, you'll get the result: 101. Why?
'2' != 2 and '3' != 3. Actually the calculation is:
'0' + 2 + '0' + 3, which means 48 + 2 + 48 + 3 because '0' == 48 in ascii code.
To fix this little problem, all you have to do is to decrease the inserted value into the vals stack by '0':
vals.push(c - '0');
Now the result for the input 23+ is: 5.
Second problem:
You are using two stacks instead of one that actually needed. When you push the result value into the second stack (mystack), you actually can't get an access to it (or rather say make it more complicated to use it's value) whenever you will get another part of expression, for example:
23+5*
You can debug this case (use watch table/debug code feature of the IDE you are working with) and see that you are trying to access the 5 of the first result, and get nothing left in the first stack, because the result stored in the second one. Solution: use single stack.
case '+':
result = value1 + value2;
//mystack.push(result);
vals.push(result);
break;
General Improvements
function: isdigit
The first thing I would advice you to do, is to remove the if statement- you don't need it. The following code will do the trick:
bool isdigit(char c) {
return c >= '0' && c <= '9';
}
If this sentence will give you true, the function will return true, otherwise it will return false.
The second thing, is like the comments says, this function already exists in the standard c++ library. Just use:
#include <cctype>
And remove your implementation to this function. The same function with the same name already exists: http://www.cplusplus.com/reference/locale/isdigit/
Important!
This answer was given due to extra time in my life and a boring situation I'm in, but more importantly because I think that it can help to understand how to debug code and to solve future (and more complicated) cases. This kind of questions are Debug questions type. You don't actually have to look here for the answer, but to debug you code and to see what's wrong. Please use the tools you got here wisely, and Good Luck!
EDIT:
For more c++ style solution, in higher difficult level, you can see the following solution (consider it like welcome saying from c++):
int evaluate(string str) {
// [] () -> {} ====> READ ABOUT: Lambda expressions
stack<int> vals;
/*
* pop
* ---
* Returns the top value of a stack, and the pop it from the stack.
*/
auto pop = [] (stack<int> &s) -> int {
int res = s.top();
s.pop();
return res;
};
/*
* op
* --
* Returns a function that execute the selected operator on two integers params.
*/
auto op = [] (char op) -> std::function<int(int, int)> {
switch (op) {
case '+':
default : return [] (int a, int b) -> int { return a + b; };
case '-': return [] (int a, int b) -> int { return a - b; };
case '*': return [] (int a, int b) -> int { return a * b; };
case '/': return [] (int a, int b) -> int { return a / b; };
}
};
/*
* for_each is a loop implementation in c++ as part of the standard library (std).
* It's get the first iterator place (str.begin()), end iterator place (str.end()), and function to execute on
* each value in the collection (between start and end iterators).
*/
std::for_each(str.begin(), str.end(), [&vals, pop, op] (char c) {
if (isdigit(c)) vals.push(c - '0');
else if (c != ' ') vals.push(op(c)(pop(vals), pop(vals)));
// op(c) -> returns a function according to the operator
// op(c)(n1, n2) -> use the returned operator on n1 and n2
// pop(vals) -> function that returns the top value of the stack, and then pop it from the stack.
// op(c)(pop(vals), pop(vals)) -> apply the selected op on the first two values in the stack
});
cout << "The result is: " << vals.top() << endl;
}

Related

How to replace characters of a string in c++ with a recursive function?

Hello I'm a beginner in cpp programming. I was reading some examples of cpp programs and i see this question but i couldn't solve it :
There's an algorithm below starting from 0 as each step that goes forward you should replace all 0's with 01 and 1's 10. The input is the number of stage and the output is the number that generates solve this with recursive function.
Here is the example:
1)0
2)01
3)0110
...
Input:3
Output:0110
I tried this:
string generate(string &algorithm, int n) {
if (n <= 0)
return algorithm;
//confused?
}
int main() {
string algorithm = "0";
string new_algorithm;
long long int n, k;
cin >> n >> k;
new_algorithm = generate(algorithm, n);
return 0;
}
It should be in recursive form but I can't do it straight too!
Any help would be appreciated!
The number of recusions is given so the function will look something like this:
std::string replace_recursive(const std::string& in, int n) {
if (n <= 0) return in;
std::string next = replace(in);
return replace_recursive(next,n-1);
}
It has a stop condition, it executes a single step (by calling replace) and it has the recursive call.
All you need to add is going from in to next. For this it is easiest to use a range based loop and construct the new string by appending. I am trying to not give away the whole solution:
std::string replace(const std::string& in) {
std::string result;
for (const auto& c : in) {
if (c == ....) result += " ... ";
else if (c = ....) result += " .... ";
}
return result;
}

Evaluate infix string expression consisting of only addition and multiplication

How can I evaluate an infix string expression which only consists of + and * operators. (No parenthesis).
Example 1:
Input: "1+2*3"
Output: 7
Example 2:
Input: "1+2*3+4"
Output: 11
Here is my code I have so far (which is not giving correct result), I wonder if I can do it with one stack (or none)
int evaluateExpression(string s) {
stack<int> operandStack;
stack<char> operatorStack;
string token = "";
for(char &c : s) {
if(c == '*' || c == '+') {
operandStack.push(stoi(token));
operatorStack.push(c);
token = "";
}
else {
token += c;
}
if(operandStack.size() > 1
&& operandStack.size() == operatorStack.size() + 1
&& operatorStack.top() == '*') {
int a = operandStack.top(); operandStack.pop();
int b = operandStack.top(); operandStack.pop();
operandStack.push(a * b);
}
}
while(operandStack.size() > 1) {
int a = operandStack.top(); operandStack.pop();
int b = operandStack.top(); operandStack.pop();
operandStack.push(a + b);
}
return operandStack.top();
}
Note: do not want to use any non-standard libraries. Ideally with no use of any library.
Yes, you do need only one stack. You can use the standard approach with a shift-reduce parser. In your case, and the simple grammar, this may be already a little bit too much. But I will describe it anyway.
The secret is to use a "parse stack". So only one stack. Not an operator and operand stack. There you will use attributed tokens. A token has a type, like ADD, MULT, NUMBER and, an associated attribute. The attribute is usually a union or a struct. It would be empty for ADD and MULT and would contain a value for NUMBER.
The scanner, which has usually the function getNextToken will produce your tokens. In your case, extremely simple, just those 3 tokens.
Then, in a loop, you will do always the following actions.
Always push the fresh token onto the parse stack
Try to match the top of the stack with a production of the grammar (and look ahead token)
Reduce the stack (Remove matched elements), evaluate the expression, and put the result on the parse stack
So, always: Shift, Match, Reduce
In your case you need for the match function one lookahead symbol, so, the next token. You will find exactly such an example here. There you can find a compiler, with one front end (Scanner, Parser) and 2 different code generators as back end. The code generators are not needed for you task, you can directly evaluate while reducing.
But, for such an easy grammar, you do not need a stack at all. In the book crafting A Compiler with C is a good example. My copy of the book is from 1991, but of course the content is still valid.
They basically write a function for each production/terminal/non-terminal in the grammar and evaluate the tokens and call the functions of other terminals or non-terminals. Interesting approach and not difficult for your use case.
Hope this helps a little . . .
int evaluateExpression(string s) {
string token = "";
char currOperator = '+';
stack<int> st;
string temp = s + '.';
for(const char &c : temp) {
if(isdigit(c)) {
token += c;
}
else if(c != ' ') {
if(currOperator == '*') {
int stackTop = st.top();
st.pop();
st.push(stackTop * stoi(token));
}
else if(currOperator == '+') {
st.push(stoi(token));
}
token = "";
currOperator = c;
}
}
int result = 0;
while(!st.empty()) {
result += st.top();
st.pop();
}
return result;
}

Failing to parse different math operators

This question is a follow-up from this one. Basically I'm trying to make a parser which calculates the total result of a string. 5+5+3*2/1 should give 16. This already works for strings only containing plusses and mins, so -55-44+1-2+123-54442+327737+1-2 successfully gives 273317.
It however does not work when plusses/mins get mixed with times/divides. So 1*2-2*3 returns 6 instead of -4. I think this is because I try to respect the order in which math needs to be executed (first plusses and mins, than times and division), but the operator somehow doesn't get updated.
#include <iostream>
#include <string>
#include <algorithm>
//Enumeration of all the possible
//math operators
enum Operator {
PLUS,
MIN,
TIMES,
DIVIDE,
UNDEFINED
};
/************************IGNORE********************/
char operatorToChar(Operator o) {
switch(o) {
case Operator::PLUS:
return '+';
break;
case Operator::MIN:
return '-';
break;
case Operator::TIMES:
return '*';
break;
case Operator::DIVIDE:
return '/';
break;
default:
return '0';
break;
}
}
/***************************************************/
/*
* Function to check if there are still times- or divide-operators in the action string.
* This to respect the order of math (first times and divides, than plusses and mins)
*
* :param action: The action string
* :return bool: Returns true if a '*' or '/' is found
*/
bool timesAndDividesGone(std::string& action) {
for (char& c : action) {
if (c == '*' || c == '/') {
return false;
}
}
return true;
}
/*
* Function to convert char to Operator
* :param c: One of the following '+', '-', '*', '/'
* :return Operator: Operating matching the character
*/
Operator charToOperator(char c) {
switch(c) {
case '+':
return Operator::PLUS;
break;
case '-':
return Operator::MIN;
break;
case '*':
return Operator::TIMES;
break;
case '/':
return Operator::DIVIDE;
break;
default:
return Operator::UNDEFINED;
break;
}
}
/*
* Function to do maths on two numbers, the math to do is decided by the operator
* :param x: First number
* :param y: Second number
* :param o: Operator (Plus, Min, Times or Divide)
* :return double: Result of the calculation
*
* Example:
* math(5, 5, Operator::Plus) == 10
*
*/
double math(double x, double y, Operator o) {
double z = 0;
switch (o) {
case Operator::PLUS:
z = x + y;
break;
case Operator::MIN:
z = x - y;
break;
case Operator::TIMES:
z = x * y;
break;
case Operator::DIVIDE:
z = x / y;
break;
}
return z;
}
/*
* Recursive function performing all the calculations from an action string.
* For example, if the string actions has value "5+7" in the first recursive run
* result should contain 12 after the last recursion.
*
* :param result: Double containing the calculated result after the last recursion
* :param actions: Action string (what you type in your calculator; e.g: 5+5). We analyze the first character of this string each time and add it to first_nr, second_nr, or make it the operator. First character gets deleted after each recursion
* :param first_nr: Empty at first recursion, number of left side of the operator. So in 55+77 this paramater will be "55". Gets resetted at the next operator
* :param second_nr: Idem as first_nr but for the right side of the operator.
* :param oper: Operation to calculate the first_nr and second_nr
*/
double calculate(double& result, std::string& actions, std::string& first_nr, std::string& second_nr, Operator& oper) {
//DEBUG OUTPUT:
std::cout << actions << " Gives ";
std::cout << std::to_string(result) << std::endl;
//Base-condition:
//If action string is empty return
if (actions == "") {
//Scenario for when first action is an operator
//e.g: 1+1-
if (second_nr == "")
second_nr = "0";
//Update result
result = math(std::stod(first_nr), std::stod(second_nr), oper);
return result;
}
//Get first character from action string
char c = actions[0];
//Making sure order of math is respected (first times and divdes)
//and than plus and min
char operatorInChar[4] = {'*', '/'};
if (timesAndDividesGone(actions)) {
operatorInChar[2] = '+';
operatorInChar[3] = '-';
}
//If first character is an operator
if (std::find(std::begin(operatorInChar), std::end(operatorInChar), c) != std::end(operatorInChar)) {
//Scenario for when first action is an operator
//e.g: -1+1
if (first_nr == "") {
if (actions[1] == '*')
first_nr = "1";
else
first_nr = "0";
}
//If operator is not yet set in a previous recursion
if (oper == Operator::UNDEFINED) {
oper = charToOperator(c);
//If second_nr is not empty, we need to calculate the two numbers together
if (second_nr != "") {
//Update result
result = math(std::stod(first_nr), std::stod(second_nr), oper);
}
} else {
//Update result
result = math(std::stod(first_nr), std::stod(second_nr), oper);
first_nr = std::to_string(result);
second_nr = "";
//Remove first character from action string because it's analysed in this recursion
actions = actions.erase(0, 1);
oper = charToOperator(c);
return calculate(result, actions, first_nr, second_nr, oper);
}
} else {
//If the character is not a operator but a number we append it to the correct nr
//we add to first_nr if the operator is not yet set, if we already encountered an operator
//we add to second_nr.
//e.g: actions = "123+789"
if (oper == Operator::UNDEFINED) {
first_nr += c;
} else {
second_nr += c;
}
}
//Remove first character from action string because it's analysed in this recursion
actions = actions.erase(0, 1);
//DEBUG OUTPUT:
//std::cout << first_nr << operatorToChar(oper) << second_nr << std::endl;
//std::cout << std::endl << actions << " Gives ";
//std::cout << std::to_string(result) << std::endl;
//Make recursive call
return calculate(result, actions, first_nr, second_nr, oper);
}
int main() {
//String we want to calculate
std::string str = "1*2-2*3";
std::string str_copy_for_output = str;
//Variables
double result = 0;
std::string first_nr = "";
std::string second_nr = "";
Operator oper = Operator::UNDEFINED;
//Call function
int calculation = calculate(result, str, first_nr, second_nr, oper);
//Output
std::cout << std::endl << str_copy_for_output << " = " << calculation << std::endl;
return 0;
}
tl;dr
This code works perfectly for strings only containing plusses and mins or only times and divides. Combining times and divides messes it up. Probably the operator parameter fails to update. How to fix this?
I'm sorry if I did not not analyze your code in detail because it is way too much complicated for what you are trying to do. Therefore I will not tell you where is exactly the problem, instead I will propose you something more simple.
One way or another you need to manage a stack because an algebraic expression must be handled as a tree structure and the evaluation process has to follow that structure. It can't be handled as a flat structure and you can't escape the management of operator precedence. In addition to that an expression is normally evaluated from left to right (left associativity).
That said if you really don't want to use a parsing tool (which IMHO would be more simple and clean), it is always possible to parse "manually". In that case you may avoid to manage an explicit stack by using the call stack itself as demonstrated in the following code:
#include <iostream>
int precedenceOf(char op) {
switch (op) {
case '+':
case '-':
return 4;
case '*':
case '/':
return 3;
}
return 0; // never happen
}
const int MAX_PRECEDENCE = 4;
double computeOp(double left, double right, char c) {
switch (c) {
case '+': return left + right;
case '-': return left - right;
case '*': return left * right;
case '/': return left / right;
}
return 0; // never happen
}
char readOperator(const char*& expr)
{
// read the operator
while (*expr != 0) {
switch (*expr) {
case '+':
case '-':
case '*':
case '/':
{
char res = *expr;
expr++;
return res;
}
case ' ':
break;
}
expr++;
}
return 0;
}
double readOperand(const char*& expr)
{
double result = 0;
while (*expr != 0 && *expr == ' ') expr++;
while (*expr != 0) {
if (*expr >= '0' && *expr <= '9')
result = result * 10 + *expr - '0';
else
return result;
expr++;
}
return result;
}
double eval(const char*& expr, int breakPrecedence = MAX_PRECEDENCE + 1);
// evalRight function reads the right part of an expression and evaluates it
// (up to the point where an operator with precedence 'breakPrecedence' is reached)
// returns the computation of the expression with the left operand passed as parameter.
double evalRight(const char*& expr, int breakPrecedence, double leftOperand)
{
do
{
auto posBeforeOp = expr;
auto op = readOperator(expr);
if (op == 0)
return leftOperand; // end of expression reached, meaning there is no right part
auto prec = precedenceOf(op);
if (prec >= breakPrecedence)
{
expr = posBeforeOp; // we backtrack before the operator (which will be handled by one of our caller)
return leftOperand;
}
// reads and evaluates the expression on the right hand side
auto rightOperand = eval(expr, prec);
// computes the current operation, the result becoming the new left operand of the next operation
leftOperand = computeOp(leftOperand, rightOperand, op);
} while (true);
}
// eval function reads an expression and evaluates it (evaluates it up to the point where an operator with precedence 'breakPrecedence' is reached)
// returns the evaluation of the expression
double eval(const char*& expr, int breakPrecedence)
{
auto leftOperand = readOperand(expr);
return evalRight(expr, breakPrecedence, leftOperand);
}
int main()
{
auto expression = "1 + 1 * 2 - 2 * 3 + 1";
std::cout << "result = " << eval(expression); // prints: result = -2
return 0;
}
To keep the code as simple as possible the provided expression is assumed to be syntactically correct. It's up to you to add some checks if you want.
Hope this helps.
As you said
I'd like to craft something of my own, this is not production-code. Just hobby.
so probably you want to learn a thing or two. That's why I won't write any code here and steal all the fun from you.
Looks like you should start from the basics. I could've recommend you the Dragon Book but you probably want to get your hands dirty right away instead of reading the classics for a week. So you can start with PEGs - it's really simple.
I've started to love parsing after I've read this article.
In your case the grammar will be quite simple:
Expr ← Sum
Sum ← Product (('+' / '-') Product)*
Product ← Value (('*' / '/') Value)*
Value ← [0-9]+
With functions you can rewrite it like this
value = repeat_at_least_once(character("0"),...,character("9"))
product = sequence(value , repeat(one_of(character("*"),character("/")), value )
expr = sequence(product, repeat(one_of(character("+"),character("-")), product)
All you have to do now - write these functions :) It will be not much longer than the code you've written, if not shorter.
If you fill confident, you can even implement packrat parsing with left recursion support, in this case you grammar will be even simpler.
IMHO, your current approach (doing multiplications and divisions first, then continuing with addition and subtraction, and all in one function) will be painful at best. Your calculate function is very hard to reason about already, because it mixes multiple cases already, e.g.
first pass or second pass (depending on the content of string action, which is the current status of the expression, which you modify from call to call)
first_nr empty/filled
second_nr empty/filled
Now imagine that more operators are added, like ^ and ( and ). I do understand that this is a hobby project. But even if you get this to work one day, you will not be able to understand it a week later.
Since you want to reuse your current code, how about this:
Think about how you yourself (as a human being) would go about this? There are multiple approaches. Independent of the specific algorithm they consist of two parts:
Tokenization (identifying numbers and operators)
Evaluation (combine those numbers and operators)
You are mixing both parts in your code. It would be much simpler for you and anybody you are asking for help if you separated them.
Tokenization is simple (you are doing it already, although I would recommend to treat the expression string as read-only).
Evaluation is more tricky, because you have to think about operator precedence. But again, it helps to think about how you would do it as a human. You might read from left to right. How do you handle that as a person? You might evaluate sub expressions with higher precedence first (as you intend to do now). How do you store the tokens? Think of different data structures. Lists, stacks, or queues for examples.
There are many ways. Once you found one, looking at some literature should be fun.
Enjoy!
While I clearly stated I did not want a postfix solution, I actually realized it's the most sane solution. I made a postfix solution myself with the help of tutorials (and still learnt a lot!). Thanks everyone for the help and suggestions.
#include <iostream>
#include <string>
#include <stack>
/*
* Function to check if a given character is an operator (+, -, *, /) or not
* :param c: Character to check
* :return bool: Returns true if parameter c is an operator
*/
bool isOperator(char c) {
char operators[4] = {'+', '-', '*', '/'};
if (std::find(std::begin(operators), std::end(operators), c) != std::end(operators)) {
return true;
}
return false;
}
/*
* Function to get the precedence matching the character
*
* :param a: Character containing the operator to get precedence from
* :return int: Integer representing precedence. Operators with high precedence (e.g * and /) return a higher value than e.g + and -.
*
* Example:
* precedence('*') > precedence('+') == true
*
*/
int precedence(char a) {
switch (a) {
case '+': return 1;
break;
case '-': return 1;
break;
case '*': return 2;
break;
case '/': return 2;
break;
}
return -1;
}
/*
* Function to convert an infix string to postfix notation
* :param infix: Infix string
* :return string: returns postfix string
*
* Example:
* std::string s = "5+5";
* toPostfix(s) == "5 5 +"
*
*/
std::string toPostfix(std::string& infix) {
std::string postfix = "";
//Stack to hold operators and nr is a helper string to
//group digits in numbers
std::stack<char> stack;
std::string nr = "";
//If first character is a minus-operator (AKA a negative number)
//add "0"
if (infix[0] == '-') {
infix = "0" + infix;
}
//Looping over infix string
for (int i = 0; i < infix.size(); i++) {
//If current evaluated character ain't an operator, it's a digit
if (!isOperator(infix[i])) {
//If digit is in a group of digits (AKA a number) put the whole number in nr
while (!isOperator(infix[i]) && i < infix.size()) {
nr += infix[i];
i++;
}
i--;
//Append the number to the postfix string
postfix += nr + " ";
nr = "";
} else {
//This block is executed when evaluated character is an operator
//If stack is empty, or the evaluated operator is higher than the one in the stack
//push it to the stack (Needs to be appended to the postfix string later)
if (stack.size() == 0 || precedence(infix[i]) > precedence(stack.top())) {
stack.push(infix[i]);
} else {
//While the stack contacts a higher or equally high precedence as currently
//evaluated operator
while (precedence(stack.top()) >= precedence(infix[i])) {
//We append the top of the stack to the postfix string
postfix += stack.top();
postfix += ' ';
stack.pop();
if (stack.size() == 0) {
break;
}
}
//Push evaluated operator to stack
stack.push(infix[i]);
}
}
}
//Append all remaining operators to the postfix string
while (stack.size() != 0) {
postfix += stack.top();
stack.pop();
}
return postfix;
}
/*
* Evaluate two numbers regaring the used operator
* :param x: First number to do evaluation with
* :param y: Second number to do evaluation with
* :param _operator: Operator to do calculation with
* :return double: Result of the evaluation
*
* Example:
* x: 5
* y: 60
* _operator: +
* = 65
*/
double evaluate(double x, double y, char _operator) {
switch(_operator) {
case '+':
return x + y;
break;
case '-':
return x - y;
break;
case '*':
return x * y;
break;
case '/':
return x / y;
break;
}
return 0;
}
/*
* Calculate the result of an infix string
* :param s: String containing the infix notation
* :return double: Result of the calculation
*
* Example:
* std::string s = "5+5";
* calculate(s) == 10
*/
double calculate(std::string& s) {
//Convert infix to postfix
s = toPostfix(s);
//Stack holding operators and nr (string) for separating numbers
std::stack<double> stack;
std::string nr = "";
//Looping over postfix string
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') {
continue;
}
//If evaluated character is a digit,
//put it in nr
if (isdigit(s[i])) {
//If digit is first of a group of digits, put that group of digits
//AKA a number in nr
while (isdigit(s[i])) {
nr += s[i];
i++;
}
i--;
//Pushing nr in stack
stack.push(std::stod(nr));
nr = "";
} else {
//If current evaluated character is not a digit
//but an operator, do a calculation
//Retrieve first number for calculation
int x = stack.top();
stack.pop();
//Retrieve second number for calculation
int y = stack.top();
stack.pop();
//Put evaluation result in integer and push into stack
int result = evaluate(y, x, s[i]);
stack.push(result);
}
}
//Final number is in stack
return stack.top();
}
int main() {
std::string s = "-5*5-2*2+3-10/5";
std::cout << calculate(s) << std::endl;
}
you need divided calculation for several steps
copy expression to writable memory and check/normalize it:
.check that all chars valid (positive)
.remove spaces
.convert all to low (or upper) case (if case you use hex expressions)
.some operators take 2 symbols ( ==, !=, >=, <=, <<, >>, ||, && ) - replace it to single symbol, from not valid (negative) range
remove ( ) if exist - calculate expressions in ():
.find first ) symbol from begin
.find last ( before it.
.check that after ) and before ( was separator symbols (operator or begin/end of string) but not digit.
.format new string where you replace (..) with it digital result
remove (calculate) all unary operators (+, -, !, ~)
.unary operators - on right side must have digit and on left - another operator(or begin of string), but not digit
.format new string with result of unary operator
remove (calculate) all binary operators.
.we need calculate in reverse precedence - so first need calculate/remove operators with lowest precedence.
.so need do loop by operators (from low to high precedence) - search operator symbol in string.
.if found - A op B - calculate separate A and B and then apply op.
convert string to integer
.now, after all ( ) and operators removed - only digit must be in string
example of code:
namespace Eval
{
typedef INT_PTR (* fn_b_op)(INT_PTR a, INT_PTR b);
typedef INT_PTR (* fn_u_op)(INT_PTR a);
struct b_op_arr { fn_b_op pfn; char c; };
struct u_op_arr { fn_u_op pfn; char c; };
struct name_to_char { char b[3]; char c;};
static INT_PTR fn1_bnt(INT_PTR a){ return !a; }
static INT_PTR fn1_not(INT_PTR a){ return ~a; }
static INT_PTR fn1_add(INT_PTR a){ return +a; }
static INT_PTR fn1_sub(INT_PTR a){ return -a; }
static INT_PTR fn2Land(INT_PTR a,INT_PTR b){ return a && b; }
static INT_PTR fn2_Lor(INT_PTR a,INT_PTR b){ return a || b; }
static INT_PTR fn2_equ(INT_PTR a,INT_PTR b){ return a == b; }
static INT_PTR fn2_nqu(INT_PTR a,INT_PTR b){ return a != b; }
static INT_PTR fn2_lqu(INT_PTR a,INT_PTR b){ return a < b; }
static INT_PTR fn2_gqu(INT_PTR a,INT_PTR b){ return a > b; }
static INT_PTR fn2_leu(INT_PTR a,INT_PTR b){ return a <= b; }
static INT_PTR fn2_geu(INT_PTR a,INT_PTR b){ return a >= b; }
static INT_PTR fn2_add(INT_PTR a,INT_PTR b){ return a + b; }
static INT_PTR fn2_sub(INT_PTR a,INT_PTR b){ return a - b; }
static INT_PTR fn2_mul(INT_PTR a,INT_PTR b){ return a * b; }
static INT_PTR fn2_div(INT_PTR a,INT_PTR b){ return a / b; }
static INT_PTR fn2_dv2(INT_PTR a,INT_PTR b){ return a % b; }
static INT_PTR fn2_lsh(INT_PTR a,INT_PTR b){ return (UINT_PTR)a << b; }
static INT_PTR fn2_rsh(INT_PTR a,INT_PTR b){ return (UINT_PTR)a >> b; }
static INT_PTR fn2_xor(INT_PTR a,INT_PTR b){ return a ^ b; }
static INT_PTR fn2_and(INT_PTR a,INT_PTR b){ return a & b; }
static INT_PTR fn2__or(INT_PTR a,INT_PTR b){ return a | b; }
enum /*: char*/ { equ = -0x80, not_equ, less_equ, gre_equ, l_or, l_and, r_shift, l_shift };
inline static b_op_arr b_arr[] =
{
{fn2_mul, '*'}, {fn2_div, '/'}, {fn2_lsh, l_shift}, {fn2_rsh, r_shift},
{fn2_xor, '^'}, {fn2_dv2, '%'}, {fn2_and, '&'}, {fn2__or, '|'},
{fn2_equ, equ}, {fn2_nqu, not_equ}, {fn2_lqu, '<'}, {fn2_gqu, '>'},
{fn2_leu, less_equ},{fn2_geu, gre_equ},{fn2_add, '+'}, {fn2_sub, '-'},
{fn2Land, l_and}, {fn2_Lor, l_or}
};
inline static u_op_arr u_arr[] =
{
{fn1_add, '+'}, {fn1_sub, '-'}, {fn1_bnt,'!'}, {fn1_not,'~'}
};
inline static name_to_char _2_to_1[] =
{
{"==", equ}, {"!=", not_equ}, {"<=", less_equ}, {">=", gre_equ },
{">>", r_shift}, {"<<", l_shift}, {"||", l_or}, {"&&", l_and},
};
void initBits(LONG bits[], const char cc[], ULONG n)
{
do
{
_bittestandset(bits, cc[--n]);
} while (n);
}
static bool IsSeparatorSymbol(char c)
{
static LONG bits[8];
static bool bInit;
if (!bInit)
{
// acquire
static const char cc[] = {
'*', '/', '+', '-', '^', '%', '&', '|', '<', '>', '!', '~', '(', ')',
equ, not_equ, less_equ, gre_equ, l_or, l_and, r_shift, l_shift, 0
};
initBits(bits, cc, _countof(cc));
// release
bInit = true;
}
return _bittest(bits, c);
}
static bool IsUnaryOpSymbol(char c)
{
static LONG bits[8];
static bool bInit;
if (!bInit)
{
// acquire
static char cc[] = {
'+', '-', '!', '~'
};
initBits(bits, cc, _countof(cc));
// release
bInit = true;
}
return _bittest(bits, c);
}
static bool IsDigit(char c)
{
static LONG bits[8];
static bool bInit;
if (!bInit)
{
// acquire
static char cc[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
initBits(bits, cc, _countof(cc));
// release
bInit = true;
}
return _bittest(bits, c);
}
__int64 strtol64_16(char* sz, char** psz)
{
__int64 r = 0;
while (char c = *sz)
{
ULONG d;
if ((ULONG)(c - '0') <= '9' - '0')
{
d = (c - '0');
}
else if ((ULONG)(c - 'a') <= 'z' - 'a')
{
d = (c - 'a') + 10;
}
else
{
break;
}
r = (r << 4) + d;
sz++;
}
*psz = sz;
return r;
}
bool Normalize(const char* psz, char* buf, size_t s)
{
int len = 0;
do
{
--s;
char c = *psz++, d;
// is valid char
if (c < 0) return false;
// skip space
if (c == ' ') continue;
if ((ULONG)(c - 'A') < (ULONG)('Z' - 'A'))
{
c += 'a' - 'A';
}
// not last char
if (s)
{
d = *psz;
int k = _countof(_2_to_1);
do
{
if (_2_to_1[--k].b[0] == c && _2_to_1[k].b[1] == d)
{
c = _2_to_1[k].c, psz++, --s;
break;
}
} while (k);
}
*buf++ = c, len++;
} while (s);
return 0 < len;
}
char* format_new_str(const char* a, INT_PTR r, const char* b)
{
static const char format[] = "%s%I64x%s";
int len = _scprintf(format, a, r, b);
if (0 < len)
{
if (char* buf = new char [++len])
{
if (0 < sprintf_s(buf, len, format, a, r, b))
{
DbgPrint("++%p\n\"%s\"\n", buf, buf);
return buf;
}
delete buf;
}
}
return 0;
}
bool _calc (char* str, INT_PTR& result)
{
DbgPrint("\"%s\"\n", str);
struct SB
{
char* str;
SB() : str(0) {}
~SB()
{
operator <<(0);
}
void operator <<(char* psz)
{
if (str)
{
DbgPrint("--%p\n", str);
delete [] str;
}
str = psz;
}
} sb;
size_t len = strlen(str);
if (!len)
{
return false;
}
char b, c;
int l;
INT_PTR r, q;
//1. remove ( )
char *psz = str, *pc = 0, *buf;
for (;;)
{
switch (*psz++)
{
case '(':
pc = psz;
continue;
case ')':
if (!pc || !IsSeparatorSymbol(*psz) || (pc > str + 1 && !IsSeparatorSymbol(pc[-2]))) return false;
psz[-1] = 0, pc[-1] = 0;
if (_calc(pc, r) && (buf = format_new_str(str, r, psz)))
{
sb << buf;
psz = str = buf, pc = 0;
continue;
}
return false;
case 0:
goto __2;
}
}
__2:
//2. remove unary op
psz = str;
do
{
if (IsDigit(c = *psz) && str < psz && IsUnaryOpSymbol(c = psz[-1]) && (psz == str + 1 || IsSeparatorSymbol(psz[-2])))
{
psz[-1] = 0;
l = _countof(u_arr);
do
{
if (u_arr[--l].c == c)
{
r = strtol64_16(psz, &psz);
if (IsSeparatorSymbol(*psz))
{
r = u_arr[l].pfn(r);
if (buf = format_new_str(str, r, psz))
{
sb << buf;
psz = str = buf;
goto __2;
}
}
break;
}
} while (l);
return false;
}
} while (psz++, c);
//3. remove binary op
l = _countof(b_arr);
do
{
c = b_arr[--l].c;
psz = str;
do
{
if (c == (b = *psz++))
{
psz[-1] = 0;
if (_calc(psz, q) && _calc(str, r))
{
result = b_arr[l].pfn(r, q);
return true;
}
return false;
}
} while (b);
} while (l);
result = strtol64_16(str, &str);
return !*str;
}
bool calc(const char* psz, INT_PTR& result)
{
bool fOk = false;
if (size_t s = strlen(psz))
{
if (char* buf = new char[++s])
{
if (Normalize(psz, buf, s))
{
fOk = _calc(buf, result);
}
delete [] buf;
}
}
return fOk;
}
};
use
INT_PTR r;
Eval::calc(str, r);
While reading Learning Go I've implemented some of the suggested training programs. One of which has nearly the same requirements as yours, although I have to admit, that yours is a bit more evolved. So, I hope you can get something out of this code (I know it's not C++, but I'm sure you can read it):
package main
import (
"fmt"
"os"
"bufio"
"stack"
"strconv"
)
func readInput() string {
reader := bufio.NewReader(os.Stdin)
switch in, ok := reader.ReadString('\n'); true {
case ok != nil:
fmt.Printf("Failed to read inputs: %v", ok)
return "error"
default:
return in[:len(in)-1]
}
}
func isdigit(in string) bool {
_,ok := strconv.Atoi(in)
return ok == nil
}
func isOperation(in string) bool {
chars := []rune(in)
return '+' == chars[0] || '-' == chars[0] || '*' == chars[0] || '/' == chars[0]
}
func calc(operation string, op2, op1 int) float32 {
chars := []rune(operation)
switch chars[0] {
case '+':
return float32(op1 + op2)
case '-':
return float32(op1 - op2)
case '*':
return float32(op1 * op2)
case '/':
return float32(op1) / float32(op2)
}
print("Failed to recognize operation: ")
println(operation)
fmt.Printf("%v\n", chars)
return 0.0
}
func main() {
var st stack.Stack
fmt.Println("Calculator.")
fmt.Println("Please input operations and then one of + - * / for calculation,")
fmt.Println("or anything else for exit.")
LOOP: for {
in := readInput()
switch {
case isdigit(in):
i,_ := strconv.Atoi(in)
st.Push(i)
case isOperation(in):
op2 := st.Pop()
op1 := st.Pop()
res := calc(in, op2, op1)
st.Push(int(res))
fmt.Println(res)
default:
fmt.Println("Exit")
break LOOP
}
}
}
... similar, isn't it?

Write a function without using any semicolon

I have a very strange problem in my homework.
So I have to build a function which calculates the sum/difference of two numbers.
It looks fairly easy but there's a catch.
This is the function:
void sumdif()
{
int result = 0;
//input
//output
}
I can't use any semicolons, and this is how the function must look.
Input consists of:
number, + or - (depending if you want to substract or to add) and another number.
The function will output the result.
If I could use semi-colons, it would've been easy.
I have no idea how to resolve this problem in this case, though.
I've thought about using a ternary operator. Unfortunately, I can't see how to take input, output and also differentiate + and - in one line. (and I think I needed ";" anyway so it wouldn't help me).
Here's the problem:
https://www.pbinfo.ro/?pagina=probleme&id=3191
Unfortunately, it is in romanian. You can use google translate for more details, but I've explained the idea.
Through that function you take input, then output the result, and more than that you can't use any semicolon. (this is the hardest part for me - I've never dealt with this before)
How can this problem be solved?
Just performs the operations inside the if condition like in the following:
void sumdif()
{
if (char c = '+') { //declare c
if (cin >> c) { //read c
if (int a = 1) { //declare a
if (cin >> a) { //read a
if (int b = 1) { //declare b
if (cin >> b) { //read b
if (c == '+') { //choose operation
if (cout << (a + b)) { //print sum
}
}
else {
if (cout << (a - b)) { //print difference
}
}
}
}
}
}
}
}
}
LIVE DEMO

Write a recursive function that reverses the input string

I've been reading the book C++ For Everyone and one of the exercises said to write a function string reverse(string str) where the return value is the reverse of str.
Can somebody write some basic code and explain it to me? I've been staring at this question since yesterday and can't figure it out. The furthest I've gotten is having the function return the first letter of str (Which I still don't know how it happened)
This is as far as I got (An hour after posting this question):
string reverse(string str)
{
string word = "";
if (str.length() <= 1)
{
return str;
}
else
{
string str_copy = str;
int n = str_copy.length() - 1;
string last_letter = str_copy.substr(n, 1);
str_copy = str_copy.substr(0, n);
word += reverse(str_copy);
return str_copy;
}
return word;
}
If I enter "Wolf", it returns Wol. Somebody help me out here
If I return word instead of return str_copy then I get a w
If I return last_letter then I get an l
I'll instead explain the recursive algorithm itself. Take the example "input" which should produce "tupni". You can reverse the string recursively by
If the string is empty or a single character, return it unchanged.
Otherwise,
Remove the first character.
Reverse the remaining string.
Add the first character above to the reversed string.
Return the new string.
Try this one
string reverse(string &s)
{
if( s.length() == 0 ) // end condtion to stop recursion
return "";
string last(1,s[s.length()-1]); // create string with last character
string reversed = reverse(s.substr(0,s.length()-1));
return last+reversed; // Make he last character first
}
A recursive function must have the following properties
It must call itself again
It must have a condition when the recursion ends. Otherwise you have a function which
will cause a stack overflow.
This recursive function does basically create a string of the last character and then call itself again with the rest of the string excluding the last character. The real switching happens at the last line where last+reversed is returned. If it would be the other way around nothing would happen.
It is very inefficient but it works to show the concept.
Just to suggest a better way of handling recursion:
String reversal using recursion in C++:
#include <iostream>
#include <string>
using namespace std;
string reverseStringRecursively(string str){
if (str.length() == 1) {
return str;
}else{
return reverseStringRecursively(str.substr(1,str.length())) + str.at(0);
}
}
int main()
{
string str;
cout<<"Enter the string to reverse : ";
cin>>str;
cout<<"The reversed string is : "<<reverseStringRecursively(str);
return 0;
}
I won't write a full-blown algorithm for you, but here's a hint:
How about swapping the two outermost characters, and then apply the same to the characters in the middle?
Oh, and if that book really proposed string reverse(string str) as an appropriate function signature for this, throw it away and buy a good book instead.
Here is my version of a recursive function that reverses the input string:
void reverse(char *s, size_t len)
{
if ( len <= 1 || !s )
{
return;
}
std::swap(s[0], s[len-1]);// swap first and last simbols
s++; // move pointer to the following char
reverse(s, len-2); // shorten len of string
}
Shortest and easiest
class Solution {
public:
string reverseString(string s) {
string str;
if(s != "\0"){
str = reverseString(s.substr(1, s.length()));
str += s.substr(0,1);
}
return str;
}
};
1-line recursive solution:
string RecursiveReverse(string str, string prev = "") {
return (str.length() == 0 ? prev : RecursiveReverse(str.substr(0, str.length()-1), prev += str[str.length()-1]));
}
You call it like this:
cout << RecursiveReverse("String to Reverse");
I know I shouldn't give a solution, but since no one mentioned this easy solution I though I should share it. I think the code literally is the algorithm so there is no need for a pseudo-code.
void c_plusplus_recursive_swap_reverse(std::string::iterator start,
std::string::iterator end)
{
if(start >= end) {
return;
}
std::iter_swap(start, end);
c_plusplus_recursive_swap_reverse(++start, --end);
}
To call it use:
c_plusplus_recursive_swap_reverse(temp.begin(), temp.end());
All existing solutions had way too much code that didn't really do anything, so, here's my take at it:
#include <iostream>
#include <string>
std::string
r(std::string s)
{
if (s.empty())
return s;
return r(s.substr(1)) + s[0];
}
int
main()
{
std::cout << r("testing") << std::endl;
}
P.S. I stumbled upon this question trying to find a C++ way for std::string of what s+1 for a char * in C is; without going the whole route of s.substr(1, s.length()-1), which looks too ugly. Turns out, there's std::string::npos, which means until the end of the string, and it's already the default value for the second argument, so, s.substr(1) is enough (plus, it also looks more efficient and on par with the simple s + 1 in C).
Note, however, that recursion in general doesn't scale as the input grows larger, unless the compiler is able to do what is known as tail-recursion optimisation. (Recursion is rarely relied upon in imperative languages.)
However, in order for the tail recursion optimisation to get activated, it is generally required that, (0), the recursion only happens within the return statement, and that, (1), no further operations are performed with the result of the recursive call back in the parent function.
E.g., in the case above, the + s[0] is logically done by the parent after the child call completes (and it probably would be so even if you go the more uglier s[s.length()-1] + route), so, it might as well prevent most compilers from doing a tail-recursion-optimisation, thus making the function very inefficient on large inputs (if not outright broken due to heap exhaustion).
(For what it's worth, I've tried writing a more tail-recursion-friendly solution (making sure to grow the return result through an argument to the function itself), but disassembly of the resulting binary seems to suggest that it's more involved than that in the imperative languages like C++, see gcc: is there no tail recursion if I return std::string in C++?.)
you can implement your own reverse similar to std::reverse.
template <typename BidirIt>
void reverse(BidirIt first, BidirIt last)
{
if((first == last) || (first == --last))
return;
std::iter_swap(first, last);
reverse(++first, last);
}
I did something like this, it did the reversal in place. I took two variables that traverse the string from two extreme end to the centre of the string and when they overlap or equal to each other then reversal terminates.
Take an example: input string str = "abcd" and call the function as
ReverseString(str,0,str.length()-1);
and increment/decrement the variable pointers recursively.
First the pointers points to 'a' and 'd' and swap them, then they point to 'b' and 'c' and swap them. Eventually i >= j which calls for the base case to be true and hence the recursion terminates. The main take away for this question is to pass input string as reference.
string ReverseString(string& str,int i,int j){
if(str.length() < 1 || str == "" || i >= j){
return "";
}
else{
char temp = str[i];
str[i] = str[j];
str[j] = temp;
ReverseString(str,i+1,j-1);
}
return str;
}
String can be reversed in-place. If we start from smallest possible string i.e. one character string, we don't need to do anything. This is where we stop or return from our recursive call and it becomes our base case.
Next, we have to think of a generic way to swap the smallest string i.e. two characters or more. Simplest logic is to swap the current character str[current_index] with character on the opposite side str[str_length-1 - current_index].
In the end, call the reverse function again for next index.
#include <iostream>
using namespace std;
void reverse_string(std::string& str, int index, int length) {
// Base case: if its a single element, no need to swap
// stop swapping as soon as we reach the mid, hence index*2
// otherwise we will reverse the already reversed string
if( (length - index*2) <= 1 ) {
return;
}
// Reverse logic and recursion:
// swap current and opposite index
std::swap(str[index], str[length-1 - index]);
// do the same for next character (index+1)
reverse_string(str, index+1, length);
}
int main() {
std::string s = "World";
reverse_string(s, 0, s.length());
std::cout << s << endl;
}
There are already some good answer but I want to add my approach with full working Recursive reversing string.
#include <iostream>
#include <string>
using namespace std;
char * reverse_s(char *, char*, int,int);
int main(int argc, char** argv) {
if(argc != 2) {
cout << "\n ERROR! Input String";
cout << "\n\t " << argv[0] << "STRING" << endl;
return 1;
}
char* str = new char[strlen(argv[1])+1];
strcpy(str,argv[1]);
char* rev_str = new char[strlen(str)+1];
cout<<"\n\nFinal Reverse of '" << str << "' is --> "<< reverse_s(str, rev_str, 0, strlen(str)) << endl;
cin.ignore();
delete rev_str, str;
return 0;
}
char* reverse_s(char* str, char* rev_str, int str_index, int rev_index ) {
if(strlen(str) == 1)
return str;
if(str[str_index] == '\0' ) {
rev_str[str_index] = '\0';
return rev_str;
}
str_index += 1;
rev_index -=1;
rev_str = reverse_s(str, rev_str, str_index, rev_index);
if(rev_index >= 0) {
cout << "\n Now the str value is " << str[str_index-1] << " -- Index " << str_in
dex << " Rev Index: " << rev_index;
rev_str[rev_index] = str[str_index-1];
cout << "\nReversed Value: " << rev_str << endl;
}
return rev_str;
}
void reverse(string &s, int &m) {
if (m == s.size()-1)
return;
int going_to = s.size() - 1 - m;
string leader = s.substr(1,going_to);
string rest = s.substr(going_to+1,s.size());
s = leader + s.substr(0,1) + rest;
reverse(s,++m);
}
int main ()
{
string y = "oprah";
int sz = 0;
reverse(y,sz);
cout << y << endl;
return 0;
}
void ClassName::strgRevese(char *str)
{
if (*str=='\0')
return;
else
strgRevese(str+1);
cout <<*str;
}
here is my 3 line string revers
std::string stringRevers(std::string s)
{
if(s.length()<=1)return s;
string word=s.at(s.length()-1)+stringRevers(s.substr(0,s.length()-1));//copy the last one at the beginning and do the same with the rest
return word;
}
The question is to write a recursive function. Here is one approach. Not a neat code, but does what is required.
/* string reversal through recursion */
#include <stdio.h>
#include <string.h>
#define size 1000
char rev(char []);
char new_line[size];
int j = 0;
int i =0;
int main ()
{
char string[]="Game On";
rev(string);
printf("Reversed rev string is %s\n",new_line);
return 0;
}
char rev(char line[])
{
while(line[i]!='\0')
{
i++;
rev(line);
i--;
new_line[j] = line[i];
j++;
return line[i];
}
return line[i];
}
It will reverse Original string recursively
void swap(string &str1, string &str2)
{
string temp = str1;
str1 = str2;
str2 = str1;
}
void ReverseOriginalString(string &str, int p, int sizeOfStr)
{
static int i = 0;
if (p == sizeOfStr)
return;
ReverseOriginalString(str, s + 1, sizeOfStr);
if (i <= p)
swap(&str[i++], &str[p])
}
int main()
{
string st = "Rizwan Haider";
ReverseOriginalString(st, 0, st.length());
std::cout << "Original String is Reversed: " << st << std::endl;
return 0;
}