【发布时间】:2020-03-28 23:24:08
【问题描述】:
如果我有一个字符串 4+6*7/2 我想要一个计算值的函数,在本例中为 25。
为此,我编写了一个递归函数,逐个字符地分析字符串。
基本算法是这样的(或者应该是这样的):
如果我们现在分析的字符是普通密码并且我们没有遇到运算符(+、-、*、/),但我们将它存储在一个名为first_nr 的字符串中,最终将成为左侧的数字运营商。我们会这样做,直到遇到操作员。如果我们遇到一个运算符,我们会存储它是哪个运算符,以便我们知道以后要做什么。因为我们遇到了一个运算符,所以我们现在必须将以下数字添加到另一个名为second_nr 的字符串中,该字符串最终将成为运算符右侧的数字。 [我已经实现到这里] 当然我们还需要考虑计算的顺序,所以我会先忽略所有的加号和分钟,直到分析完所有的时间和除法。
这样,如果我有例如以下操作字符串:
123+789+4。我的函数首先将123 放入first_nr,然后查看运算符并将+ 存储在operator 中。因为operator != NULL 现在它添加了以下数字,即789 到second_str。结合这三个参数,我们可以形成first_nr + operator + second_str,在这种情况下为123+789。我的程序需要在遇到下一个运算符之前执行它,因此在这种情况下它将形成 912+4 并重复递归。
我努力了,但还是有很多漏洞。现在,如果我能让字符串 12+5 运行,我会很高兴。所以忽略除加号之外的所有运算符,忽略计算顺序(第一次和除法,然后是加号和最小值),并忽略一个字符串中的多个运算符。
如果我可以让最基本的字符串运行,我会改进我的算法以处理更复杂的字符串。
我的努力:
#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;
}
问题是result 始终为 0。任何帮助将不胜感激!
【问题讨论】:
-
actions = actions.erase(0, actions.size());这会清除整个字符串,不是吗? -
@O'Niel 你能解释一下这个表达式 4+6*7/2 是如何给出 23 的吗?
-
您可能还想研究递归下降解析器。
-
@VladfromMoscow 25。大声笑对不起。对我来说是深夜。
-
@user3365922 是的,在我的代码中对其进行了编辑。但同样的问题仍然存在。