什么?面试时手写一个计算器?看完这篇文章让你也可以实现
前言
近日发现一道面试题目,让我们手写一个计算器,我觉得这还挺有意思的,我就自己尝试了下,题目的基本要求实现了,下面我就和大家分享一下我是如何实现的 效果如下:
正文
实现思路
实现一个计算器,我们要在显示部分,显示我们刚刚输入了什么数字或者符号,那么这里我们就可以使用一个v-model
双向绑定我们输入的数据,然后如何处理我们输入的表达式,表达式分为两种,一种是正确能计算的表达式,一种是无法计算的表达式。然后使用什么判断我们可以开始计算我们输入的表达式,以及退格
,清屏
,清存
三个功能如何实现。
下面是我的页面样式部分
<template>
<div class="counter-wrapper">
<div class="counter-input">
<input type="text" v-model="number">
</div>
<div class="couter-btn">
<ul>
<li>存储</li>
<li>累存</li>
<li @click="numberCounter('7')">7</li>
<li @click="numberCounter('4')">4</li>
<li @click="numberCounter('1')">1</li>
<li @click="numberCounter('0')">0</li>
</ul>
<ul>
<li>取存</li>
<li>积存</li>
<li @click="numberCounter('8')">8</li>
<li @click="numberCounter('5')">5</li>
<li @click="numberCounter('2')">2</li>
<li @click="numberCounter('.')">.</li>
</ul>
<ul>
<li @click="backspace">退格</li>
<li @click="replaceNumber">清存</li>
<li @click="numberCounter('9')">9</li>
<li @click="numberCounter('6')">6</li>
<li @click="numberCounter('3')">3</li>
<li @click="numberCounter('+-')">+/-</li>
</ul>
<ul>
<li @click="onClear">清屏</li>
<li @click="numberCounter('/')">/</li>
<li @click="numberCounter('*')">X</li>
<li @click="numberCounter('-')">-</li>
<li @click="numberCounter('+')">+</li>
<li @click="numberCounter('=')">=</li>
</ul>
</div>
</div>
</template>
<style lang="less" scoped>
.counter-wrapper{
position: relative;
border: 4px solid #CCC;
width: 800px;
height: 540px;
transform: translate(-50%);
left: 50%;
.counter-input{
width: 100%;
height: 60px;
position: relative;
input{
position: relative;
width: 95%;
height: 60px;
border: 2px solid #CCC;
transform: translate(-50%);
left: 50%;
top:10px;
font-size: 24px;
text-align: right;
}
}
.couter-btn{
position: relative;
width: 95%;
border: 2px solid #CCC;
height: 400px;
margin-top: 40px;
transform: translate(-50%);
left: 50%;
display: flex;
ul{
text-align: center;
width: 90%;
height: 100%;
li{
list-style: none;
margin: 4px;
border: 1px solid #CCC;
width: 170px;
font-size: 20px;
height: 60px;
line-height: 60px;
cursor: pointer;
}
}
}
}
</style>
代码实现
这里由于计算器样式大家可以自定义,我就不过多介绍了 我们直接来看功能实现
显示框这里我们使用响应式数据,双向绑定响应式变量
const number = ref('0)
我们赋予一个初始值,为0,因为emmm,计算器开机使用也会默认显示一个0。对于我们输入数据,这里我们可以这样思考,我们把我们所有输入的内容变成一个字符串,就可以得到一个字符串形式的数学表达式,我们只需要处理这个字符串数学表达式就好了,那么什么时候开始计算呢?当然是检测到我们输入的数据是一个字符=
时,我们就开始处理并计算字符串数学表达式,那么我们现在开始来实现输入部分这个函数吧.
输入判断
这里我们使用try{}catch()
对于输入的内容处理,我们先打造一个数组用于存放我们输入的内容const counterNumber = ref([])
try {
if (symbol === '=') {
const result = eval(counterNumber.value.join(''))
if (typeof result === 'number' && !isNaN(result)) {
number.value = result;
}else if(counterNumber.value.length === 0){
number.value = 0
}else{
alert('非法字符')
onClear();
}
} else {
console.log(symbol);
counterNumber.value.push(symbol)
number.value = counterNumber.value.join('')
}
} catch (error) {
alert('非法计算')
onClear();
}
首先我们对输入的字符进行判断,如果我们拿到的是一个=
我们这里就要开始进行计算,这里就不得不提起eval()
这个伟大的内置函数它可以把字符串数学表达式转化成数学表达式进行计算,是的,没错,它就是可以帮我们把字符串形式的数学表达式,变成数学表达式计算,并返回结果。返回结果我们要判断这个值是否是一个number
类型且不是NaN
,如果是就打印这个内容否则,就报错,这里我们要注意一个细节,如果我们没有输入任何内容,直接点击等号,也是会计算的,所以我们要加一个特殊情况,就是数组为空,点击等号依旧不会报错的,就加上了else if(counterNumber.value.length === 0)
.这样我们就处理好了计算,那么,如何处理输入就是,我们把传入的数据,存在数组中,最后让双向绑定的数据number.value
等于数组counterNumber.value
变成字符串就好了。
清屏 清存 退格
清屏,我实现的是清除这个表达式,那么清除这个表达式,我们只需要让这个表达式的数组为空就好了,并在输入框显示为0
//清屏
function onClear(){
number.value = 0
counterNumber.value = []
}
其实说实话,我感觉我这里清存,退格,实现的功能都差不多(其实是我自己不理解这两个词语,分别的含义是什么),所以,我这里退格实现的是清除当前输入,显示上一次的输入
//退格
function backspace(){
if(counterNumber.value.length === 0){
alert('没有可退的数字')
number.value = 0
}
if(counterNumber.value.length > 0){
counterNumber.value.length = counterNumber.value.length - 1;
number.value = counterNumber.value.join('') ?? 0
}
}
每点击一个退格就会让表达式的长度减一,直至减到0,就无法再减。number.value = counterNumber.value.join('') ?? 0
这句代码我使用的是es6中三元运算符的简化形式表达一个算元运算符,等效于number.value = counterNumber.value.join('') ?counterNumber.value.jion(''): 0
;
然后清存,有一说一写的跟退格真的很像,若是诸位有什么对清存这一功能其他的想法也可以告诉作者我改进改进
// 清存
function replaceNumber(){
counterNumber.value.length = counterNumber.value.length - 1
number.value = counterNumber.value.join('')
if(counterNumber.value.length === 0){
number.value = 0
}
}
完成JS:
<script setup>
import { ref} from 'vue'
const counterNumber = ref([])
const number = ref('0')
function numberCounter(symbol) {
try {
if (symbol === '=') {
const result = eval(counterNumber.value.join(''))
if (typeof result === 'number' && !isNaN(result)) {
number.value = result;
}else if(counterNumber.value.length === 0){
number.value = 0
}else{
alert('非法字符')
onClear();
}
} else {
console.log(symbol);
counterNumber.value.push(symbol)
number.value = counterNumber.value.join('')
}
} catch (error) {
alert('非法计算')
onClear();
}
}
//清屏
function onClear(){
number.value = 0
counterNumber.value = []
}
// 清存
function replaceNumber(){
counterNumber.value.length = counterNumber.value.length - 1
number.value = counterNumber.value.join('')
if(counterNumber.value.length === 0){
number.value = 0
}
}
//退格
function backspace(){
if(counterNumber.value.length === 0){
alert('没有可退的数字')
console.log(111);
number.value = 0
}
if(counterNumber.value.length > 0){
counterNumber.value.length = counterNumber.value.length - 1;
number.value = counterNumber.value.join('') ?? 0
}
}
</script>
文章到这里就结束了,希望对大家有用,若有不足,恳请指出!!
转载自:https://juejin.cn/post/7398044739893362725