<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{margin: 0;padding: 0;user-select: none;}
li{list-style: none;}
.box{width: 250px;height: 500px;margin: 100px auto;}
.show{width: 188px;height: 20px;border: 1px solid orange;margin: 2px;text-align: center;line-height: 20px;user-select: text;font-size: 14px;color: #ccc;font-weight: 600;padding: 15px;}
li{width: 50px;height: 50px;border: 1px solid orange;margin: 2px;float: left;text-align: center;line-height: 50px;}
button{width: 70px;height: 35px;margin: 10px;}
.compute{margin-right: 5px;}
.reset{margin-left: 5px;}
</style>
</head>
<body>
<div class="box">
<div class="show"></div>
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>+</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>-</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>*</li>
<li>(</li>
<li>0</li>
<li>)</li>
<li>/</li>
<li>.</li>
</ul>
<button class="compute">compute</button>
<button class="reset">reset</button>
</div>
</body>
<script>
// 为每一个 li 绑定点击事件
var liList = document.getElementsByTagName("li")
var exstr = ""
for (let i = 0; i < liList.length; i++) {
let li = liList[i]
li.onclick = function () {
// 获取中缀表达式
exstr += this.textContent
show.innerHTML = exstr
// console.log(exstr)
}
}
// 点击计算按钮,在显示框中输出值
var show = document.getElementsByClassName("show")[0]
var combtn = document.getElementsByClassName("compute")[0]
var rebtn = document.getElementsByClassName("reset")[0]
combtn.onclick = function () {
if(exstr){
show.innerHTML = computeSuffix(midTransSuffix(strSplit(exstr)))
exstr = ""
}
}
rebtn.onclick = function () {
show.innerHTML = "请输入计算式"
exstr = ""
}
// 增加一个按 Enter 键 实现计算的事件
document.onkeypress = function (evt) {
// evt.key 获取按键的值(区分英文字母大小写)
console.log(evt.key)
if (evt.key == "Enter") {
show.innerHTML = computeSuffix(midTransSuffix(strSplit(exstr)))
exstr = ""
} else {
exstr += evt.key
show.innerHTML = exstr
}
console.log(exstr, "exstr")
}
// ==================================================================================================
// 将中缀表达式 字符串 => 数组
// ==================================================================================================
function strSplit(exstr) {
// 声明变量存储操作数左下标 数组
var index = 0, list = []
for (var i = 0; i < exstr.length; i++) {
// 忽略空格
if (exstr[i] == " ") {
continue
}
// 如果是操作符
// 1. 先将操作符前的操作数加入到数组中(判断是否为空)
// 2. 再将操作符本身加入到数组中
if ("+-*/()".indexOf(exstr[i]) != -1) {
if (exstr.slice(index, i)) {
list.push(exstr.slice(index, i))
}
list.push(exstr[i])
// 3. 将左下标后移一位
index = i + 1
}
}
// 循环结束判断是否存在最后一位操作数,存在,加入数组
if (i == exstr.length && exstr.slice(index, i)) {
list.push(exstr.slice(index, i))
}
return list
}
// function strSplit(exstr) {
// // 将输入的中缀表达式转为数组
// var numsex = []
// // 左右指针 记录操作数的起始下标
// var left = 0, right = -1
// // 以操作符分隔
// for (var i = 0; i < exstr.length; i++) {
// // 忽略空格
// if (exstr[i] == " ") {
// continue
// }
// // 判断,是否输入了操作数和操作符外的其他字符
// if ("+-*/()1234567890.".indexOf(exstr[i]) == -1) {
// return []
// }
// if ("+-*/".indexOf(exstr[i]) != -1) {
// // 是操作符
// numsex.push(exstr.slice(left, i))
// numsex.push(exstr[i])
// left = i + 1
// }
// if (exstr[i] == "(") {
// numsex.push(exstr[i])
// left = i + 1
// }
// if (exstr[i] == ")") {
// numsex.push(exstr.slice(left, i))
// numsex.push(exstr[i])
// left = i + 1
// }
// if (i == exstr.length - 1 && exstr.slice(left, i + 1).length > 0) {
// // 将最后一个操作数加入到数组中
// numsex.push(exstr.slice(left, i + 1))
// }
// }
// console.log(numsex, "中缀数组")
// return numsex
// }
// console.log(strSplit("103-5"))
// ==================================================================================================
// 中缀表达式转后缀表达式
// ==================================================================================================
function midTransSuffix(exlist) {
// 栈的创建
var opStack = new Object()
opStack.value = []
opStack.push = function (item) {
this.value.push(item)
}
opStack.pop = function () {
return this.value.pop()
}
opStack.peek = function () {
return this.value[this.value.length - 1]
}
opStack.isEmpty = function () {
return this.value.length == 0
}
opStack.size = function () {
return this.value.length
}
// 定义优先级判断
var dic = {}
dic['*'] = 3
dic['/'] = 3
dic['+'] = 2
dic['-'] = 2
dic['('] = 1
// 列表存储转换的后缀表达式
var outputList = []
for (var i of exlist) {
if ("+-*/()".indexOf(i) == -1) {
// 是操作数,直接添加到 列表中
outputList.push(i)
} else if (i == "(") {
opStack.push(i)
} else if (i == ")") {
while (opStack.peek() != "(") {
outputList.push(opStack.pop())
}
opStack.pop()
} else {
while (!opStack.isEmpty() && dic[opStack.peek()] >= dic[i]) {
outputList.push(opStack.pop())
}
opStack.push(i)
}
}
while (!opStack.isEmpty() && opStack.peek() != "") {
outputList.push(opStack.pop())
}
console.log(outputList, "后缀数组")
return outputList
}
// var prefix = "a+b*c+(d*e+f)*g"
// console.log(midTransSuffix(prefix))
// 检验栈对象是否成功
// console.log(opStack.value)
// console.log(opStack.push(5))
// console.log(opStack.value)
// console.log(opStack.push(10))
// console.log(opStack.peek())
// console.log(opStack.isEmpty())
// console.log(opStack.size())
// console.log(opStack.value)
// ==================================================================================================
// 后缀表达式计算
// ==================================================================================================
function computeSuffix(exlist) {
// 如果接收的是空数组
// 代表表达式错误 / 用户未输入
if (exlist.length == 0) {
return "请输入正确的表达式"
}
// 栈的创建
var opStack = new Object()
opStack.value = []
opStack.push = function (item) {
this.value.push(item)
}
opStack.pop = function () {
return this.value.pop()
}
opStack.peek = function () {
return this.value[this.value.length - 1]
}
opStack.isEmpty = function () {
return this.value.length == 0
}
opStack.size = function () {
return this.value.length
}
computeCharString = "+-*/"
for (var i = 0; i < exlist.length; i++) {
// 遍历表达式
switch (exlist[i]) {
case "+":
opStack.push(opStack.pop() + opStack.pop())
break
case "-":
var jianshu = opStack.pop()
opStack.push(opStack.pop() - jianshu)
break
case "*":
opStack.push(opStack.pop() * opStack.pop())
break
case "/":
var chushu = opStack.pop()
opStack.push(opStack.pop() / chushu)
break
default:
opStack.push(parseFloat(exlist[i]))
}
}
// return Math.round(opStack.pop(), 2)
var result = opStack.pop()
console.log(result, "后缀结果")
if (isNaN(result)) {
return "计算出错啦!"
}
return result % 1 == 0 ? result : result.toFixed(2)
}
// console.log(computeSuffix(["4", "2", "/"]))
// var test = "12+6-(3+1)"
// console.log(computeSuffix(midTransSuffix(strSplit(test))))
</script>
</html>
javascript 实现计算器效果(输入中缀表达式字符串=>转为后缀表达式数组=>后缀表达式计算)
最新推荐文章于 2021-09-09 11:52:32 发布