C++ 尝试检查char*是否为double时发生访问冲突
大家好。我在运行时出错。我正在尝试检查令牌是否为双精度令牌,但收到错误“错误:0x40516B处的访问冲突:读取地址0x0”。。什么原因导致错误?我可以做些什么来防止错误?有没有其他方法可以检查令牌是双精度的还是字母数字的?谢谢C++ 尝试检查char*是否为double时发生访问冲突,c++,access-violation,C++,Access Violation,大家好。我在运行时出错。我正在尝试检查令牌是否为双精度令牌,但收到错误“错误:0x40516B处的访问冲突:读取地址0x0”。。什么原因导致错误?我可以做些什么来防止错误?有没有其他方法可以检查令牌是双精度的还是字母数字的?谢谢 #include <iostream> #include <conio> #include <string> #include <ctype> #include <stdlib> char statement
#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();
}
#包括
#包括
#包括
#包括
#包括
char语句[256];
字符串语句;
字符串变量名[5];
双值[5];
int计数器=0;
双结果=0;
字符串stmtFormat=“”;
字符*代币;
字符串新闻字符串;
布尔值是双倍的(字符*toCheck)
{
bool valid=true;
对于(int i=0;i
错误的原因是什么
在while循环开始时执行两次tokens=strtok(NULL,“”;
看起来非常错误:
tokens = strtok (statement," ");
while(tokens!= NULL)
{
tokens = strtok(NULL ," "); // tokens might become NULL here!
IMHO将其放入for
循环中更具可读性和安全性:
for(tokens = strtok (statement," "); tokens != NULL; strtok (NULL ," "))
{
// ...
}
请注意,tokens
在while循环中调用后可能会变为NULL
,并未经检查传递给else
部分中的isDouble()
。这很可能是您的问题
我能做些什么来防止这个错误呢
在取消引用之前,请始终检查非空值的指针。<>代码> ISALPHA/<代码>,<代码> ISDigi> <代码>,或<代码> ISALNUM < /C> >可以在循环中的特定字符中使用,但我会使用<代码> STD::String ,如果可能的话,使用更多的C++。
也就是说,您的AV是由这样一个事实造成的:您最终将没有更多的字符串令牌可检索,strtok
将返回NULL,并且您不希望使用operator[]
访问NULL ptr……您可以在isDouble方法中添加NULL检查作为一种快速破解:
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;
}
有许多问题:
1:一开始,全局变量似乎是个好主意。
他们不是,把他们赶走
2:您正在修改的变量与您在isDouble
中想象的不同
内部声明隐藏了外部声明
3:您正在将字符*
与文字进行比较。
不要这样做,这是指针比较。没有一个比较是正确的
4:在检查结果是否为NULL
(一个常见的初学者误解是,一旦条件为假,循环就会停止。它不会停止。)
最后一次,当它为NULL
时,可能是您崩溃的时候。
将调用移到循环内,使其成为最后一个而不是第一个。读取地址0x0
表示您正在尝试取消引用null
指针。为什么要使用tokens=strtok(null,”)标记上的
?此外,检查语法
无法比较两个符号为=
的字符串:使用strcmp()
相反。您提出了一个模糊的问题,在这里丢弃了大量代码,并且没有提供导致失败的输入。您甚至没有费心去修剪代码中不相关的部分。您得到的任何回答都将是一种极端慷慨的行为。
char* tokens = strtok (statement, " ");
while (tokens != NULL)
{
// do stuff
tokens = strtok (NULL, " ");
}