华为机试-表达式求值

思路:先中缀转后缀,再求值

package main
import(
    "fmt"
    "unicode"
    "strings"
    "strconv"
)
// Stack声明
type Stack struct{
    top *node
    length int
}
type node struct{
    value interface{}
    prev *node
}
func New()*Stack{
    return &Stack{nil,0}
}
func (s *Stack)Len()int{
    return s.length
}
func (s *Stack)Peek()interface{}{
    if s.length==0{
        return nil
    }
    return s.top.value
}
func (s *Stack)Pop()interface{}{
    if s.length==0{
        return nil
    }
    n:=s.top
    s.top=n.prev
    s.length--
    return n.value
}
func (s *Stack)Push(value interface{}){
    n:=&node{value,s.top}
    s.top=n
    s.length++
}


func main(){
    var str string
    fmt.Scanln(&str)
    str=transexp(str)
//     fmt.Println(str)
    calculate(str)
}
func calculate(exp string){
    slice := strings.Split(exp, " ")
//     fmt.Println(exp,slice)
    explen:=len(slice)
    s:=New()
    for i:=0;i<explen;i++{
        str:=slice[i]
        
        if digit,err:=strconv.Atoi(str);err==nil{
            s.Push(digit)
        }else{
            s1, _ := strconv.Atoi(fmt.Sprintf("%v", s.Pop()))
            s2, _ := strconv.Atoi(fmt.Sprintf("%v", s.Pop()))
            switch str{
                case "+":
                    s.Push(strconv.Itoa(s1+s2))
                case "-":
                    s.Push(strconv.Itoa(s2-s1))
                case "*":
                    s.Push(strconv.Itoa(s1*s2))
                case "/":
                    if s1!=0{
                        s.Push(strconv.Itoa(s2/s1))
                    }
                    
            }
        }
        
    }
    res,_:=strconv.Atoi(fmt.Sprintf("%v", s.Peek()))
    fmt.Println(res)
}
func transexp(exp string)string{
    opStack:=New()
    explen:=len(exp)
    res:=""
    isNeg:=false
    for i:=0;i<explen;i++{
        str:=string(exp[i])
        switch str{
            case "":
                continue
            case "0","1", "2", "3", "4", "5", "6", "7", "8", "9":
                j:=i
                digit:=""
                for ;j<explen&&unicode.IsDigit(rune(exp[j])); j++ {
                    digit+=string(exp[j])
                }
                i=j-1
                if isNeg==true{
                    res+=" "+"-"+digit
                    isNeg=false
                }else{
                    res+=" "+digit
                }
            case "(":
                opStack.Push(str)
            case ")":
                for opStack.Len()>0{
                    preNode:=fmt.Sprintf("%v",opStack.Peek())
                    if preNode=="("{
                        opStack.Pop()
                        break
                    }
                    res+=" "+preNode
//                     res+=preNode
                    opStack.Pop()

                }
            default:
//                fmt.Println(i,str)
               if str=="-"{
                     if i-1>=0&&(unicode.IsDigit(rune(exp[i-1]))||string(exp[i-1])==")"){
                         isNeg=false
                     }else{                        
                         isNeg=true
                     }
                    
               }

                for opStack.Len()>0{
                    if isNeg==true{
                        break
                    }
                    top:=fmt.Sprintf("%v",opStack.Peek())
                    if isPrior(str,top){
                        break
                    }
                    res+=" "+top
//                     res+=top
                    opStack.Pop()
                }
                if !isNeg{
                    opStack.Push(str)
                }
                
        }
    }
    for opStack.Len() > 0 {
        res += fmt.Sprintf(" %v", opStack.Pop())
    }
    return res
}
func isPrior(op string, top string) bool {
    switch top {
    case "+", "-":
        if op == "*" || op == "/" {
            return true
        }
    case "(":
        return true
    }
    return false
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值