让我们说我们想对字符串中的表达式求值。为了简单起见,在示例中用(###)
表示的表达式。为了简单起见,我们仅在示例中计算主题标签。表达式可以嵌套。
#include <iostream>
#include <string>
std::string expression{ "(###(##)#(###)##)" };
int countHash(std::string::iterator stringIterator, std::string::iterator stringEnd)
{
int result = 0;
while (stringIterator != stringEnd)
{
if (*stringIterator == '#')
{
result += 1;
}
else if (*stringIterator == '(')
{
result += countHash(++stringIterator, stringEnd);
}
else if (*stringIterator == ')')
{
return result += countHash(++stringIterator, stringEnd);
}
++stringIterator;
}
return result;
}
int main()
{
std::cout << countHash(expression.begin(), expression.end()) << std::endl;
return 0;
}
输出:51
扩展输出:11
所以我的问题是当我从递归调用中返回时,迭代器没有更新。它落后了。该处理多次遍历字符串的各个部分。我该如何处理?
我的主要目标是能够评估这样的表达式:
std::string expr = "(+1 (+22 3 25) 5 (+44 (*3 2)))";
EXPECT(106== evalExpression(expr.begin(), expr.end()));
谢谢。
编辑:
我根据评论中的建议更新了问题。
答案 0 :(得分:0)
#include <string>
#include <iostream>
std::string expression{ "#####-###-##" };
int countHash(std::string::iterator & stringIterator, std::string::iterator stringEnd)
{
int result = 0;
while (stringIterator != stringEnd)
{
switch (*stringIterator++)
{
case '#':
result += 1;
break;
case '-':
result += countHash(stringIterator, stringEnd);
break;
default:
// indicate error ?
break;
}
}
return result;
}
int main()
{
std::string::iterator b = expression.begin();
std::cout << countHash(b, expression.end()) << std::endl;
return 0;
}
答案 1 :(得分:0)
好的,所以在我编辑原始问题时,这是一个解决方案:
#include <iostream>
#include <string>
std::string expression{ "(###((##)#)(#(#)#)#(#))" };
int countHash(std::string::iterator& stringIterator, std::string::iterator stringEnd)
{
int result = 0;
while (stringIterator != stringEnd)
{
if (*stringIterator == '#')
{
result += 1;
}
else if (*stringIterator == '(')
{
result += countHash(++stringIterator, stringEnd);
continue;
}
else if (*stringIterator == ')')
{
++stringIterator;
return result;
}
++stringIterator;
}
return result;
}
int countHash(std::string expression)
{
auto it = expression.begin();
return countHash(it, expression.end());
}
int main()
{
std::cout << countHash(expression) << std::endl;
return 0;
}
输出:11
所以重要的一点是,您需要通过引用传递字符串,以避免在从递归调用返回后多次处理字符串的相同段。
我还遇到的困难是您需要在continue
循环中递归调用之后执行while
。这是因为您不想在递归调用返回后递增stringIterator
。
您也可以使用后增量运算符和switch-case
来完成此操作,就像@bruno在他的回答中所做的那样。那是我的见识。如果您不仅要检查字符,switch-case
是不可能的。您可以使用do-while循环,但我不喜欢这样。
更重要的是,在从)
分支返回之前,您需要增加迭代器。这是因为这是表达式的结尾,如果是递归调用,则您要继续在调用者端使用该表达式。
另一个问题是,如果函数引用了迭代器,则无法传递expression.begin()
。
对于
std::string expr = "(+1 (+22 3 25) 5 (+44 (*3 2)))";
表达式我的解决方案可从https://github.com/bencemeszaroshu/expeval/blob/master/expeval/expeval.cpp获得。我现在不喜欢它,但是稍后我将尝试对其进行改进。 (很高兴听到建议。)但是它正在工作。感谢大家的帮助,我将@bruno回答标记为已接受,因为它对我的帮助最大。