尝试检查char *是否为double时访问冲突

时间:2014-03-07 16:55:46

标签: c++ access-violation

大家好日子。我在运行时遇到错误。我正在尝试检查令牌是否为双,但我收到错误“错误:0x40516B处的访问冲突:读取地址0x0”..是什么导致错误,我该怎么做才能防止错误?有没有其他方法来检查令牌是双或字母数字?谢谢..

#include <iostream>
#include <conio>
#include <string>
#include <ctype>
#include <stdlib>

char statement[256];
string strStatement;
string variableName[5];
double values[5];
int counter = 0;
double result=0;
string stmtFormat =" ";
char * tokens;
string newString;

bool isDouble(char *toCheck)
{
  bool valid = true;
  for(int i=0 ; i <(sizeof(toCheck)/sizeof(toCheck[0]));i++)
  {
    if((i!=0 && toCheck[i]=='-')||(toCheck[i]!='0'||toCheck[i]!='1'||toCheck[i]!='2'||toCheck[i]!='3'||toCheck[i]!='4'||toCheck[i]!='5'||toCheck[i]!='6'||toCheck[i]!='7'||toCheck[i]!='8'||toCheck[i]!='9'))
    {
      bool valid = false;
      cout<<"invalid number";
      break;
    }
  }
  return valid;
}

void checkGrammar(string strStatement)
{    
  if(strStatement == "print;")
  {
    cout<<"-----Output of the program-----"<<endl;
    cout<<"The result is "<<result;
  }
  else
  {
    tokens = strtok (statement," ");
    while(tokens!= NULL)
    {
      tokens = strtok(NULL ," ");
      if (tokens == "    " ){stmtFormat = stmtFormat+"<opr>";}
      else if (tokens == "-" ){stmtFormat = stmtFormat+"<opr>";}
      else if (tokens == "*" ){stmtFormat = stmtFormat+"<opr>";}
      else if (tokens == "/" ){stmtFormat = stmtFormat+"<opr>";}
      else if (tokens == "^" ){stmtFormat = stmtFormat+"<opr>";}
      else if (tokens == ";"){stmtFormat = stmtFormat+"<end>";}
      else //not operands or end
      {
        if (isDouble(tokens)){stmtFormat = stmtFormat+"<val>";}
        else{}
      }
    }
  }
}

main(void)
{
  cout <<"\nInstructions: you can declare up to 5 variables. use this syntax: \n \"num var_name = value ; \" (without the \"\")    "<<endl;
  cout <<"use , instead of . for decimals.   \n";
  cout <<"Afterwards, type the expression that you want."<<endl;
  cout <<"To print;, just type: print"<<endl;
  cout <<"Let's start!\n\n";
  while(strStatement != "print;")
  {
    cout<< ">";
    cin    getline(statement, 256);
    strStatement = statement;
    checkGrammar(strStatement);
  }
  getch();
}

3 个答案:

答案 0 :(得分:0)

  

导致错误的原因

在while循环开始时执行tokens = strtok(NULL ," ");两次看起来非常错误:

 tokens = strtok (statement," ");
 while(tokens!= NULL)
 {
     tokens = strtok(NULL ," "); // tokens might become NULL here!

恕我直言,将其置于for循环中更具可读性和安全性:

 for(tokens = strtok (statement," "); tokens != NULL; strtok (NULL ," "))
 {
    // ...
 }

请注意,tokens可能会在while循环内调用后变为NULL,并且会被取消选中isDouble()部分中的else。这可能很可能是你的问题。

  

我该怎么做才能防止错误?

在解除引用之前,请务必检查非NULL值的指针。

答案 1 :(得分:0)

isalpha中的{p> isdigitisalnum<cctype>可以像循环使用循环中的特定字符,但我会使用std::string和如果可能的话,更多的C ++。

那说你的AV是由于你最终没有更多的字符串标记要检索而strtok将返回NULL并且你不想使用operator[]访问nullptr。 ..你可以在你的isDouble方法中添加一个空检查作为快速黑客:

bool isDouble(char *toCheck)
{
  bool valid = toCheck != 0;
  if ( valid ) {
   for(int i=0 ; i <(sizeof(toCheck)/sizeof(toCheck[0]));i++)
   {
    if((i!=0 && toCheck[i]=='-')||(toCheck[i]!='0'||toCheck[i]!='1'||toCheck[i]!='2'||toCheck[i]!='3'||toCheck[i]!='4'||toCheck[i]!='5'||toCheck[i]!='6'||toCheck[i]!='7'||toCheck[i]!='8'||toCheck[i]!='9'))
      {
        bool valid = false;
         cout<<"invalid number";
         break;
      }
   }}
   return valid;
}
然而,在循环中捕捉它可能会更好

  char* tokens = strtok (statement, " ");
  while (tokens != NULL)
  {
    // do stuff
    tokens = strtok (NULL, " ");
  }

答案 2 :(得分:0)

有很多问题:

1:首先,全局变量通常看起来是个好主意 他们不是。摆脱它们。

2:你正在修改一个与你在isDouble中想到的不同的变量 内部声明隐藏了外部声明。

3:您将char*与文字进行比较 不要这样做,这是一个指针比较。没有比较是真的。

4:在检查结果是否为strtok后,您正在调用NULL
(一个并不罕见的初学者的误解是,一旦条件为假,循环就会停止。它不会。)
最后一次, NULL,可能是你崩溃的时候 在循环内移动调用,使其最后而不是第一个。