gpt4 book ai didi

c++ - 调车场表达式解析器中的一元减号

转载 作者:可可西里 更新时间:2023-11-01 18:33:06 24 4
gpt4 key购买 nike

这是我使用调车场算法的表达式解析器它按预期工作良好,除了在一种情况下,当我像 -2*3 那样使用一元减号时它不会工作(我认为它不应该因为我没有在算法中找到任何东西来处理这个)有没有一种简单的方法可以解决这个问题?(这是一个简单的解析器,我只需要 () + - */^ )问候 佩德拉姆

#include <cctype>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
int olaviat (char c) {
/*************
**Operator precedence
*************/
switch(c) {
case '-' : case '+' :
return 1 ;
case '*' : case '/' :
return 2 ;
case '^' :
return 3 ;
default :
return 0 ;
}
}
double eval(char *exp) {
/*************
**Convert to reverse polish
*************/
char n [50] , o[50] ;
static int nl = 0 , ol = 0 ;

while (*exp) {
while(isspace(*exp)) *exp++ ;
if(*exp == '(') {
o[ol++] = *exp++ ;
}
else if (*exp == ')'){
while(o[--ol]!='('){
n[nl++] = o[ol];
n[nl++] = ' ';
}
*exp++;
}
else if (isdigit(*exp)) {
while (isdigit(*exp)) {
n[nl++] = *exp++ ;
}
n[nl++] = ' ' ;
}
else if (strchr("+-*/^",*exp)){
if(olaviat(*exp) > olaviat(o[ol-1])) {
o[ol++] = *exp++ ;


}
else {
if(olaviat(*exp) == olaviat(o[ol-1]) && olaviat(*exp)== 3) {
o[ol++] = *exp++ ;
}else{
n[nl++] = o[ol-1] ;
n[nl++] = ' ' ;
o[--ol] = '\0' ;

}
}
}

}

for (int k = ol-1 ; k >= 0 ; k --){
n[nl++] = o[k];
n[nl++] = ' ' ;
}
/*******************************/
cout << "Reverse Polish" << endl ;
for (int i = 0 ; i < nl-1 ; i++){
cout << n[i] ;
}
cout << endl ;
//n[nl+1] = '\0' ;
/*******************************
**Calculate Result
*******************************/
double temp[50];
char *e ;
ol = 0;
int nol = 0 ;
e=n ;
int digitcount = 0;
while (*e) {
while (isspace(*e)) *e++;
if (isdigit(*e)) {
while (isdigit(*e)) {
o[ol++] =*e++ ;
digitcount++ ;
}
temp[nol++] = atof(o) ;
for (int i = 0 ; i < digitcount ; i++)
o[i]='\0' ;
ol=0;
digitcount = 0 ;
}
else if (strchr("+-*/^",*e)){
// char opr ;
double tempAns = 0;
switch (*e) {
case '+' :
tempAns = temp[nol-2] + temp [nol-1] ;
break ;
case '-' :
tempAns = temp [nol-2] - temp [nol-1] ;
break;
case '*' :
tempAns = temp [nol-2] * temp [nol-1] ;
break;
case '/' :
tempAns = temp[nol-2] / temp[nol-1];
break ;
case '^' :
tempAns = pow(temp[nol-2],temp [nol-1]);
break ;
default :
cout << "\n Unknown error" ;
continue;
}
*e++ ;
nol--;
temp[nol-1] = tempAns ;
temp[nol] = NULL ;
}
else {
break ;
}
}
double ans = temp[0];

return ans ;
}

int main() {

char exp[100];
char c;
start :
cin.get (exp , 99);
cout << "\n\tANS= " << eval(exp) ;
cout << endl ;
system("PAUSE");
return 0;
}

最佳答案

上面的选项是正确的,但它会变得非常麻烦和错误。考虑这种情况 2*-(1+2)^-(2+5*-(2+4))。如您所见,您需要考虑很多事情。此外,每当您找到 *-(,例如,您知道您将用 *(0-(... 替换它,这将被编码成一个繁琐的递归函数。

最好的解决方案要简单得多。解析运算符时,请考虑运算符是 - 并且它前面有另一个运算符,或者前面有左括号,或者它是输入的第一个字符的情况(这些情况意味着它是一元减号而不是二元)。在这种情况下,您将其更改为另一个字符,比如 u(这是我的情况),并使其优先级与 ^ 相同。

此外,将其视为数字字面量的一部分也有其局限性。想象一下 -2^4 这样的情况。在 Wolfram Alpha 中,您会得到 -16,而不是 16

并考虑使用堆栈。它们会让您的生活更轻松。

让我解释一下我的意思。考虑给你输入:

2 / - 7 + ( - 9 * 8 ) * 2 ^ - 9 - 5

按照我的建议进行替换,它会变成这样:

2 / u 7 + ( u 9 * 8 ) * 2 ^ u 9 - 5

现在您的运算符优先级开关应更改为:

switch(c)
{
case '-' : case '+' :
return 1 ;
case '*' : case '/' :
return 2 ;
case '^' : case 'u': //note the 'u' operator we added
return 3 ;
default :
return 0 ;
}

当然,您需要进行更改以支持此一元运算符。

关于c++ - 调车场表达式解析器中的一元减号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16425571/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com