golang 使用栈模拟计算器

news2024/11/19 17:24:33

思路: 

 

// @Author sunwenbo
// 2024/4/12 16:51
package main

import (
	"errors"
	"fmt"
	"strconv"
)

// 使用数组来模拟一个栈的应用
type Stack struct {
	MaxTop int     //表示栈最大可以存放数的个数
	Top    int     //表示栈底,因为栈底是固定的,因此我们可以直接使用Top
	arr    [20]int //数组模拟栈
}

// 入栈
func (this *Stack) Push(val int) (err error) {

	// 先判断栈是否已经满了
	if this.Top == this.MaxTop-1 {
		fmt.Println("stack full")
		return errors.New("stack full")
	}
	this.Top++
	// 放入数据
	this.arr[this.Top] = val
	return
}

// 遍历栈,需要从栈顶开始遍历
func (this *Stack) List() {
	// 先判断栈是否为空
	if this.Top == -1 {
		fmt.Println("stack  empty")
		return
	}
	//curTop := this.Top
	fmt.Println("栈的情况如下:")
	for i := this.Top; i >= 0; i-- {
		fmt.Printf("arr[%d]=%d\n", i, this.arr[i])
	}
}

// 出栈
func (this *Stack) Pop() (val int, err error) {
	// 判断栈是否为空
	if this.Top == -1 {
		fmt.Println("stack empty")
		return 0, errors.New("stack empty")
	}
	// 先取值,再this.Top--
	val = this.arr[this.Top]
	this.Top--
	return val, nil
}

// 判断一个字符是不是一个运算符 [+,-,*,/]
func (this *Stack) IsOper(val int) bool {
	if val == 42 || val == 43 || val == 45 || val == 47 {
		return true
	} else {
		return false
	}

}

// 运算的方法
func (this *Stack) Cal(num1 int, num2 int, oper int) int {
	res := 0
	switch oper {
	case 42:
		res = num2 * num1
	case 43:
		res = num2 + num1
	case 45:
		res = num2 - num1
	case 47:
		res = num2 / num1
	default:
		fmt.Println("运算符错误..")
	}
	return res
}

// 编写一个方法返回某个运算符的优先级[程序员定的]
// [* / => 1, +- = 0 ]
func (this *Stack) Priority(oper int) int {
	res := 0
	if oper == 42 || oper == 47 {
		return 1
	} else if oper == 44 || oper == 45 {
		fmt.Println("oper=", oper)
		return 0
	}
	return res
}

