做一个简易计算器
1.目标图片
2.计算器的内容(HTML)
由图片可以看出,计算器是一个整体标签,里面分为两个大块级标签,第一个大块级标签用来存放计算器的显示框,第二个大块级标签用来存放计算机的按键。共16个按键,将第二个大块级标签分为四个块级标签,每个块级标签里存放四个小块级标签,每个小块级标签即一个按键。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>第四题</title>
<link href="css/fourth.css" rel="stylesheet" />
</head>
<body>
<!-- 讲一个整体标签拆成两个部分,一个标签用来放入计算机的显示框,另一个标签存放计算机的按钮 -->
<!-- 整体标签开始 -->
<div id="counter">
<!-- 显示框标签 -->
<div id="input"></div>
<!-- 计算机按钮标签开始,将其分为四个部分,每个部分保存4个计算机按钮 -->
<div id="countkey">
<!-- 按钮部分一 -->
<div id="key">
<div onclick="count(this)">7</div>
<div onclick="count(this)">8</div>
<div onclick="count(this)">9</div>
<div onclick="count(this)">+</div>
</div>
<div style="clear: left;"></div>
<!-- 按钮部分二-->
<div id="key">
<div onclick="count(this)">4</div>
<div onclick="count(this)">5</div>
<div onclick="count(this)">6</div>
<div onclick="count(this)">-</div>
</div>
<div style="clear: left;"></div>
<!-- 按钮部分三 -->
<div id="key">
<div onclick="count(this)">1</div>
<div onclick="count(this)">2</div>
<div onclick="count(this)">3</div>
<div onclick="count(this)">*</div>
</div>
<div style="clear: left;"></div>
<!-- 按钮部分四 -->
<div id="key">
<div onclick="count(this)">0</div>
<div onclick="count(this)">C</div>
<div onclick="count(this)">=</div>
<div onclick="count(this)">/</div>
</div>
<div style="clear: left;"></div>
</div>
<!-- 计算机按钮标签结束 -->
</div>
<!-- 整体标签结束 -->
<script src="js/fourth.js"></script>
</body>
</html>
3.计算器的样式(CSS)
对计算器的每个部分设置样式
/* 清除默认外边距和内边距 */
*{
margin: 0;
padding: 0;
}
/* 计算机设置基本样式并定位 */
#counter{
width:500px;
height: 400px;
background-color: #C0C0C0;
position: absolute;
top: 25%;
left: 35%;
}
/* 为显示框设置基本样式 */
#input{
width: 400px;
height: 40px;
background-color: white;
position: absolute;
top:3%;
left:10%;
border-top-style:inset;/* 清除默认外边距和内边距 */
*{
margin: 0;
padding: 0;
}
/* 计算机设置基本样式并定位 */
#counter{
width:500px;
height: 400px;
background-color: #C0C0C0;
position: absolute;
top: 25%;
left: 35%;
}
/* 为显示框设置基本样式 */
#input{
width: 400px;
height: 40px;
background-color: white;
position: absolute;
top:3%;
left:10%;
/* 为显示框边界设置样式显得更立体 */
border-top-style:inset;
border-left-style:inset;
border-right-style:inset;
border-bottom-style: inset;
}
/* 计算机按钮设置基本样式,每个部分浮动 */
#key div{
border: none;
width:90px;
height:40px;
background-color:#DDDDDD ;
line-height: 40px;
text-align: center;
/* 为计算机按钮边界设置样式 */
border-right-style: outset;
border-top-style: outset;
border-bottom-style: inset;
border-bottom-color: #DDDDDD;
/* 设置浮动 */
float: left;
/* 为按钮添加外边距调整按钮之间的距离 */
margin-top:30px;
margin-left: 28px;
}
/* 为计算机按钮整个部分添加外边距,使第一行的按钮能与显示框保持距离 */
#countkey{
margin-top: 80px;
}
border-left-style:inset;
border-right-style:inset;
border-bottom-style: inset;
}
/* 计算机按钮设置基本样式,每个部分浮动 */
#key div{
border: none;
width:90px;
height:40px;
background-color:#DDDDDD ;
line-height: 40px;
text-align: center;
border-right-style: outset;
border-top-style: outset;
border-bottom-style: inset;
border-bottom-color: #DDDDDD;
float: left;
margin-top:30px;
margin-left: 28px;
}
/* 为计算机按钮整个部分添加外边距,使第一行的按钮能与显示框保持距离 */
#countkey{
margin-top: 80px;
}
完成样式后,计算器基本内容可以在网页里呈现出来
4.计算器的功能(JS)
接下来实现计算器的功能,首先要清楚计算器每个部分及每个部分的功能
首先显示框是用来显示点击按钮后的结果,按钮分为四种按钮:
1.数字按钮:点击后显示框可以显示相应的数字或将对应的数字与之前输入的内容拼接起来。
2.运算符按钮:点击后将运算符号和之前输入的内容拼接起来。
从上面两部分可以看出,实现拼接功能很容易就能联想到字符串,在实现功能时肯定要定义一个字符串变量
3.结果按钮"=":计算输入的结果并显示
结合前面的思路,输入的肯定是一个字符串,要对字符串内容进行运算,那么可以用eval函数
4.清除按钮"C":清空显示屏
那么只需要对字符串变量赋空值即可
秉持要操作,先得到的原则,我们需要先得到对象,对象为两个,一个是显示框,另一个就是按钮
可是按钮共有16个,如果每个都要得到,那么仅按钮就需要定义16个变量。 所以在此我们就可以设一个有参函数,定义两个变量,一个用来取显示框,另一个来取参数的内容即使用innerhtml。参数为Obj,在写完后每个按钮利用onClick点击事件调用函数,传过去的参数为this。
在JS里定义功能函数:
在HTML里每个按钮标签里调用该函数
接下来是实现按钮功能。根据上面的思路我们先定义一个空字符串并从条件表达式简单的写
首先是清除按钮"C",很明显当条件成立时只需要将字符串变量变为空
然后是结果按钮"=",条件成立时变量等于eval(变量名)即可
然后是其余按钮,它们需要实现的主要就是拼接。那么就用+=将字符串变量和按钮的内容拼接起来。
最后是显示,直接将字符串变量赋给显示屏的变量即可。
到此基本功能已经实现,但总会出现一些意外情况,比如点错了连续输入两个运算符,又或是开头直接输入乘除号等,为了更加规范,便需要添加一些判定,以下是自己目前能考虑到的情况
1.字符串的首字母是乘号或除号时输入不合法,比如"*36",“/9+8”
这里我想到了String类里的CharAt方法,利用其取出首字符进行判定
2.字符串连续出现相同的运算符,比如"7++",“787945–”
很明显判定时,每个相邻之间的位置都有可能出现这种情况。这里我想到了用循环去判定,仍然用CharAt方法去判定
3.开始时直接点击"="按钮
开始时字符串为空,用它作为判定条件,执行报错即可。
4.报错后,字符串的内容就成了报错的内容。此时在进行运算就会直接在报错的字体后面拼接
于是设一个if语句,判定字符串里内容为报错时,将字符串清空
5.进行一次运算后,数值会保留在显示屏上,如果这时候输入数字,会直接拼接在后面。例如运算出结果为"16",这时候如果直接输入"6",那么就会变成"166"。
很明显这种情况并不是我们想要的,我们想下次输入数字时,将前面的运算结果清除,但如果下次输入运算符,计算器应该仍是拼接他们,这时候需要注意两个点:
在此之前,我们可以设置控制台显示输入结果和result类型
5.1 : 此时的result已经不是String类型,变为了number类型
5.2:我们利用innerhtml得到的按钮的内容是String类型;
虽然此时result是number类型,但因为获得的按钮内容仍是String类型,通过拼接表达式又拼接成了字符串赋给了result,然后result又变成了String类。
那么我们就利用result变成number类这一特性来进行判定,因为不管是清除还是拼接都是在运算结果出来后的状况,所以当变为number类时再进行下一步操作,判定是否输入的是运算符,如果不是就清空显示屏内容。这里面就可以用 if嵌套。
5.过程中遇到的一些问题
1.点击运算符按钮和数字按钮时,发现没有拼接起来
解决方案:起初我以为是我的拼接表达式写的不对,或者是思路有问题,innerhtml取得内容不能拼接等等,最后发现是我把定义字符串变量的位置写错了,我将它写入了函数里即成了局部变量,每次调用函数时,都会先让它变成空字符串,再进行后面的操作,将定义字符串变量写在函数之前,即将字符串变量变为全局变量即可。
错误代码:
正确代码:
2.执行合法表达式没有达到预期效果
当时把合法情况的表达式写入了for循环里,结果发现这样的话,每次合法时都会运算一下,于是我又将它写在了循环体外面,结果发现当遇到不合法的情况时赋给result报错内容后跳出循环,然后又会执行eval运算。
解决方案:首先肯定要写在循环体外,但是不合法的时候不能执行合法表达式,于是我想到了布尔变量,我将其加到了函数体内,每次调用函数时就会使其为true,如果判定不合法时在赋给result报错内容后,然后将布尔变量变为false,再跳出循环,而合法表达时放在if语句里,如果布尔型变量为true才能执行。这样就避免了前面的问题发生。
3.判定运算结果之后的操作
起初我想的时将判断是否为运算符和数值类型是否为number用||连接起来。但是我忽略了一个问题:它为number类是绝对成立的,也就是说这个表达式一直为真,不管是否为运算符都会执行。后来我用&&去连接它们,但是当输入的不是运算符时,两边都为真,条件就会成立。从而将字符串清空了。
解决方案:于是我选择了if嵌套,将等于number类放在前提,成立了后再去判断是否是运算符。并且四个运算符都不是时再执行清空操作。后来我发现我之前的不为运算符的判定式也写的不对,每个小块之间应该用&&连接
于是有了第二种写法:
4.判定直接输入"="时的情况
当时我是想着直接把result=""跟其余不合法情况写在一起用||连接起来,但是在测试时发现并没有起作用,我猜测可能是因为如果字符串为空的话,本来长度就为0,但是我是把他放在for循环里执行的,而for循环判定时涉及到了字符串的长度。i初始值为0,字符串长度减1就变成了-1,那么for循环根本不会执行。也就没有判定这一说。
解决方案:将判定为空的条件和其余不合法情况条件分开来写,两者之间用if…else 来联系,因为不论是首字符是乘除号还是字符串里有连续的运算符,实际此时的字符串并不是空的。
JS完整代码:
/* 计算机功能分为4个部分,一个是点击数字按钮输入数值,一个是点击运算符按钮拼接内容,
一个是点击"="进行相应的运算并显示结果,最后一个是点击"C"清除屏幕上的内容*/
// 定义一个字符串用来拼接,存储变量
var result="";
function count(obj){
var inputObj=document.getElementById("input");
var KeyObj=obj.innerHTML;
// 定义一个布尔型变量,来确定点击"="时的应实现哪种情况
var judge=true;
// 点击"C"时清除内容
if(KeyObj=="C"){
result="";
}
/* 点击"="时分情况,"="相当于对前面做的一系列操作进行判定,那么就分为合法和不合法两种情况
不合法: 如果字符串首字母是"*"或"/"又或者输入时连续输入相同的运算符就显示输入格式错误,
合法: 其余的情况就利用eval函数计算 */
else if(KeyObj=="="){
// 不合法时的情况
//未进行输入直接按"="
if(result==""){
result="输入格式错误,请重新输入";
}
// 字符串内容不规范
else {
for(var i=0;i<result.length-1;i++){
if((result.charAt(i)=="+"&&result.charAt(i+1)=="+")||(result.charAt(i)=="-"&&result.charAt(i+1)=="-")||
(result.charAt(i)=="*"&&result.charAt(i+1)=="*")||(result.charAt(i)=="/"&&result.charAt(i+1)=="/")||
(result.charAt(0)=="*"||result.charAt(0)=="/")){
result="输入格式错误,请重新输入";
judge=false;
break;
}
}
// 合法时的情况
if(judge==true){
result=eval(result);
}
}
}
//不管是点击数字还是运算符应该都是字符串的拼接,但是如果已经有结果就要分情况
/*如果此时已经计算过一次,那么result的数值类型会变成number,这时候如果直接进行下次运算,先输入数字的话就会和上一次的结果拼接在一块
所以要在result的类型变为number的基础上再进行是否运算符的判断,即if嵌套*/
else {
if((KeyObj!="+"&&KeyObj!="-"&&KeyObj!="*"&&KeyObj!="/") && (typeof(result)=="number") ){
result="";
}
result+=KeyObj;
}
// 将每次操作后的result值显示到显示框上
inputObj.innerHTML=result;
// 如果格式错误将字符串清空,否则会直接继续在后面拼接,影响重新输入的操作。
if(result=="输入格式错误,请重新输入"){
result="";
}
}
6.结果
经过目前测试,想要的功能都已经实现