大家好日子。我在运行时遇到错误。我正在尝试检查令牌是否为双,但我收到错误“错误: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();
}
答案 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> isdigit
,isalnum
或<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
,可能是你崩溃的时候
在循环内移动调用,使其最后而不是第一个。