问题
If I have a string 4+6*7/2
I want a function which calculates the value, in this case 25.
To achieve this I have written a recursive function which analyses the string character by character.
The basic algorithm goes (or should go) like this:
If the character we analyse now is a normal cipher and we haven't encountered an operator (+, -, *, /) yet we store it in a string called first_nr
, which will eventually become the number on the left side of the operator. This we do until we encounter an operator. If we encounter an operator we store which operator it was so we know what to do later. Because we have encountered an operator, we now have to add the following numbers to another string called second_nr
which will eventually become the number on the right-side of the operator. [I have implemented until here] Of course we also need to take the order of calculations in consideration, so I'd first ignore all the plusses and mins until all the times and divides are analyzed.
This way if I have for example the following action string:
123+789+4
. My function would first put 123
in first_nr
, then see an operator and store the +
in operator
. Because operator != NULL
now it adds the following numbers, being 789
to second_str
. Combining those three parameters we could form first_nr + operator + second_str
in this case 123+789
. My program needs to execute that before it encounters the next operator so it will form in this case 912+4
and the recursion repeats.
I did an effort but it still has a lot of holes in it. For now I would be happy if I could get the string 12+5
running. So ignore all operators besides plus, ignore the order of calculations (first times and divide, than plus and min), and ignore multiple operators in one string.
If I can get the most basic string running I'll improve my algorithm to also work with more complex strings.
My effort:
#include <iostream>
#include <string>
#include <algorithm>
//Enumeration of all the possible
//math operators
enum Operator {
PLUS,
MIN,
TIMES,
DIVIDE,
UNDEFINED
};
/************************IGNORE********************/
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;
}
}
/***************************************************/
/*
* 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
*/
int calculate(double& result, std::string& actions, std::string& first_nr, std::string& second_nr, Operator& oper) {
//Base-condition:
//If action string is empty return
if (actions == "") {
return result;
}
//Get first character from action string
char c = actions[0];
//If first character is an operator
char operatorInChar[] = {'+', '-', '*', '/'};
if (std::find(std::begin(operatorInChar), std::end(operatorInChar), c) != std::end(operatorInChar)) {
//If operator is not yet set in a previous recursion
if (oper == NULL || 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 = std::stod(first_nr) + std::stod(second_nr); //For now we only implement plus
//Calculation is done, so reset first_nr, second_nr and operator
//for the next 'first_nr [operator] second_nr' block in the action string
first_nr = "";
second_nr = "";
oper = Operator::UNDEFINED;
}
}
} 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 == NULL || 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);
//Make recursive call
return calculate(result, actions, first_nr, second_nr, oper);
}
int main() {
//String we want to calculate
std::string str = "5+7";
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 << str_copy_for_output << " = " << calculation << std::endl;
return 0;
}
The problem is that the result
is always 0. Any help would be appreciated!
回答1:
Step through the program (with a debugger, printf
s here and there, or mentally at least). Several interesting points, in order:
- oper is UNDEFINED (it can’t be NULL btw as it’s not a pointer; a compiler could warn you), first_nr is "", second_nr is "", actions is "5+7".
first_nr += c;
is executed.- oper is UNDEFINED, first_nr is "5", second_nr is "", action is "+7".
oper = charToOperator(c);
is executed.- oper is PLUS, first_nr is "5", second_nr is "", action is "7".
Whoops! "+" is not in actions
anymore, so actions[0]
will never be found in operatorInChar
and that branch will not be executed anymore. You probably need to additionally execute it at end of string.
来源:https://stackoverflow.com/questions/60908275/recursive-function-to-convert-a-string-containing-math-to-integer