组合公式为 "((r1c1+r1c2)/r1c3)"
        1. 组合的公式是一个字符串.
        2. 字符串元素包括"rc0123456789+-*/()"
        3. r1c1=7,r1c2=2,r1c3=4
        4. 求组合成的公式的值是多少.

解决思路:
        1.对公式进行字符合法性检查.
        2.对公式中出现的变量进行取值替换.
        3.检查语句的合法性.(组合规则)
        4.检查运算的合法性.(除数为0的情况)
        5.求值.


具体解决方法:
        str1 = "(r1c1+r1c2)/r1c3)"
        str1 = replace(str1," ","")  '去除公式中间出现的空格
        1.  对公式进行字符合法性检查.

              bool1 = getDataOperationCharCheck(str1)

              if bool1 = false then
                      Response.write "公式不合法.有异常字符出现.<br>"
              else
                      Response.write "公式检查通过!<br>"
              end if

        2.对公式中出现的变量进行取值替换

                RCstr = getdataoperation(str1)

        3.检查语句的合法性.(组合规则)

                bool2 = getDataOperationSyntaxCheck(RCstr)

                      if bool2 = false then
                                 Response.write "运算公式语法不合法,有组合异常字符出现.<br>"
                      else
                                 Response.Write "运算公式语法检查通过!<br>"
                      end if

          4.检查运算的合法性.(除数为0的情况)

                   bool3 = getDataOperationRunCheck(RCstr)

                        if bool3 = false then
                                Response.write "运算公式运算不合法,有除数为0出现.<br>"
                        else
                                Response.write "运算公式运算合法性检查通过!<br>"  
                        end if

           5.求值.
 
                        intValue = getRunSearch(RCstr)

           6.运算结果:

                        (((7*1.0)+(2*1.0))/(4*1.0)) = 2.25

'1.=============================================================

'对原始公式进行字符检查,是否有不合法的字符

function getDataOperationCharCheck(datastr)
       datastr = replace(datastr," ","")
        sumchar = "rc0123456789+-*/()"
        strlen = len(datastr)
        strreturn = true
        for i = 1 to strlen
                singlechar = mid(datastr,i,1)
                if instr(sumchar,singlechar) = 0 then
                        strreturn = false
                        exit for
                end if
        next
        getDataOperationCharCheck = strreturn
end function

'2.==============================================================

'对原始计划公式进行取值替换.
'实现方法:对原始字符串进行单个字符检查,
'在出现 "+-*/()" 中的任何一个字符时,对已经组合生成的变量进行取值.
'在取到值的同时对其进行 double 转换 ,实现方法是 (intvalue * 1.0)

function getdataoperation(datastr)
        strlen = len(datastr)  
        sunstr = ""
        strID = ""
        intvalue = 0
        singlechar = ""
        operationstr="()+-*/"
        for i=1 to strlen
                'Response.write mid(datastr,i,1) & "<br>" 
                singlechar = mid(datastr,i,1)
                if instr(operationstr,singlechar) > 0 then
   
                        if strID <> "" then
                                intvalue = getValue(strID)
                                sunstr = sunstr & "(" & intvalue & "*1.0)"   '(1)     
                                intvalue = 0
                                strID = ""          
                        end if
                        sunstr = sunstr & singlechar
                        singlechar = ""
                else
                        strID = strID & singlechar
                end if     
        next
        getdataoperation = sunstr
end function

'变量取值函数.
'下列数据是为测试使用.
'
function getValue(strRC)
        select case strRC
                case "r1c1"
                        getValue = 2
                case "r1c2"
                        getValue = 7
                case "r1c3"
                        getValue = 2
               end select
end function

'3.==============================================================

'对公式进行语法合法性检查.
'eg.检查 (),--,++,**,//,(/,*) 等 是否成对出现.
'检查是否有


