模擬棧&四則運算
尚硅谷Golang課

模擬棧&四則運算

//模擬棧的使用
type Stack struct {
	MaxTop int //最大可存個數
	Top    int //頂
	arr    [20]int
}

func (s *Stack) Push(val int) (err error) {
	//先判斷是否滿
	if s.Top == s.MaxTop-1 {
		fmt.Println("stack full")
		return errors.New("stack full")
	}
	//放入數據
	s.Top++
	s.arr[s.Top] = val
	return
}

func (s *Stack) Pop() (val int, err error) {
	//先判斷是否空
	if s.Top == -1 {
		fmt.Println("stack empty")
		return 0, errors.New("stack empty")
	}
	//彈出數據
	val = s.arr[s.Top]
	s.Top--
	return val, nil
}

//遍歷
func (s *Stack) List() {
	//先判斷是否空
	if s.Top == -1 {
		fmt.Println("stack empty")
		return
	}
	fmt.Println("stack now=")
	for i := s.Top; i >= 0; i-- {
		fmt.Printf("arr[%d]=%d\n", i, s.arr[i])
	}
}

//判斷字符是數字還運算符號
func (s *Stack) IsOper(val int) bool {
	if val == 42 || val == 43 || val == 45 || val == 47 {
		//ASC碼的+-*/
		return true
	} else {
		return false
	}
}

//運算
func (s *Stack) Cal(n1, n2, oper int) int {
	res := 0
	switch oper {
	case 42:
		res = n2 * n1
	case 43:
		res = n2 + n1
	case 45:
		res = n2 - n1
	case 47:
		res = n2 / n1
	default:
		fmt.Println("運算符號錯誤")
	}
	return res
}

//優先級
func (s *Stack) Priority(oper int) int {
	res := 0
	if oper == 42 || oper == 47 {
		res = 1
	} else if oper == 43 || oper == 45 {
		res = 0
	}
	return res
}

func main() {
	// stack := &Stack{
	// 	MaxTop: 5,  //最多存5個
	// 	Top:    -1, //表示棧為空
	// }
	// stack.Push(1)
	// stack.Push(2)
	// stack.Push(3)
	// stack.Push(4)
	// stack.Push(5)
	// stack.Push(6)
	// p1, _ := stack.Pop()
	// fmt.Println("彈出", p1)
	// p1, _ = stack.Pop()
	// fmt.Println("彈出", p1)
	// p1, _ = stack.Pop()
	// fmt.Println("彈出", p1)
	// p1, _ = stack.Pop()
	// fmt.Println("彈出", p1)
	// p1, _ = stack.Pop()
	// fmt.Println("彈出", p1)

	//四則運算練習

	//數字棧
	numStack := &Stack{
		MaxTop: 20,
		Top:    -1,
	}

	//運算符號
	operStack := &Stack{
		MaxTop: 20,
		Top:    -1,
	}

	exp := "30+20*6+1"
	n1 := 0
	n2 := 0
	oper := 0
	res := 0
	keepNum := ""

	//定義一個index來掃描
	index := 0
	for {
		ch := exp[index : index+1]  //字符串
		temp := int([]byte(ch)[0])  //對應的ASC碼
		if operStack.IsOper(temp) { //說明是符號
			if operStack.Top == -1 { //說明是空棧
				operStack.Push(temp) //就入
			} else {
				if operStack.Priority(operStack.arr[operStack.Top]) >= operStack.Priority(temp) {
					//比較一下棧頂的運算符號優先級,如果有先乘除的
					n1, _ = numStack.Pop()
					n2, _ = numStack.Pop()
					oper, _ = operStack.Pop()
					res = operStack.Cal(n1, n2, oper)
					//算完塞回去
					numStack.Push(res)
					operStack.Push(temp)
				} else {
					operStack.Push(temp)
				}
			}
		} else {
			//處理多位數,看index後面是不是運算符號
			//拼接
			keepNum += ch

			if index == len(exp)-1 { //如果已經到最後
				val, _ := strconv.ParseInt(keepNum, 10, 64)
				numStack.Push(int(val))
			} else {
				if operStack.IsOper(int([]byte(exp[index+1 : index+2])[0])) {
					val, _ := strconv.ParseInt(keepNum, 10, 64)
					numStack.Push(int(val))
					keepNum = ""
				}
			}
			//從ASC轉回數字
			// val, _ := strconv.ParseInt(ch, 10, 64)
			// numStack.Push(int(val))
		}
		//判斷是否繼續掃描
		if index+1 == len(exp) {
			break
		}
		index++
	}

	for {
		if operStack.Top == -1 {
			break
		}
		n1, _ = numStack.Pop()
		n2, _ = numStack.Pop()
		oper, _ = operStack.Pop()
		res = operStack.Cal(n1, n2, oper)
		//算完塞回去
		numStack.Push(res)
	}
	final, _ := numStack.Pop()
	fmt.Printf("算式%s=%v", exp, final)
}

上次修改於 2021-09-01

此篇文章的評論功能已經停用。