you need to write a lexical analyzer, or try something like (although it is not very interesting)<script>
var a = 1;
var b = 2;
var c = 3;var strExp = "a=b+";
var bGood = false;
try
{
eval(strExp)
bGood = true;
}
catch (ex)
{
alert(ex.description);
}alert(bGood);
</script>
var a = 1;
var b = 2;
var c = 3;var strExp = "a=b+";
var bGood = false;
try
{
eval(strExp)
bGood = true;
}
catch (ex)
{
alert(ex.description);
}alert(bGood);
</script>
解决方案 »
- 初级问题:jquery中的append里面怎样包含变量?
- 求一个带输入框的JS分页代码
- var NewClass = {}和var NewClass = Class.create()的区别
- 在html文件中的javascript 能读取session吗?
- 请教一个关于选择器的问题
- 请教一下高手们,怎么在javascrip里读取asp的application变量
- 关于指定字符判断的问题·#¥%%…—
- 为何总提示undefined?是不是得到的是一个数组而无法取值?如何才能取值?
- 关于for循环,马上给分
- JQuery mobile popup功能 如何弹出后3秒自动关闭
- EJB和JAVABAEN有什么区别呢??
- frame的问题。
check("a=b+");
check("a=b+c");
check("a=b*(c+d");
check("a=b*(c+d)");
check("a=b+()+c")
check("a=b+(d)+c")
check("a=)b+c(")
check("a=(b+c)")
check("a=b%")
check("a=b*42%")function check(str){
if(str.match(/[\+\-\*\/]$/)){alert(str+"\nError:操作符后面必须要有数");return false}
var reg=/\([^)]+\)/,tmp=str;while(tmp.match(reg))tmp=tmp.replace(reg,"");
if(tmp.match(/(\)|\()/)){alert(str+"\nError:括号不对");return false}
if(tmp.match(/\D%/)){alert(str+"\nError:%前要接数字");return false}
alert(str+"\n通过");return true;
}
</script>
function testSuanshi(teststr)
{
var a=1,b=1,c=1,d=1;
with(Math)
{
try{eval(teststr);alert("你的算式正确!"+teststr);}
catch(exception){alert("你的算式错误!"+teststr);}
}
}testSuanshi("a+b-c");
testSuanshi("a=b+c");
testSuanshi("a+b-c(");
testSuanshi("sin(a+b)");
苹果*3+李子*5+(栗子*9+小栗子)*25%+橘子
写成这种形式:
str = "@苹果@*3+@李子@*5+(@栗子@*9+@小栗子@)*25%+@橘子@";
然后:
try{
var re = /@+[\s]+@/g;
str = str.replace(re, "(1)");
s = eval(str);
}catch(err)
{
alert("您输入的表达式有误!\n\n 请检查修改");
}
a=b
a==b
a===b
a>b
a>=b
a<b
a<=b
a<>b
a><b
这种不合法的运算式居然也通过验证???????????是不是要去掉啊?
再做另外一个函数先检查有没有=,<,>?
我是这样想的。
但如果表达式是
while(1)alert()
还是需要另外一套
<>的处理和()相似
=的处理和%相似
或只能有一个,和+-*/相似
1.括号必须成双出现,且“(”在“)”之前;
2.字符串的第一个字符或是最后一个字符均不能是“+,-,*,/”中的任何一个;(要在首位就出现正负情况的,请使用括号。)
3.%前要接数字;
4.不准省略“*”,比如“3(a+b)”,请改为“3*(a+b)”;
5.不得出现“=”、“<”、“>”之类;
6.不得出现其他不友善字符。(这句话有点搞笑啊,连我自己都不明白,害羞中.................)
十二支持以eval为核心,再加上其它的细节
反对以没有加上细节而否定核心
document.write(check("b+"),"<br>");
document.write(check("b+c"),"<br>");
document.write(check("b*(c+d"),"<br>");
document.write(check("b*(c+d)"),"<br>");
document.write(check("b+()+c"),"<br>")
document.write(check("b+(d)+c"),"<br>")
document.write(check(")b+c("),"<br>")
document.write(check("(b+c)"),"<br>")
document.write(check("b%"),"<br>")
document.write(check("b*42%"),"<br>")
document.write(check("3(b+c)"),"<br>")
document.write(check("3*(b+c)"),"<br>")
function check(str){
if(str.match(/[\+\-\*\/]$/))return(str+"\nError:操作符后面必须要有数");
if(str.match(/[^\+\-\*\/]\(/))return(str+"\nError:括号前不能省略操作符");
if(str.match(/\D%/))return(str+"\nError:%前要接数字");
if(str.match(/<=>/))return(str+"\nError:不得出现“=”、“<”、“>”之类");
var reg=/\([^)]+\)/,tmp=str;while(tmp.match(reg))tmp=tmp.replace(reg,"");
if(tmp.match(/(\)|\()/))return(str+"\nError:括号必须成双出现,且“(”在“)”之前");
return str+"\n通过";
}
</script>
还有几个操作符号连着的也会通过验证!我想这个程序要完整的话,必须与eval结合使用。先验证后,再用数字去替换除了操作符号以外的字符,计算后返回结果。但是eval不能正确计算含有%的字符串。
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
</HEAD>
<BODY>
<script>
function check(testStr){
document.write(testStr+"<br><hr>");
var tmpNum='';//临时变量,存储数字
var hopeArr=new Array();//期待数组
var strArr=testStr.split('');
hopeArr[0]=1; /************************************************************
* 当前字符 * type * 期望type *
************************************************************
* 0,1,2,3,4,5,6,7,8,9 * 0 * 1 or 3 *
* + - * / * 1 * 0 or 2 *
* ( * 2 * {0 or 2}and 3 *
* ) * 3 * 1 *
************************************************************/
function getType(ID){//返回字符类型,
var type;
if(!isNaN(strArr[ID])){
type=0;
}else{
switch(strArr[ID]){
case '+':type=1;
break;
case '-':type=1;
break;
case '*':type=1;
break;
case '/':type=1;
break;
case '(':type=2;
break;
case ')':type=3;
break;
case '.':type=4;
break;
default :return alert("'"+strArr[ID]+"'是一个非法字符!");
}
}
return type;
}
//====================================================
if(getType(0)==2)hopeArr.push(1);
if(getType(0)!=0&&getType(0)!=2)return alert("第一个字符不合法")
for(i=0;i<strArr.length-1;++i){
curType=getType(i);
nxtType=getType(i+1);
switch(curType){
case 0:{ if(nxtType==0){tmpNum+=strArr[i];if(isNaN(tmpNum))return alert(tmpNum+"不是一个数字");break;}
if(nxtType==1)break;
if(nxtType==2){alert("位置"+(i+2)+"缺少运算符"+strArr[i]);break;}
if(nxtType==3){hopeArr.pop();if(hopeArr.length==0)alert("位置"+(i+1)+'出现未匹配的”)“'+strArr[i]);break;}
if(nxtType==4){tmpNum+=strArr[i];if(isNaN(tmpNum))return alert(tmpNum+"不是一个数字");break;}
}
break;
case 1:{ tmpNum='';
if(nxtType==0)break;
if(nxtType==1){alert("位置"+(i+2)+"缺少运算数字"+strArr[i]);break;}
if(nxtType==2){hopeArr[hopeArr.length]=1;break;}
if(nxtType==3){alert("位置"+(i+2)+'缺少运算符'+strArr[i]);break;}
if(nxtType==4){alert("位置"+(i+2)+"缺少运算数字"+strArr[i]);break;}
}
break;
case 2:{ tmpNum='';
if(nxtType==0)break;
if(nxtType==1){alert("位置"+(i+2)+"缺少运算数字"+strArr[i]);break;}
if(nxtType==2){hopeArr[hopeArr.length]=1;break;}
if(nxtType==3){alert("位置"+(i+2)+"缺少运算数字"+strArr[i]);break;}
if(nxtType==4){alert("位置"+(i+2)+"缺少运算数字"+strArr[i]);break;}
}
break;
case 3:{ tmpNum='';
if(nxtType==0)break;
if(nxtType==1)break;
if(nxtType==2)break;
if(nxtType==3){hopeArr.pop();if(hopeArr.length==0)alert("位置"+(i+1)+'出现未匹配的”)“'+strArr[i]);break;}
if(nxtType==4){alert("位置"+(i+2)+"缺少运算数字"+strArr[i]);break;}
}
break;
case 4:{ if(nxtType==0){tmpNum+=strArr[i];if(isNaN(tmpNum))return alert(tmpNum+"不是一个数字");break;}
if(nxtType==1){tmpNum+=strArr[i];if(isNaN(tmpNum))return alert(tmpNum+"不是一个数字");break;}
if(nxtType==2){
tmpNum+=strArr[i];
if(isNaN(tmpNum))return alert(tmpNum+"不是一个数字");
alert("位置"+(i+2)+"缺少运算数字"+strArr[i]);break;}
if(nxtType==3){tmpNum+=strArr[i];if(isNaN(tmpNum))return alert(tmpNum+"不是一个数字");hopeArr.pop();if(hopeArr.length==0)alert("位置"+(i+1)+'出现未匹配的”)“'+strArr[i]);break;}
if(nxtType==4){alert("位置"+(i+2)+"多余的小数点"+strArr[i]);break;}
}
break;
}
}
if(getType(strArr.length-1)==4){
tmpNum+='.';
if(isNaN(tmpNum))return alert(tmpNum+"不是一个数字")
}
if(hopeArr.length>1)return alert("存在没有匹配的'('")
alert("算术表达是合法,结果为: "+eval(testStr))
}a='1.1+2.9*(3-4.)/5.1';
/*
a='1+2*(3-4)/5';
a='1.1+2.9*(3-4.)/5.1';
a='1.1.+2.9*(3-4.)/5.1';
a='1.1+2.9.*(3-4.)/5.1';
a='1.1+2.9*.(3-4.)/5.1';
a='1.1+2.9*(.3-4.)/5.1';
a='1.1+2.9*(3-4.)/5.1.';
a='(1.1+2.9*(3-4.)/5.1';
a='1.1+2.9*(3-4.)/5.1)';
a='1.1+2.9*(3-4.)/5.1';
a='1.1+2.9*(3-4.)/5.1';
a='1.1+2.9*((3-4.)/5.1)';
*/
check(a)
</script>
</BODY>
</HTML>
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
</HEAD><BODY>
<script>
testStr='1+2*(1+1)+1';strArr=testStr.split('');//评估树组
hopeArr=new Array();//期待数组
hopeArr[0]=1;
var tmpNub;//临时变量,存储数字
var type=0;//0-9 :0||"+" "-" "*" "/" :1||"(" ")":2function checkHope(ID,result){//result=0 返回ID的type||result=1 返回ID的hope
var hope=-1;
if(!isNaN(strArr[ID])){
type=0;
hope=0;
}else{
switch(strArr[ID]){
case '+':hope=1;type=1;
break;
case '-':hope=1;type=1;
break;
case '*':hope=1;type=1;
break;
case '/':hope=1;type=1;
break;
case '(':hope=2;type=2;
break;
case ')':hope=3;type=3;
break;
default :return alert("'"+strArr[ID]+"'是一个非法字符!");
}
}
if(!result)return type;
else return hope;
}
/*
*********************************************************************
* 当前字符 * type * 期望type * hope *
*********************************************************************
* 0,1,2,3,4,5,6,7,8,9 * 0 * 1 or 3 * 0 *
* + - * / * 1 * 0 or 2 * 1 *
* ( * 2 * {0 or 2}and 3 * 2 *
* ) * 3 * 1 * 3 *
*********************************************************************
###对于左括号"("应作特殊处理,她先后期待一个 有括号")"和数字
*/
function check(){
document.write(testStr+"<br><hr>");
var curType,hopeType;
for(i=0;i<strArr.length;++i){
curHope=hopeArr[hopeArr.length-1];
curType=checkHope(i,0);
switch(curHope){
case 0:{ if(curType==1){
hopeArr.pop();
hopeArr[hopeArr.length]=checkHope(i,1);
document.write("位置"+(i+1)+"渴望出现运算符“+ - * /”或右括号“)”,<font color=green>出现了 "+strArr[i]+"...ok</font><br>");
break;
}
if(curType==3){
hopeArr.pop();
if(hopeArr[hopeArr.length-1]!=2)return document.write('<font color=red>位置'+(i+1)+"出现了')',但没有'('匹配</font><br>");
hopeArr.pop();
hopeArr[hopeArr.length]=checkHope(i,1);
document.write("位置"+(i+1)+"渴望出现运算符“+ - * /”或右括号“)”,<font color=green>出现了 "+strArr[i]+"...ok</font><br>");
}
}
break;
case 1:{ if(curType==0){//0-9
hopeArr.pop();
hopeArr[hopeArr.length]=checkHope(i,1);
document.write("位置"+(i+1)+"渴望出现数字“0~9”或左括号“(”,<font color=green>出现了 "+strArr[i]+"...ok</font><br>");
break;
}
if(curType==2){//(
hopeArr.pop();
hopeArr[hopeArr.length]=checkHope(i,1);
hopeArr[hopeArr.length]=1;
document.write("位置"+(i+1)+"渴望出现数字“0~9”或左括号“(”,<font color=green>出现了 "+strArr[i]+"...ok</font><br>");
break;
}
return document.write("<font color=red>位置"+(i+1)+"渴望出现数字“0~9”或左括号“(”,但出现了"+strArr[i]+"</font><br>");
}
break;
case 2:{//事实上hope=2并不意义,指作为一个期待)出现的记号,下面代码不会执行
if(curType==0){
hopeArr.pop();
document.write("位置"+(i+1)+"渴望出现数字“0~9”或右括号“)”,<font color=green>出现了 "+strArr[i]+"...ok</font><br>");
alert(3)
break;
}
if(curType==3){
alert(2)
}
}
break;
case 3:{ if(curType==1)hopeArr.pop()
else return document.write("<font color=red>位置"+(i+1)+"渴望出现运算符“+ - * /”,但出现了"+strArr[i]+"</font><br>");
hopeArr[hopeArr.length]=checkHope(i,1);
document.write("位置"+(i+1)+"渴望出现运算符“+ - * /”,<font color=green>出现了 "+strArr[i]+"...ok</font><br>");
}
break;
}
}
}
check()</script>
</BODY>
</HTML>
上面两个我用了不同的思路,你可以看看,不过没有什么实用价值,在C中+ -*/式运算符,并且可以重载,作为类的方法出现,那样实现运算式的判断想对容易,如果js 中可以重载,那么业就不需要上面那么麻烦了。
第一个与第二个思路不同,肯能有错误的地方,毕竟草草写了几句,如有错误,请原谅。================
顺便吻一下,为什么从昨天到今天14:30我都登陆不了论坛????
http://expert.csdn.net/Expert/topic/1104/1104078.xml?temp=.7486231
的程序,如果再精练点就好了。
请你继续关注我的新贴:
http://expert.csdn.net/Expert/topic/1111/1111289.xml?temp=.5580713
你的程序需要好象很多测试不能通过啊。
把你不通过的四则式子写出来好吗?你不要用第二个,那个我想使用统一思路解决括号匹配和式子有效,发现有些麻烦,数据结构没学好,别介意。
比如a+(b+c 就不能得到正确结果。但是你的这段程序我觉得很不错了,对我帮助和启发也很大。
如果不用统一的思路,请教精练点的代码?
我希望你的程序能够“遍历”整串字符。要以“+、-、*、/、为界,
然后把每个不是数字的小段读出来。比如
苹果+梨子*(3-香蕉/板栗)+25%+核桃我要得到其中的“水果”,而不要3,25%,就是要判断是不是数字之类的,只要字符的。尤其是象%不好处理。
//------------------------------------------
number='(5+2)-1*' //算式
try
{
eval(number);
}
catch(e)
{
alert('算式错误!');
}
//------------------------------------------这样做简单,但可能有缺陷,具体没仔细考虑过,最好能跟正则结合起来,比如一个错误的算式有可能是一个正常的js语句,这时上面的代码不会报错的。
楼主如果你是想考察原理,用最根本的方式检测死则运算式,那么你就要用JS模仿栈去检测,如果只是对数型量,不涉及重载问题,用JS无法实现运算符重载,因为运算符本身就是函数,js不支持,所以从根本上检测运算式会很繁杂。对于一般性的检测正确性就用秋水的那些方法通过异常来判断合法性吧!
========================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!--
//--------------------------------------------------------------------
//对于括号匹配的检测
function GetBracketError(Bracket,oprt){
//对于左括号将期待一个右括号解除期待,于是存贮右括号;对于右括号解除一个期待,删除一个数组元素
switch(oprt)
{
case "(": Bracket.push(")"); break;
case ")": {
if(Bracket.length==0)
{
alert("Error!\ninvalid ']' is found!");
return 1;
}
else if(Bracket[Bracket.length-1]!=")")
{
alert("Error!\n'"+Bracket.pop()+"' expected but ')' found!");
return 1;
}
else Bracket.pop();
break;
}
case "[": Bracket.push("]"); break;
case "]":{
if(Bracket.length==0)
{
alert("Error!\ninvalid ']' is found!");
return 1;
}
else if(Bracket[Bracket.length-1]!="]")
{
alert("Error!\n'"+Bracket.pop()+"' expected but ']' found!");
return 1;
}
else Bracket.pop();
break;
}
}
return 0;
}
//--------------------------------------------------------------------
//多于运算符的判断:允许左侧为左括号活着操作数,允许右测为左括号或操作数,如果右侧为结束符返回错误
function GetError(opnd1,opnd2,optr,exp)
{
//操作符不可以作为结束
if(opnd2=="")
{
alert("Error!\nOperater '"+optr+"' expect a number but not found!\nCurrent char:"+exp);
return 1;
}
//操作符左测只能为运算数、右括号
if(isNaN(opnd1)&&opnd1!=")"&&opnd1!="]")
{
alert("Error!\nOperater '"+optr+"' expect a number but not found!"
+"\n'"+opnd1+optr+opnd2+"' is not valid!\nCurrent char:"+exp);
return 1;
}
//操作符右侧只能为运算数、左括号
if(isNaN(opnd2)&&opnd2!="("&&opnd2!="[")
{
alert("Error!\nOperater '"+optr+"' expect a number but not found!"
+"\n'"+opnd1+optr+opnd2+"' is not valid!\nCurrent char:"+exp);
return 1;
}
return 0;
}
//--------------------------------------------------------------------
//对于做括号的判断:只检测右边是否位操作数活着左括号,如果是结束符或有括号都返回错误
function GetError2(Bracket,opnd1,opnd2,optr,exp)
{
//对于左括号不允许右侧为结束符
if(opnd2=="")
{
alert("Error!\n missing a number or left parenthesis!\nCurrent char:"+exp);
return 1;
}
//对于左括号不允许左侧为数字
if(opnd1!="")
{
alert("Error!\n Operate expected but '"+optr+"' found!\nCurrent char:"+exp);
return 1;
}
//右侧值允许运算数、左括号
if(isNaN(opnd2)&&opnd2!="("&&opnd2!="[")
{
alert("Error!\n a number or left parenthesis expected but '"+opnd2+"' found!\nCurrent char:"+exp);
return 1;
}
//监测括号的匹配情况
if(GetBracketError(Bracket,optr))return 1;
return 0;
}
//--------------------------------------------------------------------
//对于右括号的判断:只检测右边的字符是否位运算符、右括号、结束符
function GetError3(Bracket,opnd1,opnd2,optr,exp)
{
//右侧值允许结束符、运算符、右括号
if(opnd2!=""&&opnd2!="+"&&opnd2!="-"&&opnd2!="*"&&opnd2!="/"&&opnd2!=")"&&opnd2!="]")
{
alert("Error!\nexpected Operater but '"+opnd2+"' found!\nCurrent char:"+exp);
return 1;
}
//监测括号的匹配情况
if(GetBracketError(Bracket,optr))return 1;
return 0;
}
//--------------------------------------------------------------------
//
function CheckExp(Exp){
var Bracket=new Array();//用于检测括号的匹配
var OPND="";//临时存放运算数
var Char="";//当前检测的字符
var ResultExp="";//用于监测检查点
for(i=0;i<Exp.length;++i)
{
Char=Exp.charAt(i);
if(!isNaN(Char)||Char==".")
{
OPND+=Char;
ResultExp+=Char;
}
else
{
switch(Char)
{
case "+": if(GetError(OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
OPND="";
break;
case "-": if(GetError(OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
OPND="";
break;
case "*": if(GetError(OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
OPND="";
break;
case "/": if(GetError(OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
OPND="";
break;
case "%": if(isNaN(OPND))return alert("Error!\n'"+OPND+"%' is not a number!\nCurrent char:"+exp);
//OPND/=100;
;break;
case "(": if(GetError2(Bracket,OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
break;
case ")": if(GetError3(Bracket,OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
break;
case "[": if(GetError2(Bracket,OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
break;
case "]": if(GetError3(Bracket,OPND,Exp.charAt(i+1),Char,ResultExp))return 0;
break;
default : return alert("Error!\n'"+Char+"' is invalid character!\nCurrent char:"+exp);
}
ResultExp+=Char;
}
}
if(Bracket.length!=0)return alert("Error!\n'"+Bracket[Bracket.length-1]+"' expected but not found!\nCurrent char:"+ResultExp);
return 0;
}
//-->
</SCRIPT>
<input id=Expression value="[8-8.0%*((1)+1)+1"><input id=Result value="=">
<BR><input type=button value="check" onclick="if(!CheckExp(Expression.value))test();">
<SCRIPT LANGUAGE="JavaScript">
<!--
function test(){
exp=Expression.value;
exp=exp.replace(/\[/g,"(");
exp=exp.replace(/\]/g,")");
exp=exp.replace(/\%/g,"/100");
Result.value=eval(exp);
}
//-->
</SCRIPT>
</BODY>
</HTML>