用于评估导致Segfault的Postfix的函数

Function to Evaluate Postfix Resulting in a Segfault

本文关键字:Postfix 函数 Segfault 评估 用于      更新时间:2023-10-16

我刚刚对我的程序提出了一个小问题。因此,我有一个函数来计算后缀表达式,并返回计算出的整数或浮点值。这里涉及以下功能:

#include <iostream>
#include <sstream>
#include <cstring>
#include <stack>
#include <limits>
float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
cout << pexpLength << endl;
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{ 
continue;
}     
else if(isOperator(pexp[i]))
{ 
int operand2 = S.top(); S.pop();
int operand1 = S.top(); S.pop();
int result = isOperate(pexp[i], operand1, operand2); 
S.push(result);
}
else if(isDigit(pexp[i]))
{   
int operand = 0; 
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0'); 
i++;
} 
i--;
S.push(operand);
}
} 
return S.top();
}
bool postfixUtility::isDigit(char C) 
{
if(C >= '0' && C <= '9') 
{ 
return true;
}
return false;
}
bool postfixUtility::isOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/')
{
return true;
}
return false;
}
int postfixUtility::isOperate(char operation, int operand1, int operand2)
{
if(operation == '+')
{   
return operand1+operand2;
}
if(operation == '-')
{
return operand1-operand2;
}
if(operation == '*')
{
return operand1*operand2;
}
if(operation == '/')
{   
return operand1/operand2;
} 
}

这些函数共同作用来求解输入的后缀表达式。输入的表达式不是空的,实际上包含一个后缀表达式。然而,每次运行代码时,都会导致segfault。事实上,我很困惑,因为在我看来,我的代码应该可以工作。

谢谢!

编辑#1:所以,我的函数的原始输入是:"(4+3*12)/(12+3/2+46/4)">

然后,我通过另一个函数将其转换为后缀。这就是功能:

int postfixUtility::priority(char a) 
{
int temp;
if (a == '^')
temp = 1;
else  if (a == '*' || a == '/')
temp = 2;
else  if (a == '+' || a == '-')
temp = 3;
return temp;
}
string postfixUtility::getPostfix(string nexp)
{
stack<char> operator_stack;
stringstream output;
for (unsigned i = 0; i < nexp.length(); i++) {
if (nexp[i] == '+' || nexp[i] == '-' || nexp[i] == '*' || nexp[i] == '/' || nexp[i] == '^') {
while (!operator_stack.empty() && priority(operator_stack.top()) <= priority(nexp[i])) {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.push(nexp[i]);
} else if (nexp[i] == '(') {
operator_stack.push(nexp[i]);
} else if (nexp[i] == ')') {
while (operator_stack.top() != '(') {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.pop();
} else {
output << nexp[i];
}
}
while (!operator_stack.empty()) {
output << operator_stack.top();
operator_stack.pop();
}
//cin.ignore(numeric_limits<streamsize>::max(), 'n');
return output.str();
}

哪一个将其转换为:"43 12*+12 3 2/+46 4/+/",这是错误的吗?这会是我得了segfault的原因吗?

编辑#2:所以,我已经注释掉了代码中的2行,我不再得到segfault。

float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{ 
continue;
}     
else if(isOperator(pexp[i]))
{ 
float operand2 = S.top(); 
//S.pop();
float operand1 = S.top(); 
//S.pop();
float result = isOperate(pexp[i], operand1, operand2); 
S.push(result);
}
else if(isDigit(pexp[i]))
{   
int operand = 0; 
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0'); 
i++;
} 
i--;
S.push(operand);
}
} 
return S.top();
}

然而,答案应该是1.6,但我得到了1。为什么会发生这种情况?

编辑#3:我将isOperate功能更改为以下内容:

float postfixUtility::isOperate(char operation, float operand1, float operand2)
{
if(operation == '+')
{   
return operand1+operand2;
}
else if(operation == '-')
{
return operand1-operand2;
}
else if(operation == '*')
{
return operand1*operand2;
}
else if(operation == '/')
{   
return operand1/operand2;
} 
}

然而,我还是得到了1。

那些重要的弹出窗口:

float operand2 = S.top(); 
//S.pop();
float operand1 = S.top(); 
//S.pop();

在不弹出最后一个元素的情况下,operand1将始终等于operand2,并且数字除以其本身通常会得到1。

首先得到segfault的原因是你的后缀转换器给了你(非常)错误的结果(从它的输出中包含输入中不存在的数字这一事实应该很清楚)。让我们来看一下您发布的输出的第一部分:43 12*+。您的解析器会将4312标识为数字,并将它们推送到堆栈中。它将把*识别为一个运算符,从堆栈中取两个数字,将它们相乘,并将结果推送到堆栈上。然后它将遇到+,并尝试从堆栈中获取两个操作数。然而,堆栈上只有一个元素,即乘法运算的结果。在空堆栈上调用top()会导致segfault。

编辑:在执行可能导致错误输入的未定义行为的操作之前,通常最好进行健全性检查。这使您可以采取措施解决问题,或者生成包含诊断信息的错误消息(例如,在您的情况下,运算符、字符串中的位置、字符串本身等)。这将帮助您更容易地识别此类问题。

tl;修复你的后缀转换器。