func main() {
	// 数栈
	numStack := &Stack{
		MaxTop: 20,
		Top:    -1}
	// 符号栈
	operStack := &Stack{
		MaxTop: 20,
		Top:    -1}

	exp := "30+3*6-4"

	// 定义一个index,帮助扫描 exp
	index := 0
	// 为了配合运算,我们定义需要的变量
	num1, num2, oper, result, keepNum := 0, 0, 0, 0, ""
	for {
		fmt.Println("numStack")
		numStack.List()
		fmt.Println("operStack")
		operStack.List()

		// 这里需要增加一个逻辑,处理多位数的问题
		ch := exp[index : index+1] // 字符串
		// ch ==> "+" ==> 43
		temp := int([]byte(ch)[0])  // 字符对应的ASCI码
		if operStack.IsOper(temp) { //说明是符号
			//如果operStack 是一个空栈,直接入栈
			if operStack.Top == -1 { // 空栈
				operStack.Push(temp)
			} else {
				// 两个逻辑
				// 1. 如果发现operStack 栈顶的运算符的优先级大于等于当前准备入栈的运算符的优先级,就从符号栈Pop出,
				//并从数栈也pop两个数,进行运算,运算后的结果再重新入栈到栈,符号再入符号栈
				if operStack.Priority(operStack.arr[operStack.Top]) >= operStack.Priority(temp) {
					num1, _ = numStack.Pop()
					num2, _ = numStack.Pop()
					oper, _ = operStack.Pop()
					result = operStack.Cal(num1, num2, oper)
					// 将计算结果重新入数栈
					numStack.Push(result)
					// 将当前的符号压入符号栈
					operStack.Push(temp)
				} else {
					operStack.Push(temp)
				}
			}
		} else { //说明是数字
			//处理多位数的思路
			// 1. 先定义一个变量keepNum string,做拼接工作
			keepNum += ch
			// 2. 每次要向index的后面字符测试一下,看看是不是运算符,然后再做处理
			// 如果到表达式的最后了,直接将keepNum 转换成整数
			if index == len(exp)-1 { // 已经到表达式最后了
				val, _ := strconv.ParseInt(keepNum, 10, 64)
				numStack.Push(int(val))
			} else {
				// index 的后一位测试一下,看看是不是运算符,如果不是运算符则继续上面的for循环,做字符串拼接
				if operStack.IsOper(int([]byte(exp[index+1 : index+2])[0])) {
					val, _ := strconv.ParseInt(keepNum, 10, 64)
					numStack.Push(int(val))
					keepNum = ""
				}
			}
			//val, _ := strconv.ParseInt(ch, 10, 64)
			//numStack.Push(int(val))
		}
		// 继续扫描,先判断index 是否已经扫描到计算表达式的最后
		if index+1 == len(exp) {
			break
		}
		index++
	}
	// 如果扫描表达式完毕,依次从符号栈取出符号,然后从数栈中取出两个数,
	// 运算后的结果,入数栈,直到符号栈为空
	for {
		if operStack.Top == -1 {
			break //退出条件
		}
		num1, _ = numStack.Pop()
		num2, _ = numStack.Pop()
		oper, _ = operStack.Pop()
		result = operStack.Cal(num1, num2, oper)
		// 将计算结果重新入数栈
		numStack.Push(result)
	}
	// 如果我们的算法没有问题,表达式也是正确的则结果就是numStack的最后一个数
	res, _ := numStack.Pop()

	fmt.Printf("表达式: %s=%v", exp, res)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1594142.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java集合进阶】数据结构(二又树,二又查找树,平衡二又树)

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 …

java项目实战之图书管理系统(1)

✅作者简介:大家好,我是再无B~U~G,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 1.背景 图书管理系统是一种用于管理图书…

MongoDB 初识

介绍 MongoDB是一种开源的文档型数据库管理系统,它使用类似于JSON的BSON格式(Binary JSON)来存储数据。与传统关系型数据库不同,MongoDB不使用表和行的结构,而是采用集合(Collection)(Mysql表)和…

Linux 快问快答

如果对于找 Java 后端开发的话,我感觉会这几个差不多了,面试官应该不会问的这么详细吧。一般就问问 Linux 的几个常用的命令,然后做一些简单的性能排查就好了。如果面试被问到另外的问题,那我再补充进来,现在先掌握这么…

979: 输出利用先序遍历创建的二叉树的后序遍历序列

解法&#xff1a; #include<iostream> using namespace std; struct TreeNode {char val;TreeNode* left;TreeNode* right;TreeNode(char c) :val(c), left(NULL), right(NULL) {}; }; TreeNode* buildTree() {char c;cin >> c;if (c #) {return NULL;}TreeNode*…

CTF之comment

网站的登录框里有提示 账号&#xff1a;zhangwei 密码&#xff1a;zhangwei***&#xff08;后三位要自己猜&#xff09; 用burpsuit抓包爆破发现密码为zhangwei666 进去后就一个留言榜&#xff08;目前没发现怎么用&#xff09; 扫一下网站发现git泄露 1.下载 进入root用户&…

964: 数细胞

样例&#xff1a; 解法&#xff1a; 1.遍历矩阵 2.判断矩阵[i][j]&#xff0c;若是未标记细胞则遍历相邻所有未标记细胞并标记&#xff0c;且计数 实现&#xff1a;遍历相邻所有未标记细胞 以DFS实现&#xff1a; function dfs(当前状态) {if (终止条件) {}vis[标记当前状…

构建动态交互式H5导航栏:滑动高亮、吸顶和锚点导航技巧详解

功能描述 产品要求在h5页面实现集锚点、吸顶及滑动高亮为一体的功能&#xff0c;如下图展示的一样。当页面滑动时&#xff0c;内容区域对应的选项卡高亮。当点击选项卡时&#xff0c;内容区域自动滑动到选项卡正下方。 布局设计 css 布局 为了更清晰的描述各功能实现的方式&…

CentOS 7安装Nginx

说明&#xff1a;本文介绍如何在CentOS 7操作系统中安装Nginx 下载安装 首先&#xff0c;去官网上下载Nginx压缩包&#xff0c;官网地址&#xff1a;https://nginx.org/en/download.html&#xff0c;我这里下载稳定版1.24.0&#xff1b; 上传到云服务器上&#xff0c;解压&am…

数据分析案例(三):基于RFM分析的客户分群

实验2 基于RFM分析的客户分群 Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢…

读书笔记:高效能人士的七个习惯

前言 恐惧感和不安全感 现代社会&#xff0c;太多的人饱受恐惧感的折磨。他们恐惧将来&#xff0c;恐惧失业&#xff0c;恐惧无力养家。这种弱点&#xff0c;常常助长了一种倾向&#xff1a;无论在工作时&#xff0c;还是回到家中&#xff0c;都倾向于零风险的生活&#xff0…

CMMI认证是什么?如何确定CMMI认证的目标和范围

CMMI&#xff08;Capability Maturity Model Integration&#xff09;认证是一种用于评估和改进组织软件和项目管理过程的框架。它由美国国防部软件工程所&#xff08;SEI&#xff09;开发&#xff0c;旨在帮助组织提高其软件和项目管理的成熟度水平。 CMMI认证的意义在于&…

Python求利率

要求 编写程序计算在给定利率、指定年数的情况下投资的未来值。这个计算公式如下。 使用文本域输入投资额、年份和利率。当用户单击“calculate”按钮时&#xff0c;在文本域中显示未来的投资值&#xff0c;如图所示。 代码实现 import tkinter as tkdef calculate():amou…

求圆、圆球和圆柱的面积和体积(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> //定义π常量的值&#xff1b; # define π 3.141526int main() {//初始化变量值&#xff1b;float r, h, S1, S2, P1, V1, V2;int judge 0;//提示用户&#x…

【Spring进阶系列丨第九篇】基于XML的面向切面编程(AOP)详解

文章目录 一、基于XML的AOP1.1、打印日志案例1.1.1、beans.xml中添加aop的约束1.1.2、定义Bean 1.2、定义记录日志的类【切面】1.3、导入AOP的依赖1.4、主配置文件中配置AOP1.5、测试1.6、切入点表达式1.6.1、访问修饰符可以省略1.6.2、返回值可以使用通配符&#xff0c;表示任…

设计模式之大话西游

8年前深究设计模式&#xff0c;现如今再次回锅&#xff5e; 还是大话设计模式 这本书还是可以的 大话西游经典的台词&#xff1a;“曾经有一份真挚的爱情摆在我面前,我没有珍惜,等我失去的时候,我才后悔莫及,人世间最痛苦的事莫过于此。如果上天能够给我一个再来一次的机会,我会…

内网通如何去除广告,内网通免广告生成器

公司使用内网通内部传输确实方便&#xff01;但是会有广告弹窗推送&#xff01;这个很烦恼&#xff01;那么如何去除广告呢&#xff01; 下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1CVVdWexliF3tBaFgN1W9aw?pwdhk7m 提取码&#xff1a;hk7m ID&#xff1a;…

大数据产品有哪些分类?各类里知名大数据产品都有哪些?

随着互联网技术的持续进步和全球数字化转型的推进&#xff0c;我们正处于一个数据爆炸的时代。在这样的大背景下&#xff0c;大数据已经逐渐崭露头角&#xff0c;成为了推动各行各业发展的关键因素和核心资源。大数据不仅仅是指数据的规模巨大&#xff0c;更重要的是它蕴含的价…

消除 BEV 空间中的跨模态冲突,实现 LiDAR 相机 3D 目标检测

Eliminating Cross-modal Conflicts in BEV Space for LiDAR-Camera 3D Object Detection 消除 BEV 空间中的跨模态冲突&#xff0c;实现 LiDAR 相机 3D 目标检测 摘要Introduction本文方法Single-Modal BEV Feature ExtractionSemantic-guided Flow-based AlignmentDissolved…

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…