2014-09-11 122 views
-1

第一次使用的用户,它似乎从其他职位是个案的基础。那么,我是一名自学成才的C++语言程序员。于是,我终于学会了动态分配的内存,并开始思考使用CLI编程计算器的新方法,以输入单个字符串并抽出答案。这个项目似乎是一个很好的起点,我开始研究解决方案。以下是我的结果:如何调试我的“堆损坏”? (C++)

#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string strInput; 
    cin >> strInput; 
    int nOperatorCount = 0; 
    for(int i = 0; i<(strInput.size());i++) 
    { 
     if(strInput[i]=='+'||strInput[i]=='-'||strInput[i]=='*'||strInput[i]=='/') 
      nOperatorCount++; 
    } 
    int *pnOperatorLocation = new int[nOperatorCount+1]; 
    int *pnOperatorType = new int[nOperatorCount]; 
    float *pnExpressions = new float[nOperatorCount + 1]; 
    pnOperatorLocation[0] = -1; 
    for(int i=0,j=0; i<(strInput.size());i++) 
    { 
     if(strInput[i]=='+') 
    { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 0; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(strInput[i]=='-') 
     { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 1; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(strInput[i]=='*') 
     { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 2; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(strInput[i]=='/') 
     { 
      pnOperatorLocation[j+1] = i; 
      pnOperatorType[j] = 3; 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i)).c_str()); 
      j++; 
     } 
     if(i==(strInput.size()-1)) 
      pnExpressions[j] = atoi((strInput.substr(pnOperatorLocation[j]+1,i+1)).c_str()); 
    } 
    for(int i=0;i<nOperatorCount+1;i++) 
    { 
     cout << "pnExpressions[" << i << "]: " << pnExpressions[i] << endl; 
    } 
    int nOperationsCount = 0; 
    for(int i=0;i<nOperatorCount;i++) 
    { 
     if(pnOperatorType[i]==2||pnOperatorType[i]==3) 
     { 
      if(pnOperatorType[i+1]==0||pnOperatorType[i+1]==1) 
       nOperationsCount++; 
      else if((i+1)==nOperatorCount) 
       nOperationsCount++; 
     } 
    } 
    cout << "nOperationsCount: " << nOperationsCount << endl; 
    float *pnNewExpressions = new float[nOperationsCount]; 
    for(int i=0,j=0;i<nOperatorCount;i++) 
    { 
     if(pnOperatorType[i]==2) 
     { 
      pnNewExpressions[j] = pnExpressions[i] * pnExpressions[i+1]; 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       for(int k=i;k<nOperatorCount-i;k++) 
       { 
        if(pnOperatorType[k+1]==2) 
         pnNewExpressions[j] = pnNewExpressions[j] * pnExpressions[k+2]; 
        else if(pnOperatorType[k+1]==3) 
         pnNewExpressions[j] = pnNewExpressions[j]/pnExpressions[k+2]; 
        else 
         break; 
        if(k+1>=nOperatorCount) 
         break; 
       } 
      } 
      j++; 
     } 
     if(pnOperatorType[i]==3) 
     { 
      pnNewExpressions[j] = pnExpressions[i]/pnExpressions[i+1]; 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       for(int k=i;k<nOperatorCount-i;k++) 
       { 
        if(pnOperatorType[k+1]==2) 
         pnNewExpressions[j] = pnNewExpressions[j] * pnExpressions[k+2]; 
        else if(pnOperatorType[k+1]==3) 
         pnNewExpressions[j] = pnNewExpressions[j]/pnExpressions[k+2]; 
        else 
         break; 
        if(k+1>=nOperatorCount) 
         break; 
       } 
      } 
      j++; 
     } 
     if(i+1>=nOperatorCount) 
      break; 
    } 
    for(int i=0;i<nOperationsCount;i++) 
    { 
     cout << "pnNewExpressions[" << i << "]: " << pnNewExpressions[i] << endl; 
    } 
    float fEvaluation; 
    if(pnOperatorType[0]==2||pnOperatorType[0]==3) 
     fEvaluation = pnNewExpressions[0]; 
    else 
     fEvaluation = pnExpressions[0]; 
    cout << "fEvaluation: " << fEvaluation << endl; 
    for(int i=0,j=1;i<nOperatorCount;i++) 
    { 
     if(pnOperatorType[i]==0) 
     { 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       fEvaluation = fEvaluation + pnNewExpressions[j]; 
       j++; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
      else 
      { 
       fEvaluation = fEvaluation + pnExpressions[i+1]; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
     } 
     if(pnOperatorType[i]==1) 
     { 
      if(pnOperatorType[i+1]==2||pnOperatorType[i+1]==3) 
      { 
       fEvaluation = fEvaluation - pnNewExpressions[j]; 
       j++; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
      else 
      { 
       fEvaluation = fEvaluation - pnExpressions[i+1]; 
       cout << "fEvaluation: " << fEvaluation << endl; 
      } 
     } 
    } 
    cout << "fEvaluation: " << fEvaluation << endl; 
    delete[] pnOperatorLocation; 
    delete[] pnNewExpressions; 
    delete[] pnOperatorType; 
    delete[] pnExpressions; 
    system("pause"); 
    return 0; 
} 

我,如果你通过所有的阅读非常非常非常非常抱歉,但我一直工作在一个已经归结第二个副本少了很多复杂的,但我d为什么这个人突然停止工作。它用于大约10-15次使用,并且我使用了诸如“2 * 3 * 4 + 2 * 3 + 2”的输入,并且它返回了“检测到的腐败笔:在正常的程序段#184之后”。所以我的问题是没有任何人有任何想法如何我可以基于该错误消息进行调试?如果没有,任何人都可以找到为什么我的代码适用于像1 + 1和8 * 8这样的简单方程式,但不是像我期望的那样复杂的方程式?

+0

有些事情要尝试:'valgrind','efence',使用'at()'而不是'[]'来建立索引。 – 2014-09-11 02:06:54

+0

使用'std :: vector'删除所有对'new []'和'delete []'的调用。一旦你这样做了,使用vector的'at()'方法。一旦你排除了,然后用'[]'替换'at()'。 – PaulMcKenzie 2014-09-11 02:19:36

+0

只看代码,'j'的使用看起来很可疑(你永远不会真的检查它的最大值,并且至少有一个循环从值'1'开始),因为它可能会超过索引数组的边界。 – lurker 2014-09-11 02:19:54

回答

0

的问题是,这部分代码:

for (int i = 0, j = 0; i < nOperatorCount; i++) 
{ 
    if (pnOperatorType[i] == 2) 
    { 
     pnNewExpressions[j] = pnExpressions[i] * pnExpressions[i + 1]; // <<--- Error 

下标j是出在环路的2*3*4+2*3+2输入界。

但这里是我很快找到错误的原因 - 我用std::vector将所有这些调用替换为new[]delete[]。由于您使用的是Visual Studio(错误是VS错误),因此DEBUG版本会自动检查矢量数组边界错误。出现的错误框会给你一个subscript out of range错误,因此VS IDE会直接发生违规行。

现在,std::vector::operator[]不检查release版本中的边界,通常operator []不应该这样做。然而VS的调试库打开了这个检查。所以你可以说我正在利用Visual Studio提供的调试帮助。但是,只有当我改用std::vector时,我才得到这个。

vector::at()函数的作用与使用[]的作用相同,但无论您是在运行发行版还是调试版,它都可以进行范围检查。我没有在这里用at()取代呼叫,但是如果由于某种原因[]没有找到错误,我总是可以将代码中的[]更改为at(),直到出现错误为止。

这里的变化快速简介:

#include <iostream> 
#include <string> 
#include <vector> 
//... 
std::vector<int> pnOperatorLocation(nOperatorCount + 1); 
std::vector<int> pnOperatorType(nOperatorCount); 
std::vector<float> pnExpressions(nOperatorCount + 1); 
//... 
std::vector<float> pnNewExpressions(nOperationsCount); 

此外,所有的呼叫delete[]的不再是必要的。

这是否解决了错误?不,我不想在解决方程式时检查你的算法/逻辑。你仍然需要努力弄清楚这个循环的目的是什么,以及为什么j超出界限。但它确实表明仅仅使用现代C++技术可能是有利的。使用new[]delete[]来创建动态数组是“旧式的”,而且实际上并不是必需的,除非您真的需要使用它。

基本上,你需要问自己 - 你想编写一个方程求解器吗?如果答案为“是”,则使用可用的工具创建一个(如std::vector),然后继续解决“简单”错误,而不是使用指针进行对抗,并花费很多精力维护动态数组。

+0

Holy Moly。这是。哇。我认为使用new []和delete []的指针数组是唯一的方法,但这个向量的东西似乎更容易动态分配内存!非常感谢你。由于我是新来的网站,有什么办法可以给你一个好评或什么感谢,男人? PS:在重新组织我的程序并对其进行优化后,我能够将j限制在范围内,但是矢量事物使事情更易于阅读和调试:) – 2014-09-11 08:30:15