C++ 需要了解递归前缀计算器的帮助吗

C++ 需要了解递归前缀计算器的帮助吗,c++,recursion,prefix,evaluator,C++,Recursion,Prefix,Evaluator,这是我在教科书中找到的一段代码,用于使用递归计算前缀表达式。我很难理解这段代码以及它所经历的过程 char *a; int i; int eval() { int x = 0; while (a[i] == ' ') i++; if (a[i] == '+') { i++; return eval() + eval(); } if (a[i] == '*') { i++; retu

这是我在教科书中找到的一段代码,用于使用递归计算前缀表达式。我很难理解这段代码以及它所经历的过程

    char *a; int i;
    int eval()
      { int x = 0;
        while (a[i] == ' ') i++;
        if (a[i] == '+')
          { i++; return eval() + eval(); }
        if (a[i] == '*')
          { i++; return eval() * eval(); }
        while ((a[i] >= '0') && (a[i] <= '9'))
           x = 10*x + (a[i++] - '0');
        return x;
      }
char*a;int i;
int eval()
{int x=0;
而(a[i]='')i++;
如果(a[i]=='+')
{i++;返回eval()+eval();}
如果(a[i]='*')
{i++;返回eval()*eval();}

而((a[i]>='0')&&(a[i]理解递归示例的最佳方法是通过一个示例:

char* a = "+11 4"
首先,
i
被初始化为0,因为没有默认的初始值设定项。
i
也是全局的,因此对它的更新将影响
eval()
的所有调用

没有前导空格,因此第一个while循环条件失败。第一个if语句成功,
i
将递增为1,并执行
eval()+eval()
。我们将一次对这些条件求值,然后在得到结果后返回

i = 1, a[1] = '1'
同样,没有前导空格,因此第一个while循环失败。第一个和第二个if语句失败。在最后一个while循环中,“1”介于0和9之间(基于ascii值),因此
x
变为0+a[1]-“0”,或0+1=1。重要的是
i
a[i]之后递增读取
,然后增加i。while循环的下一次迭代将添加到x。这里x=10*1+a[2]-“0”或10+1=11。使用正确的
x值
,我们可以退出
eval()
,并返回第一个操作数的结果,这里也是11

i = 2, a[2] = '4'
与前一步一样,在eval()调用中执行的唯一语句是最后一个while循环。x=0+a[2]-“0”,或0+4=4。因此,我们返回4


此时,控制流返回到对eval()的原始调用,现在我们有了操作数的两个值。我们只需执行加法以获得11+4=15,然后返回结果。

因此这段代码只能吃+、*、空格和数字。它应该吃一个命令,可以是以下命令之一:

- + <op1> <op2>
- * <op1> <op2>
<number>
-+
- *  
它获取一个指向字符串的指针和一个读取位置,该位置随着程序沿着该字符串的运行而递增

   char *a; int i;
    int eval()
      { int x = 0;
        while (a[i] == ' ') i++; // it eats all spaces
        if (a[i] == '+') 
       /* if the program encounters '+', two operands are expected next. 
          The reading position i already points just before the place 
          from which you have to start reading the next operand 
          (which is what first eval() call will do). 
          After the first eval() is finished, 
          the reading position is moved to the begin of the second operand, 
          which will be read during the second eval() call. */
          { i++; return eval() + eval(); }
        if (a[i] == '*') // exactly the same, but for '*' operation.
          { i++; return eval() * eval(); }
        while ((a[i] >= '0') && (a[i] <= '9')) // here it eats all digit until something else is encountered.
           x = 10*x + (a[i++] - '0'); // every time the new digit is read, it multiplies the previously obtained number by 10 and adds the new digit.
        return x; 
        // base case: returning the number. Note that the reading position already moved past it. 
      }
char*a;int i;
int eval()
{int x=0;
while(a[i]=''i++;//它占用所有空格
如果(a[i]=='+')
/*如果程序遇到“+”,则接下来需要两个操作数。
我已经指出的阅读位置就在该位置之前
必须从中开始读取下一个操作数
(这是第一个eval()调用将执行的操作)。
第一次eval()完成后,
读取位置移到第二个操作数的开头,
将在第二次eval()调用期间读取*/
{i++;返回eval()+eval();}
if(a[i]=='*')//完全相同,但用于'*'操作。
{i++;返回eval()*eval();}
每次调用eval()时((a[i]>='0')&&(a[i]),它计算从位置i开始的下一个表达式的值,并返回该值

在评估范围内:
第一个while循环就是忽略所有空格。
然后有3种情况:

(a) 计算以a+开头的表达式(即a+B形式的表达式,其前缀为“+a B”

(b) 计算以a*开头的表达式(即a*b=“*a b”

(c) 计算整数值(即任何连续的数字序列)

末尾的while循环处理案例(c)

案例(a)的代码与案例(b)的代码类似。想想案例(a):
如果我们遇到+符号,这意味着我们需要添加在序列中找到的下两个“事物”。“事物””可能是数字,也可能是要计算的表达式(如X+Y或X*Y)

为了得到这些“东西”,调用函数eval(),更新值为i。每次调用eval()都将获取下一个表达式的值,并更新位置i

因此,对eval()的两个连续调用将获得以下两个表达式的值。
然后将+运算符应用于2个值,并返回结果


它将有助于处理一个示例,例如“+*23*45”,这是(2*3)+(4*5)的前缀表示法。给出的示例使用了两个全局变量。它们在函数的作用域之外持续存在,并且必须在调用函数之前进行初始化。 应该将i初始化为0,以便从字符串的开头开始,前缀表达式是a中的字符串

运算符是您的前缀,因此应该是您的第一个非空字符,如果您以数字(数字字符串)开始,则完成,这就是结果

示例:a=“+15 450”


返回的要么是找到的值,要么是运算符的结果,然后是找到的后续结果。因此,函数递归地依次查找输入字符串并执行操作,直到找到字符串结尾或无效字符。

我将然后尽可能简单地解释这个概念

eval函数总是跳过空格,以便它指向表达式字符串中当前位置的数字字符('0'->'9')、加法('+')或乘法('*')

如果它遇到一个数字,它继续吃数字,直到它到达一个以整数格式返回总结果的非数字数字


如果遇到运算符(“+”和“*”),则需要两个整数,因此eval将自身调用两次,以从表达式字符串中获取下两个数字,并将结果作为整数返回。

汤中的一根头发可能是
   char *a; int i;
    int eval()
      { int x = 0;
        while (a[i] == ' ') i++; // it eats all spaces
        if (a[i] == '+') 
       /* if the program encounters '+', two operands are expected next. 
          The reading position i already points just before the place 
          from which you have to start reading the next operand 
          (which is what first eval() call will do). 
          After the first eval() is finished, 
          the reading position is moved to the begin of the second operand, 
          which will be read during the second eval() call. */
          { i++; return eval() + eval(); }
        if (a[i] == '*') // exactly the same, but for '*' operation.
          { i++; return eval() * eval(); }
        while ((a[i] >= '0') && (a[i] <= '9')) // here it eats all digit until something else is encountered.
           x = 10*x + (a[i++] - '0'); // every time the new digit is read, it multiplies the previously obtained number by 10 and adds the new digit.
        return x; 
        // base case: returning the number. Note that the reading position already moved past it. 
      }
eval() finds '+' at i = 1
    calls eval() 
        which finds '1' at i = 3 and then '5' 
        calculates x = 1 x 10 + 5 
    returns 15
    calls eval() 
        which finds '4' at i = 6 and then '5' and then '0'
        calclulates x = ((4 x 10) + 5) x 10) + 0
    returns 450
    calculates the '+' operator of 15 and 450
returns 465
if (a[i] == '-')
      { i++; int tmp = eval(); return tmp - eval(); }