0
点赞
收藏
分享

微信扫一扫

go-计算器

伊人幽梦 2024-01-20 阅读 18

为了实践一下go语言,弄一个+-*/和有小括号的计算器,其中小括号的嵌套可以任意多个。 代码如下:

package main

import (
	"fmt"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

func main() {
	str := "6-4*(1+(2*((3+4)*2)+2)-(9-5*4)*2)-(2*3-(2+5+3-2*2))+6"
	var result []string
	for len(result) >= 0 {
		re := regexp.MustCompile(`\([^()]*\)`)
		result = re.FindAllString(str, -1)
		if len(result) == 0 {
			fmt.Println(calP2(str))
			return
		}
		str = calP3(str)
		//fmt.Println(str)
	}

}
func calP3(str string) string {
	//1.找出最深一层的嵌套
	re := regexp.MustCompile(`\([^()]*\)`)
	result := re.FindAllString(str, -1)
	//fmt.Printf("%s\n", result)

	newresult := resort(result)
	//fmt.Println(newresult)

	//2.计算最深一层的嵌套表达式的值,即没有括号的+-*/普通运算
	var calP2s []string
	for _, i := range newresult {
		calP2s = append(calP2s, calP2(i))
	}
	//fmt.Println(calP2s)

	//3.在str中,各个嵌套的表达式newresult对应替换成calP2s
	for i := 0; i < len(newresult); i++ {
		str = strings.ReplaceAll(str, newresult[i], calP2s[i])
	}
	return str
}

// 计算没有括号的普通运算
// str := "5+9+4-12*4*9*3+4/2/2-2-1-2+8/4-9/3+5*5*4/4/5*5-9/3*3"
func calP2(str string) string {
	//找出*/计算的表达式
	reNums := regexp.MustCompile(`\d[*/\d]+`)
	Nums := reNums.FindAllString(str, -1)
	//对*/表达式重新排序
	NewNums := resort(Nums)

	var p1Sum []string
	for _, i := range NewNums {
		//计算*/表达式的值
		p1 := calP1(i)
		p1Sum = append(p1Sum, p1)
	}

	//对*/表达式进行替换:12*4*9*3,4/2/2,8/4,5*5*4/4/5*5,9/3*3
	for i := 0; i < len(NewNums); i++ {
		str = strings.ReplaceAll(str, NewNums[i], p1Sum[i])
	}
	return calP1(str) //计算+-表达式的值
}

// 计算*/或+-表达式的值
// expr="5*5*4/4/5*5"
// expr="6+8-9+4-2-8"
func calP1(str string) string {
	reNums1 := regexp.MustCompile(`\d+`)
	reOperation1 := regexp.MustCompile(`[+-/*]`)
	Nums1 := reNums1.FindAllString(str, -1)
	Operation1 := reOperation1.FindAllString(str, -1)
	var sum int
	sum, _ = strconv.Atoi(Nums1[0])
	for i := 1; i < len(Nums1); i++ {
		switch Operation1[i-1] {
		case "+":
			m, _ := strconv.Atoi(Nums1[i])
			sum += m
		case "-":
			m, _ := strconv.Atoi(Nums1[i])
			sum -= m
		case "*":
			m, _ := strconv.Atoi(Nums1[i])
			sum *= m
		case "/":
			m, _ := strconv.Atoi(Nums1[i])
			sum /= m
		}
	}
	sumStr := strconv.Itoa(sum)
	return sumStr
}

// 计算*/有多少个
// expr="5*5*4/4/5*5"
func lencal(expr string) int {
	re := regexp.MustCompile("[+-/*]")
	result := re.FindAllString(expr, -1)
	return len(result)
}

// 对普通*/表达式重新排序,防止它的子集先被替换了,例如:"9/3"与"9/3*3"
// expr := []string{"12*4*9*3", "4/2/2", "8/4", "9/3", "5*5*4/4/5*5", "9/3*3"}
func resort(expr []string) []string {

	type strStruct struct {
		index  int
		strlen int
	}

	var strlens []strStruct
	for i := 0; i < len(expr); i++ {

		strlens = append(strlens, strStruct{i, lencal(expr[i])})
	}

	//对各个表达式的计算长度进行排序
	sort.SliceStable(strlens, func(i, j int) bool {
		return strlens[i].strlen < strlens[j].strlen
	})

	var Nums []string
	for i := len(strlens) - 1; i >= 0; i-- {
		Nums = append(Nums, expr[strlens[i].index])
	}
	return Nums
}
举报

相关推荐

0 条评论