以下是我项目的可运行片段。它假设是一个计算器,但我已经将它简化为尽可能简单,同时仍然表现出错误并且功能正常。
我为此代码:(
的格式错误,样式和其他所有错误道歉。有些只是为了节省空间,就像空行一样。
#include <iostream>
#include <string>
#include "Expression.h"
#include "ArithmeticExpression.h"
using namespace std;
int main() {
Expression *expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // Very intresting, if you don't delete it won't have the problem
expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // bug goes away if you don't delete
expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // ...
}
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include <string>
int findOpIndex(std::string);
int evalLen(std::string);
class Expression {
public:
Expression() { }
virtual ~Expression() { }
float result;
std::string resultStr;
virtual std::string evaluate() { }
virtual void print() { }
};
#endif
#ifndef ArithmeticExpression_H
#define ArithmeticExpression_H
#include <iostream>
#include <string>
#include "Expression.h"
class ArithmeticExpression : public Expression {
protected:
bool isTopExpr;
bool isValue;
Expression *arithExpr;
Expression *left;
Expression *right;
public:
ArithmeticExpression() { }
ArithmeticExpression(std::string, bool);
~ArithmeticExpression();
std::string evaluate();
void print();
float convert(std::string);
};
#endif
#ifndef Addition_H
#define Addition_H
#include <string>
#include "Expression.h"
#include "ArithmeticExpression.h"
class Addition : public ArithmeticExpression {
protected:
Expression *left;
Expression *right;
public:
Addition(std::string, std::string);
~Addition();
std::string evaluate();
void print();
};
#endif
#include <iostream>
#include <string>
#include "Expression.h"
int findOpIndex(std::string expr) {
char curChar;
int bflag = 0;
int firstOp = -1;
for (unsigned int c=expr.length(); c>0; c--) {
curChar = expr[c];
if (curChar == '(') {
bflag++;
} else if (curChar == ')') {
bflag--;
} else if (bflag == 0) {
if (firstOp != -1) {
if (curChar == '+' || curChar == '-') {
return c;
}
} else if (curChar == '*' || curChar == '/') {
firstOp = c;
} else if (curChar == '+' || curChar == '-') {
return c;
}
}
}
return firstOp;
}
int evalLen(std::string eval) {
int count = 0;
for (unsigned int c=0; c<eval.length(); c++) {
if (eval[c] != '.') count++;
else break;
}
return count+3;
}
#include <stdlib.h>
#include <iostream>
#include "Expression.h"
#include "ArithmeticExpression.h"
#include "Addition.h"
ArithmeticExpression::ArithmeticExpression(std::string expr, bool isTopExpr) {
this->isTopExpr = isTopExpr;
int opIndex = findOpIndex(expr);
resultStr = expr;
if (opIndex == -1 || (opIndex == -1 && expr[0] == '-' && expr[1] != '(')) {
isValue = true;
arithExpr = NULL;
} else {
std::string leftExpr = expr.substr(0, opIndex);
std::string rightExpr = expr.substr(opIndex+1, expr.length());
arithExpr = new Addition(leftExpr, rightExpr);
}
}
ArithmeticExpression::~ArithmeticExpression() {
delete arithExpr;
}
std::string ArithmeticExpression::evaluate() {
if (isValue) {
return resultStr;
} else {
return arithExpr->evaluate();
}
}
void ArithmeticExpression::print() {
if (isTopExpr && isValue) {
std::string eval = evaluate();
std::cout << eval << " = " << eval << std::endl;
} else if (isTopExpr) {
std::string eval = evaluate();
arithExpr->print();
std:: cout << " = " << eval.substr(0,evalLen(eval)) << std::endl;
} else {
if (isValue) {
std::string eval = evaluate();
if (eval[0] == '-') std::cout << "(" << eval << ")";
else std::cout << evaluate();
} else {
arithExpr->print();
}
}
}
float ArithmeticExpression::convert(std::string s) {
return atof(s.c_str());
}
#include <iostream>
#include <string>
#include "Addition.h"
#include "ArithmeticExpression.h"
Addition::Addition(std::string leftStr, std::string rightStr) {
left = new ArithmeticExpression(leftStr, false);
right = new ArithmeticExpression(rightStr, false);
}
Addition::~Addition() {
delete left;
delete right;
}
std::string Addition::evaluate() {
float l = convert(left->evaluate());
float r = convert(right->evaluate());
r = convert(right->evaluate());
r = convert(right->evaluate());
return std::to_string(l+r);
}
void Addition::print() {
std::cout << "(";
left->print();
std::cout << "+";
right->print();
std::cout << ")";
}
((1+2)+3) = 6.00
(1+2+3) = 4.00 // This evaluates correctly to 6.00 if
(1+2+3) = 4.00 // I don't delete the expr pointer in Main.cpp
这些值应该都是相同的。怎么了? 我没有使用复制构造函数;我写了它,但我意识到它们从未被调用过。 Valgrind确认,所有内存都被释放,析构函数正确地完成了它们的工作。
==20337== HEAP SUMMARY:
==20337== in use at exit: 72,704 bytes in 1 blocks
==20337== total heap usage: 22 allocs, 21 frees, 74,480 bytes allocated
==20337==
==20337== LEAK SUMMARY:
==20337== definitely lost: 0 bytes in 0 blocks
==20337== indirectly lost: 0 bytes in 0 blocks
==20337== possibly lost: 0 bytes in 0 blocks
==20337== still reachable: 72,704 bytes in 1 blocks
==20337== suppressed: 0 bytes in 0 blocks
==20337== Rerun with --leak-check=full to see details of leaked memory
==20337==
==20337== For counts of detected and suppressed errors, rerun with: -v
==20337== Use --track-origins=yes to see where uninitialised values come from
==20337== ERROR SUMMARY: 18 errors from 11 contexts (suppressed: 0 from 0)
72,704 bytes in 1 blocks
是编译器或valgrind中的错误。这段代码不是问题,因为我跑了“hello world”,它仍然说同样的事情。
答案 0 :(得分:2)
您未能初始化ArithmeticExpression::isValue
。
ArithmeticExpression::ArithmeticExpression(std::string expr, bool isTopExpr) {
this->isTopExpr = isTopExpr;
int opIndex = findOpIndex(expr);
resultStr = expr;
if (opIndex == -1 || (opIndex == -1 && expr[0] == '-' && expr[1] != '(')) {
isValue = true;
arithExpr = NULL;
} else {
isValue = false; // add this line
std::string leftExpr = expr.substr(0, opIndex);
std::string rightExpr = expr.substr(opIndex+1, expr.length());
arithExpr = new Addition(leftExpr, rightExpr);
}
}
另外,我不认为访问expr[expr.length()]
是好的,你应该改变
for (unsigned int c=expr.length(); c>0; c--) {
在Expression.cpp
到
for (unsigned int c=expr.length()-1; c>0; c--) {