【问题标题】:C++ same object, different results each timeC++同一个对象,每次结果都不一样
【发布时间】:2015-12-13 08:19:05
【问题描述】:

以下是我项目的一个可运行的sn-p。它假设是一个计算器,但我已将其简化为尽可能简单,同时仍然显示错误并正常运行。

我提前为这段代码:( 的错误格式、样式和所有其他问题道歉。有些只是为了节省空间,比如空行。

Main.cpp

#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;       // ...
}

表达式.h

#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

算术表达式.h

#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

加法.h

#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 

表达式.cpp

#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;
}

算术表达式.cpp

#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());
}

Addition.cpp

#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”,它仍然说同样的话。

【问题讨论】:

  • 编译时包含所有警告和调试信息 (g++ -Wall -Wextra -g)。然后使用调试器 (gdb) 和valgrind。题外话,我们不会做你的功课
  • 您使用的是什么操作系统?已知某些 MacOSX 版本上的某些 C++ 实现存在一些内存泄漏(至少由 valgrind 报告)
  • 你应该学习如何调试......我猜你在学校,这是最好的时间。
  • @francium:说了这么多,你应该可以调试了。如果您跳过了第一次(成功的)评估,然后又进入了失败的评估,您会看到代码走错了路,并且可以找出原因。
  • @MartinBonner:我坚信 C++ 编程的初学者应该使用他们的调试器。

标签: c++ dynamic-memory-allocation object-oriented-analysis


【解决方案1】:

您未能初始化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--) {

【讨论】:

  • 你有我最诚挚的感谢@MikeCAT。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多