先看效果
整体思路
输入一个式子(中缀表达式),将其传入并转换为后缀表达式,接着通过计算后缀表达式来获得结果。
知识点补充
- 逆波兰表达式:也叫后缀表达式,所谓后缀就是指运算符写在后面。如 ( ( 1 2 + ) ( 3 4 + ) * )
- 中缀表达式:就是平常使用的算式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
- 后缀表达式对于计算机会更加友好,所以我们要将中缀表达式转换为后缀表达式进行计算。
- 逆波兰表达式运算法则:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中。
代码实现
package main
import (
"fmt"
"strconv"
)
const Max_Size = 100
// Stack结构体表示栈,栈中的元素存储在data数组中
type Stack struct {
data [Max_Size]string //一个长度最大值为Max_Size的字符串数组
top int //top表示Stack栈的栈顶元素位置
}
// init方法初始化了栈的状态
func (s *Stack) init() {
s.top = -1 //一种约定,表示栈的空状态
}
// push方式用于先将top++后,再把传参elem添加进Stack栈顶中
func (s *Stack) push(elem string) {
if s.top == Max_Size-1 { //判断栈是否已满
fmt.Println("Error: the stack is full")
} else { //向栈中添加元素
s.top++
s.data[s.top] = elem
}
}
// pop方法先返回栈顶元素的的值,再top--。并不会弹出栈顶元素
func (s *Stack) pop() string {
var elem string
if s.top < 0 {
fmt.Println("Error:the stack is empty")
} else {
elem = s.data[s.top]
s.top--
}
return elem
}
// Get_RPN 用于将传参src中的中缀表达式转换为后缀表达式,并将后缀表达式输出
func Get_RPN(src string) [Max_Size]string {
var dst [Max_Size]string //创建了一个最大值为Max_Size的det数组,用于存放数字和操作符(即后缀表达式)
var op Stack //op是Stack结构体的实例,用于存储操作符
op.init()
var j int
var t string
//此for循环用于遍历src中的每一个字符
for i := 0; i < len(src); { //循环体中没有迭代语句i++,但循环可照常进行
//此if语句用于将src中的数字传入到dst
if i < len(src) && (string(src[i]) >= "0" && string(src[i]) <= "9") { //3,5,8,12,14,17 //用于判断该字符是否为数字 //字符的比较是通过把这个字符经ASCII转换成数字之后,对这个数字进行比较
//把前i个连续数字拼接之后放入dst数组中
for t = ""; i < len(src) && (string(src[i]) >= "0" && string(src[i]) <= "9"); i++ {
t = t + string(src[i])
}
dst[j] = t
j++
}
//此if语句用于将
if i < len(src) && string(src[i]) == "(" { //1,2,11
op.push(string(src[i]))
i++
} else if i < len(src) && string(src[i]) == ")" { //6,9,15
for op.top != -1 && op.data[op.top] != "(" {
dst[j] = op.pop()
j++
}
op.pop()
i++
} else if i < len(src) && op.top == -1 { //10
op.push(string(src[i]))
i++
} else if i < len(src) && op.data[op.top] == "(" { //4,7,13
op.push(string(src[i]))
i++
} else if i < len(src) && (string(src[i]) == "*" || string(src[i]) == "/") && (op.data[op.top] == "+" || op.data[op.top] == "-") { //16
op.push(string(src[i]))
i++
} else if i < len(src) {
dst[j] = op.pop()
j++
}
}
for op.top != -1 { //18,19
dst[j] = op.pop()
j++
}
fmt.Println(dst)
return dst
}
//用于计算传入的后缀表达式,并输出结果
func Calculate(RPN [Max_Size]string) {
var num Stack
num.init()
for i := 0; i < len(RPN); i++ {
if RPN[i] != "" {
if string(RPN[i]) >= "0" && string(RPN[i]) <= "9" {
num.push(RPN[i])
} else if RPN[i] == "+" {
x, _ := strconv.Atoi(num.pop())
y, _ := strconv.Atoi(num.pop())
n := x + y
num.push(strconv.Itoa(n))
} else if RPN[i] == "-" {
x, _ := strconv.Atoi(num.pop())
y, _ := strconv.Atoi(num.pop())
n := y - x
num.push(strconv.Itoa(n))
} else if RPN[i] == "*" {
x, _ := strconv.Atoi(num.pop())
y, _ := strconv.Atoi(num.pop())
n := y * x
num.push(strconv.Itoa(n))
} else if RPN[i] == "/" {
x, _ := strconv.Atoi(num.pop())
y, _ := strconv.Atoi(num.pop())
n := y / x
num.push(strconv.Itoa(n))
}
}
}
fmt.Println(num.data[0])
}
func main() {
fmt.Println("Input an expression like (10/2+3)*4-5")
var expr string
fmt.Scanln(&expr) //用于将用户输入的值传给expr的地址上,从而传给expr变量
RPN := Get_RPN(expr)
Calculate(RPN)
}