function getDataOperationSyntaxCheck(datastr)
        strreturn = true
        datastr = replace(datastr," ","")  '去除所有的空格
        strlen = len(datastr)
        num1 = 0                           '记录 括号的 个数  采用 有 (  加1, 有 ) 减1
        upsinglechar = ""                  '相对本次的字符的上一个字符
        singlechar = ""
        operationstr1="()+-*/"
        operationstr2="(+-*/"              '相对 在 (  左边出现的运的符号是正确的.
 
        for i = 1 to strlen
                singlechar = mid(datastr,i,1)
                select case singlechar
                        case "("
                                num1 = num1 + 1
                                if upsinglechar <> "" then
                                        if instr(operationstr2,upsinglechar) = 0 then   '在左括号的左边若不为空,必需出现 "(+-*/" 中的一个.
                                                strreturn = false
                                                exit for
                                        end if
                                end if
   
                        case ")"
                                num1 = num1 - 1
                                if num1 < 0 then
                                        strreturn = false
                                        exit for
                                end if
                                if instr(operationstr2,upsinglechar) > 0 then       '在右括号的左边若不为空,必需不能出现 "(+-*/" 中的一个
                                        strreturn = false
                                        exit for
                                end if
   
                        case "+"
                                if instr(operationstr2,upsinglechar) > 0 then       '在加号的左边若不空,必需不能出现 "(+-*/" 中的一个
                                        strreturn = false
                                        exit for
                                end if
   
                        case "-"
                                 if instr(operationstr2,upsinglechar) > 0 then      '在减号的左边若不空,必需不能出现 "(+-*/" 中的一个
                                        strreturn = false
                                        exit for
                                end if
                        case "*"
                                 if instr(operationstr2,upsinglechar) > 0 then      '在乘号的左边若不空,必需不能出现 "(+-*/" 中的一个
                                        strreturn = false
                                        exit for
                                end if
                        case "/"
                                 if instr(operationstr2,upsinglechar) > 0 then      '在除号的左边若不空,必需不能出现 "(+-*/" 中的一个
                                        strreturn = false
                                        exit for
                                end if
                end select
                upsinglechar = singlechar  
                singlechar = ""
        next
        getDataOperationSyntaxCheck = strreturn
end function

'4.==============================================================
 
'对组合公式进行运算合法性的检查
'首选查找有没有 "/0"出现.
'其次查找类似 "/(****)" = /0 出现

function getDataOperationRunCheck(datastr)
        strreturn = true
        if instr(datastr,"/")>0 then
                if instr(datastr,"/0") > 0 then    
                        strreturn = false
                else

                        '对/ 后面出现的()内的数据进行运算,取值是否会有0出现.
                        '首先计算 "/" 出现的次数
                        '再次判断 "/(" 出现的次数
                        '若 "/(" 出现的次为0 则安全.

                        intnum1 = getInstrNum(datastr,"/")
                        intnum2 = getInstrNum(datastr,"/(")
                        if intnum2 > 0 then
                                for j = intnum2 to 1 step -1
                                        intpoint1 = getInstrPoint(datastr,"/(",j)
                                        if intpoint1 > 0 then
                                                sumpoint = getRunCheck(datastr,intpoint1)
                                                if  CDbl(sumpoint) = CDbl(0) then
                                                        strreturn = false
                                                        exit for
                                                end if
                                        end if
                                next     
                        end if
                end if  
        end if
        getDataOperationRunCheck= strreturn
end function


'检查字符运行的合法性.
'主要是对/()出现的字公式进行计算是否会等于0

function getRunCheck(datastr,intpoint1)
        strlen = len(datastr)
        intpoint = intpoint1 + 1
        intnum = 0
        singlechar = ""
        rcsearch = ""
        intreturn = 0
        for m = intpoint to strlen
                singlechar = mid(datastr,m,1)
                if singlechar = "(" then
                        intnum = intnum + 1
                end if
                if singlechar = ")" then
                        intnum = intnum - 1
                end if
                rcsearch = rcsearch & singlechar
                if intnum = 0 then    
                        intreturn  = getRunSearch(rcsearch)
                        exit for
                end if   
        next
        getRunCheck = intreturn
end function

'5.==============================================================

'求值.
function getRunSearch(strrcsearch)
         sql = "select " & strrcsearch & " as rcvalue "
         Set rs = conn.execute(sql)
         'Response.write "<br>" & strrcsearch & "=" & rs("rcvalue") & "<br>"
         getRunSearch = rs("rcvalue")
end function

'公共函数==============================================================

'返回substr  在 str1 中出现的次数

function getInstrNum(str1,substr)
        strlen = len(str1)
        substrlen = len(substr)
        singlechar = ""
        intreturn = 0
        for i = 1 to strlen
                singlechar = mid(str1,i,substrlen)
                if singlechar = substr then
                        intreturn = intreturn + 1
                end if
        next
        getInstrNum = intreturn
end function

'返回substr 在 str1 中 第 intnum 次出现的位置
'intnum 必需是大于0的正整数

function getInstrPoint(str1,substr,intnum)
        intreturn = 0
        strlen = len(str1)
        substrlen = len(substr)
        singlechar = ""
        intcount = 0
        for i = 1 to strlen
                singlechar = mid(str1,i,substrlen)
                if singlechar = substr then
                        intcount = intcount + 1
                end if
                if intcount = intnum then
                        intreturn = i
                        exit for
                end if
        next
        getInstrPoint = intreturn
end function