目录
一、前言
二、前端
1. 完整jsp代码
2. 代码解读
三、后端
1. 栈的设计
2. 处理请求的Servlet
3. web.xml文件
四、完整代码下载
五、总结
在此之前
没有基础
的小伙伴可以看看我以前的文章,这样可以很好的理解这节讲的内容。
JSON&Ajax | JSON&Ajax |
Servlet的入门 | Servlet的入门 |
在做这个计算器之前,网上看了一下制作的
计算器
。发现都是实现最基本的运算,也没有混合运算
。页面也做得。。。不尽如人意,所以决定自己做一个(可能也不是很好,大佬勿喷~~)。
我们这里所制作的计算器
,可以实现最基本的加减乘除、模运算。也可以进行混合运算,但缺点就是:只能做整数运算
,对于小数运算可能会报语法错误
。除法运算
的结果也是整数(去除小数部分)
。效果如下:
相关依赖的下载
jquery-3.6.0.min.js
gson-2.2.4.jar
servlet-api.jar
我们前端页面做了一些美化,使用的是
Bootstrap5框架
。
<%--
Created by IntelliJ IDEA.
User: Long
Date: 2022/11/9
Time: 20:23
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>计算器title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/popper.js/2.9.3/umd/popper.min.js">script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.min.js">script>
<script type="text/javascript" src="./script/jquery-3.6.0.min.js">script>
<script type="text/javascript">
$(function () {
var $input = $("input[class='form-control']");
$("button").click(
function (e) {
$input.val($input.val()+e.target.value);
})
$("#button-addon2").click(
function () {
$("input[class='form-control']").val("");
}
)
$("#operation").click(
function () {
$.post(
"/calculator/calServlet",
{
data: $input.val().trim()
},
function (data) {
var regExp = new RegExp('error');
if (regExp.test(data)){
alert("语法错误");
$("input[class='form-control']").val("");
}else {
$("input[class='form-control']").val(data);
}
},
"json"
)
}
)
})
script>
<style>
button {
width: 50px;
height: 50px;
}
style>
head>
<body>
<div class="container" style="padding: 300px 500px;">
<div class="card" style="width: 18rem;">
<ul class="list-group" style="text-align: center">
<li class="list-group-item">
<div class="input-group mb-3">
<input type="text" class="form-control" aria-describedby="button-addon2">
<button class="btn btn-outline-secondary" type="button" id="button-addon2">Cbutton>
div>
li>
<li class="list-group-item">
<button type="button" class="btn btn-outline-primary" value="0">0button>
<button type="button" class="btn btn-outline-primary" value="1">1button>
<button type="button" class="btn btn-outline-primary" value="2">2button>
<button type="button" class="btn btn-outline-primary" value="3">3button>
li>
<li class="list-group-item">
<button type="button" class="btn btn-outline-primary" value="4">4button>
<button type="button" class="btn btn-outline-primary" value="5">5button>
<button type="button" class="btn btn-outline-primary" value="6">6button>
<button type="button" class="btn btn-outline-primary" value="7">7button>
li>
<li class="list-group-item">
<button type="button" class="btn btn-outline-primary" value="8">8button>
<button type="button" class="btn btn-outline-primary" value="9">9button>
<button type="button" class="btn btn-outline-primary" value="+">+button>
<button type="button" class="btn btn-outline-primary" value="-">-button>
li>
<li class="list-group-item">
<button type="button" class="btn btn-outline-primary" value="*">*button>
<button type="button" class="btn btn-outline-primary" value="/">/button>
<button type="button" class="btn btn-outline-primary" value="%">%button>
<input style="height: 50px;width: 50px" type="button" class="btn btn-outline-primary" value="=" id="operation"/>
li>
ul>
div>
div>
body>
html>
输入框获取按钮值
$("button").click(
function (e) {
$input.val($input.val()+e.target.value);
})
当鼠标点击
按钮
的时候,获取该按键的值
(除了=
建),将其添加到输入框
中去。
清除输入框内容
$("#button-addon2").click(
function () {
$("input[class='form-control']").val("");
}
)
当鼠标点击
按钮C
的时候,清除输入框
中内容。
如下图:
$("#operation").click(
function () {
$.post(
"/calculator/calServlet",
{
data: $input.val().trim()
},
function (data) {
var regExp = new RegExp('error');
if (regExp.test(data)){
alert("语法错误");
$("input[class='form-control']").val("");
}else {
$("input[class='form-control']").val(data);
}
},
"json"
)
}
)
当鼠标点击
按钮=
的时候,发送Ajax
请求。
这里我们利用回调函数
,来将后端
运算后的结果(json格式
)显示到输入框。
后端我们用了
栈的中缀表达式
,来处理前端发送来的运算式
。
package com.jl;
/**
* @author Long
* @date 2022/11/10
* @CSDN https://blog.csdn.net/qq_35947021
**/
public class ArrayStack{
private int maxsize;
private int top = -1;
private int[] stack;
public ArrayStack(int maxsize) {
this.maxsize = maxsize;
this.stack = new int[maxsize];
}
// 判断是栈是否为空
public Boolean isEmpty() {
if (top==-1) {
return true;
}else {
return false;
}
}
// 判断是否满栈
public Boolean isFull() {
if (top==this.maxsize-1) {
return true;
}else{
return false;
}
}
// 判断优先级
public int priority(int oper) {
if (oper == '*' || oper == '/'||oper=='%') {
return 1;
}
else if (oper == '+' || oper == '-') {
return 0;
}
else {
return -1; // 假定目前的表达式只有 +, - , * , /
}
}
// 入栈
public void push(int num) {
if (!isFull()) {
top++;
stack[top] = num;
}
}
// 出栈
public int pop() {
if (!isEmpty()) {
int value = stack[top];
top--;
return value;
}else{
throw new RuntimeException();
}
}
// 查看栈顶元素
public int check()
{
return stack[top];
}
// 判断是否为操作符
public Boolean isOper(char ch) {
if (ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='%') {
return true;
}else{
return false;
}
}
// 计算结果
public int cal(int num1, int num2, int oper) {
int res = 0; // res 用于存放计算的结果
switch (oper) {
case '+':
res = num1 + num2;
break;
case '-':
res = num2 - num1;
break;
case '*':
res = num1 * num2;
break;
case '/':
if (num1==0) {
throw new ArithmeticException();
}else {
res = num2 / num1;
}
break;
case '%':
res = num2 % num1;
break;
default:
break;
}
return res;
}
}
package com.jl;
/**
* @author Long
* @date 2022/11/10
* @CSDN https://blog.csdn.net/qq_35947021
**/
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CalServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response){
try {
execute(request, response);
} catch (Exception e) {
try {
response.getWriter().write(new Gson().toJson("error"));
} catch (IOException ioException) {
ioException.printStackTrace();
}
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
private void execute(HttpServletRequest request, HttpServletResponse response){
String expression = request.getParameter("data");
ArrayStack numStack = null;
ArrayStack operStack = null;
numStack = new ArrayStack(5);
operStack = new ArrayStack(5);
int index=0; /*遍历表达式的索引*/
int num1;
int num2;
char ch; /*存放每次扫描到的字符*/
int r; /*接收运算之后的结果*/
int oper; /*接收扫描到的操作符*/
String joint=""; /*用来拼接多位数字*/
while (true) {
ch = expression.charAt(index);
if (operStack.isOper(ch)) {
// 如果是操作符
if (!operStack.isEmpty()) {
// 操作符栈不为空
// 判断当前操作符与栈顶操作符的优先级
if (operStack.priority(ch)<=operStack.priority(operStack.check())) {
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
if (oper=='/'&&num1==0) {
throw new RuntimeException();
}else{
r = operStack.cal(num1, num2, oper);
numStack.push(r);
operStack.push(ch);
}
}else {
operStack.push(ch);
}
}else{
// 操作符栈为空
operStack.push(ch);
}
}else {
// 如果是数字
joint+=ch;
if (index==expression.length()-1) {
numStack.push(Integer.parseInt(joint));
}else{
if (operStack.isOper(expression.charAt(index+1))) {
numStack.push(Integer.parseInt(joint));
joint="";
}
}
}
index++;
if (index>=expression.length()) {
break;
}
}
while(true){
if (operStack.isEmpty()) {
break;
}
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
if (oper=='/'&&num1==0) {
throw new RuntimeException();
}else{
r = operStack.cal(num1, num2, oper);
numStack.push(r);
}
}
Gson gson = new Gson();
try {
response.getWriter().write(gson.toJson(numStack.pop()));
} catch (IOException e) {
throw new RuntimeException();
}
}
}
我们这里在处理请求,调用
execute()
的时候,采用的是中缀表达式
。
当有输入语法
有错误的时候,我这里采用的策略是:抛异常
,在调用execute()
的时候捕获异常,向前端发送error
字符串(json格式的
)。前端根据这个信息弹出警告弹窗
。
我们的运算结果是放到栈里的:运算完之后运算结果
会在栈顶,最后我们出栈
就可以拿到运算结果
。我们将后端的运算结果,通过response响应对象
返回给前端(json格式
),前端将其显示在输入框
。
它的基本概念小伙伴可以自行去了解。后边有时间我可能会写一篇。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CalServletservlet-name>
<servlet-class>com.jl.CalServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>CalServletservlet-name>
<url-pattern>/calServleturl-pattern>
servlet-mapping>
web-app>
完整代码下载地址
以上就是
简易计算器制作
的全部内容,里边涉及到了栈·的中缀表达式
。只要是为大家提供了一个思路,一个程序的实现多种多样。还是希望大家对一个问题提供多种解决方案,这样才能拓宽自己的思路。
如果文章有描述不正确或者错误的地方,还望指正。您可以留言或者私信我。
最后希望大家多多 关注+点赞+收藏^_^,你们的鼓励是我不断前进的动力!!!
感谢感谢~~~