计算器的Golang实现, 支持 +-*/,并会判断表达式是否合法

package code

import (
"strconv"
"unicode"
)

type Calculator struct {
origin  string
s       string
left    int
signMap map[byte]bool
}

func NewCalculator(s string) Calculator {
signMap := map[byte]bool{
    '+': true,
    '-': true,
    '*': true,
    '/': true,
    '(': true,
    ')': true,
    ' ': true,
}
return Calculator{
    origin:  s,
    s:       s,
    left:    0,
    signMap: signMap,
}
}

func (cal *Calculator) Execuate() int {
stack := NewStack()
num := 0
numFlag := false
emptyFlag := false
sign := '+'
//往前遍历字符串
for len(cal.s) > 0 {
    c := cal.s[0]
    cal.s = cal.s[1:]
    if c == ' ' {
        emptyFlag = true
        continue
    }
    //判断是不是数字,考虑到连续累加
    if unicode.IsDigit(rune(c)) {
        if numFlag {
            //数字之间不能有空格
            if emptyFlag {
                panic(cal.origin + ": express error, empty can not between in numbers")
            }
        } else {
            numFlag = true
        }
        num = num*10 + (int(c) - int('0'))
    } else {
        numFlag = false
        if _, ok := cal.signMap[c]; !ok {
            panic(cal.origin + ": express error, invaild sign:" + string(c))
        }
    }
    emptyFlag = false
    //如果是(,递归处理,直到 碰到)弹出,结果返回
    if c == '(' {
        cal.left++
        num = cal.Execuate()
    }
    //是操作符,或者到了字符串最后,进行sush操作
    if len(cal.s) == 0 || !unicode.IsDigit(rune(c)) {
        switch sign {
        case '+': //直接入stack
            stack.Push(num)
        case '-': //变成负数,再入stack
            num = 0 - num
            stack.Push(num)
        case '*': //取出statck的top元素并弹出,相乘,再入stack
            v, _ := stack.Peek()
            stack.Pop()
            stack.Push(num * v)
        case '/': //取出statck的top元素并弹出,相乘,再入stack
            v, _ := stack.Peek()
            stack.Pop()
            stack.Push(v / num)
        }

        sign = rune(c)
        num = 0
        numFlag = false
    }

    if c == ')' {
        cal.left--
        if cal.left < 0 {
            panic(cal.origin + ": express error, more )")
        }
        break
    }
}

if len(cal.s) == 0 && cal.left > 0 {
    panic(cal.origin + ":" + cal.s + ": express error, more (: " + strconv.Itoa(cal.left))
}
//statck求和,返回
return stack.Sum()
}

标签: none

添加新评论