Java之实现计算器
要求:
实现远程计算器,即客户端将要计算的数据发送给服务器,服务器端接收到数据后对接收到的数据进行解析,将计算的结果发送给客户端显示。服务器可实现的计算功能包括加(+)、减(-)、乘(*)、除(/)、阶乘、求幂(^)、斐波那契数(fib)。下图中的cls表示清空文本框中的数据。
需求:
监听鼠标和键盘事件,普通的四则运算可通过调用JDK自带的类可调用JS的功能,可以实现执行字符串中的运算公式的功能。相当于python中的eval(),
调用实例:
ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript"); try { return String.valueOf(jse.eval(str)); } catch (Exception t) {}
其他的功能如:fib(求斐波那契数)、^(求幂)、!(阶乘)通过自己写的函数实现:
代码如下:
//求幂
public String getMCF(String str){
String re = "(\\d+)\\^(\\d+)";
//通过正则表达式获取目标
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
int[] arr = new int[2];
String or="";
while (m.find()){
or = m.group();
}
int i =or.indexOf("^");
arr[0] = Integer.parseInt(or.substring(0,i));
arr[1] = Integer.parseInt(or.substring(i+1));
//根据Math 算出值
int result = (int) Math.pow(arr[0],arr[1]);
//对原式进行子串替换
String string=str.replace(String.valueOf(arr[0])+"^"+String.valueOf(arr[1])
,String.valueOf(result));
return string;
}
//求阶乘
public String getJC(String str){
String re = "(\\d+)\\!";//原来的写反了,阶乘的格式是5!的,原谅我的无知
//通过正则表达式获取目标
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
int n = 0;
String or ="";
while (m.find()){
or = m.group(0);
n= Integer.parseInt(or.replace("!",""));
}
//求阶乘:
String result = String.valueOf(JC(n));
//替换原式
return str.replace(or,result);
}
public int JC(int n){
//利用函数的调用计算阶乘
if (n==1){
return 1;
}
return JC(n-1)*n;
}
//求斐波那锲数
public String getFib(String str){
String re = "[f][i][b](\\d+)";
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
String or="";
int fib=0;
while (m.find()){
or =m.group();
fib = Integer.parseInt(or.substring(3));
}
System.out.println(Fib(fib));
//求值后替换原式
return str.replace(or,String.valueOf(Fib(fib)));
}
public int Fib(int fib){
//递归求斐波那锲
if(fib<=2){
return 1;
}
return Fib(fib-1) + Fib(fib-2);
}
遇到的问题
在用多线程的时候,一般线程还没执行就执行下面的代码了,所以用countdownlatch 进行确定线程已经运行结束,然后用类名.result获取所求得的值。
组合键盘绑定事件,这个也是在写的时候遇到的问题,可以用用isShiftDown() 确定shift键按下,然后并上另一个键是否被按下,例如:
else if (e.isShiftDown()&&e.getKeyCode()==KeyEvent.VK_F){ // content.setText(content.getText()+"fib"); }
主窗口:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
/*
* 做一个远程的计算器
*
* */
public class Calculator extends JFrame implements KeyListener{
JTextField content = new JTextField();
public Calculator(){
this.setSize(500,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
//设置图标
Image icon = new ImageIcon("src/question/image1.jpg").getImage();
this.setIconImage(icon);
JPanel panel = new JPanel();
addKeyListener(this);//添加键盘监听
panel.setBackground(Color.WHITE);
GridBagLayout gridBag = new GridBagLayout();//网格布局
GridBagConstraints c = new GridBagConstraints();//设置约束
GridBagConstraints c1 = new GridBagConstraints();//设置约束
JButton zero = new JButton("0");
JButton one = new JButton("1");
JButton two = new JButton("2");
JButton three = new JButton("3");
JButton four = new JButton("4");
JButton five = new JButton("5");
JButton six = new JButton("6");
JButton seven = new JButton("7");
JButton eight = new JButton("8");
JButton nine = new JButton("9");
JButton clear = new JButton("cls");
JButton enter = new JButton(" = ");
JButton multiplicationSign = new JButton("*");
JButton add = new JButton("+");
JButton cut = new JButton("-");
JButton divisionSign = new JButton("/");
JButton point = new JButton(".");
JButton JC = new JButton("!");
JButton fib = new JButton("fib");
JButton MCF = new JButton("^");
content.setOpaque(false);//设置透明
content.setFont(new Font("",Font.BOLD,25));//设置字体
content.setHorizontalAlignment(JTextField.RIGHT);//设置输入方向
content.setEditable(false);//设置不可编辑
//设置按钮属性
SetButton(one);
SetButton(two);
SetButton(three);
SetButton(four);
SetButton(five);
SetButton(six);
SetButton(seven);
SetButton(eight);
SetButton(nine);
SetButton(zero);
SetButton(enter);
SetButton(clear);
SetButton(cut);
SetButton(add);
SetButton(multiplicationSign);
SetButton(divisionSign);
SetButton(fib);
SetButton(MCF);
SetButton(JC);
SetButton(point);
clear.setBackground(Color.CYAN);
c1.fill = GridBagConstraints.BOTH;
c1.ipadx =100;
c1.ipady =100;
c1.weighty =1;
c1.weightx = 1;
c1.gridheight =4;
c1.gridwidth =4;
c1.gridx =0;
c1.gridy =0;
gridBag.addLayoutComponent(content,c1);
SetgridBag(clear,c,gridBag,0,5,1,1);
SetgridBag(enter,c,gridBag,1,5,1,1);
SetgridBag(zero,c,gridBag,2,5,1,1);
SetgridBag(multiplicationSign,c,gridBag,3,5,1,1);
SetgridBag(seven,c,gridBag,0,6,1,1);
SetgridBag(eight,c,gridBag,1,6,1,1);
SetgridBag(nine,c,gridBag,2,6,1,1);
SetgridBag(add,c,gridBag,3,6,1,1);
SetgridBag(four,c,gridBag,0,7,1,1);
SetgridBag(five,c,gridBag,1,7,1,1);
SetgridBag(six,c,gridBag,2,7,1,1);
SetgridBag(cut,c,gridBag,3,7,1,1);
SetgridBag(one,c,gridBag,0,8,1,1);
SetgridBag(two,c,gridBag,1,8,1,1);
SetgridBag(three,c,gridBag,2,8,1,1);
SetgridBag(divisionSign,c,gridBag,3,8,1,1);
SetgridBag(fib,c,gridBag,0,9,1,1);
SetgridBag(MCF,c,gridBag,1,9,1,1);
SetgridBag(JC,c,gridBag,2,9,1,1);
SetgridBag(point,c,gridBag,3,9,1,1);
//添加监视器
clear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//清除
content.setText("");
}
});
zero.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"0");
}
});
one.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"1");
}
});
two.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"2");
}
});
three.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"3");
}
});
four.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"4");
}
});
five.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"5");
}
});
six.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"6");
}
});
seven.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"7");
}
});
eight.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"8");
}
});
nine.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"9");
}
});
multiplicationSign.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"*");
}
});
cut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"-");
}
});
add.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"+");
}
});
divisionSign.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"/");
}
});
fib.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"fib");
}
});
MCF.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"^");
}
});
JC.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+"!");
}
});
point.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.setText(content.getText()+".");
}
});
//设置enter的动作事件
Action Aenter = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
String str = content.getText();
String result = null;
try {
result = GetValue(str);
content.setText(result);
} catch (IOException ioException) {
}
}
};
enter.addActionListener(Aenter);
enter.addKeyListener(this);
content.addKeyListener(this);
panel.add(content);
panel.add(zero);
panel.add(one);
panel.add(two);
panel.add(three);
panel.add(four);
panel.add(five);
panel.add(six);
panel.add(seven);
panel.add(eight);
panel.add(nine);
panel.add(clear);
panel.add(enter);
panel.add(multiplicationSign);
panel.add(add);
panel.add(cut);
panel.add(divisionSign);
panel.add(fib);
panel.add(MCF);
panel.add(JC);
panel.add(point);
panel.setLayout(gridBag);
this.add(panel);
this.setVisible(true);
}
public static void main(String[] args) {
new Calculator();
}
public void SetgridBag(Component component,GridBagConstraints c,
GridBagLayout gridBag,int gridx,int gridy,
int gridwidth,int gridHeight ){
//组件1(gridx,gridy)组件的左上角坐标,gridwidth,gridheight:组件占用的网格行数和列数
c.gridx = gridx;
c.gridy = gridy;
c.gridwidth = gridwidth;
c.gridheight = gridHeight;
// weightx=0,weighty=0,意思是组件大小固定,
// 不管面板如何变,自身就那么大,但是如果想让组件随面板变化的话,
// 可以设置weightx和weighty,设置为浮点数也行,其值代表着变化的大小,
// 也就是你宽度设为2,高度设为1的话,拉大面板会使组件越变越宽。
c.weightx = 1;
c.weighty =1;
// ipadx, ipady
// 组件的内部填充(可看做是 组件的内边距),即对组件最小大小的添加量。
// 组件的宽度至少为其最小宽度/高度加上 ipadx/ipady 像素
// c.ipadx = 100;
// c.ipady = 100;
c.fill = GridBagConstraints.BOTH;
gridBag.addLayoutComponent(component,c);
}
public void SetButton(JButton button){
button.setOpaque(true);//设置透明
// button.setBorder(null);//消除边框
button.setContentAreaFilled(false);//去掉背景点击效果
button.setFocusPainted(false);//去掉聚焦
button.setFont(new Font("",Font.BOLD,25));
button.setBackground(Color.RED); //白色背景
button.setForeground(Color.CYAN);
}
public String GetValue(String str) throws IOException {
// //JDK自带的类可以实现调用JS的功能,可以实现执行字符串中的运算公式的功能。相当于python中的eval
// ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
// try {
// return String.valueOf(jse.eval(str));
// } catch (Exception t) {}
int port = 4992;
String host ="localhost";
//创建一个CountDownLatch类,构造入参线程数
CountDownLatch countDownLatch = new CountDownLatch(1);
Service server= new Service(new ServerSocket(port));
Client client =new Client(new Socket(host,port),str,countDownLatch);
server.start();
client.start();
client.interrupt();
server.interrupt();
try {
// 当它为零的时候才会往下进行
//下面这句代码,CountDownLatch就阻塞在这里了
//直到countDown()到0了(从构造入参的线程数开始减)
//也即是所有线程都countDown了,
//则解除阻塞,代码继续往下执行
//注意,这句代码放在多线程countDown之后,多线程全部完成后
//继续往下执行的代码之前,起一个分界线的作用
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取所求的值
return Client.result;
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
//设置
if(e.getKeyChar() == KeyEvent.VK_ENTER){
String str = content.getText();
String result = null;
try {
result = GetValue(str);
content.setText(result);
} catch (IOException ioException) {
}
}else if(e.isShiftDown()&&e.getKeyChar() == KeyEvent.VK_SPACE){
content.setText("");
}
if(e.getKeyChar() == KeyEvent.VK_0){
}else if (e.getKeyChar() == KeyEvent.VK_1){
content.setText(content.getText()+1);
} else if (e.getKeyChar() == KeyEvent.VK_2){
content.setText(content.getText()+2);
}else if (e.getKeyChar() == KeyEvent.VK_2){
content.setText(content.getText()+2);
}else if (e.getKeyChar() == KeyEvent.VK_3){
content.setText(content.getText()+3);
}else if (e.getKeyChar() == KeyEvent.VK_4){
content.setText(content.getText()+4);
}else if (e.getKeyChar() == KeyEvent.VK_5){
content.setText(content.getText()+5);
}else if (e.getKeyChar() == KeyEvent.VK_6){
content.setText(content.getText()+6);
}else if (e.getKeyChar() == KeyEvent.VK_7){
content.setText(content.getText()+7);
}else if (e.getKeyChar() == KeyEvent.VK_8){
content.setText(content.getText()+8);
}else if (e.getKeyChar() == KeyEvent.VK_9){
content.setText(content.getText()+9);
}else if (e.isShiftDown()&&e.getKeyCode()==KeyEvent.VK_F){
//isShiftDown() 确定shift键按下
content.setText(content.getText()+"fib");
}else if (e.isShiftDown()&&e.getKeyCode()==KeyEvent.VK_6){
content.setText(content.getText()+"^");
}else if (e.getKeyCode() == 110){
content.setText(content.getText()+".");
}else if (e.getKeyCode()== 106){
content.setText(content.getText()+"*");
}else if (e.getKeyCode()== 107){
content.setText(content.getText()+"+");
}else if (e.getKeyCode()== 109){
content.setText(content.getText()+"-");
}else if (e.getKeyCode()== 111){
content.setText(content.getText()+"/");
}else if (e.getKeyCode()== 8){
//BackSpace
if (!content.getText().equals("")){
content.setText(content.getText().substring(0,content.getText().length()-1));
}
}else if (e.isShiftDown()&&e.getKeyCode()== KeyEvent.VK_1){
content.setText(content.getText()+"!");
}
}
@Override
public void keyReleased(KeyEvent e) {
}
}
客户端
import java.io.*;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
public class Client extends Thread {
private Socket socket;
public static String result;
public String str;
public CountDownLatch countDownLatch;
public Client(Socket socket, String str, CountDownLatch countDownLatch) {
this.socket = socket;
this.str = str;
this.countDownLatch = countDownLatch;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getStr() {
return str;
}
@Override
public void run() {
//建立连接
//客户端发送数据
try {
//获取输出流
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
ps.println(getStr());
//发送完毕
//接受数据
InputStream is = socket.getInputStream();
//转换为字符流
InputStreamReader isr = new InputStreamReader(is);
BufferedReader buff = new BufferedReader(isr);
setResult(buff.readLine());
//CountDownLatch类计数减一,
countDownLatch.countDown();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器端
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Service extends Thread{
private ServerSocket server;
private Socket socket;
public String str;
public String result;
public Service(ServerSocket server) {
this.server = server;
}
public String GetValue(String str){
//JDK自带的类可以实现调用JS的功能,可以实现执行字符串中的运算公式的功能。相当于python中的eval
ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
try {
//先确定是否存在 ^ 、 fib 、 !
if(!isSpecial(str)&&!isSpecial(str,"fib")){
return String.valueOf(jse.eval(str));
}else {
if (isSpecial(str,"^")){
str = getMCF(str);
}if(isSpecial(str,"!")){
str = getJC(str);
}if (isSpecial(str,"fib")){
str = getFib(str);
}
return String.valueOf(jse.eval(str));
}
} catch (Exception t) {}
return "";
}
public boolean isSpecial(String str){
//先确定是否存在 ^ 、 fib 、 !
String re = "(\\W)";
String[] ect = new String[]{"^","!"};
List<String> signalList =new ArrayList<String>();
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
while (m.find()){
signalList.add(m.group());
}
for (String siganl:signalList
) {
if (siganl.equals(ect[0])||siganl.equals(ect[1])){
return true;
}
}
return false;
}
public boolean isSpecial(String str,String signl){
//先确定是否存在 ^ 、 fib 、 !
String re = "(\\W)";
if (signl.equals("fib")){
re="[f][i][b]";
}
List<String> signalList =new ArrayList<String>();
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
while (m.find()){
signalList.add(m.group());
}
for (String siganl:signalList
) {
if (siganl.equals(signl)){
return true;
}
}
return false;
}
public String getMCF(String str){
String re = "(\\d+)\\^(\\d+)";
//通过正则表达式获取目标
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
int[] arr = new int[2];
String or="";
while (m.find()){
or = m.group();
}
int i =or.indexOf("^");
arr[0] = Integer.parseInt(or.substring(0,i));
arr[1] = Integer.parseInt(or.substring(i+1));
//根据Math 算出值
int result = (int) Math.pow(arr[0],arr[1]);
//对原式进行子串替换
String string=str.replace(String.valueOf(arr[0])+"^"+String.valueOf(arr[1])
,String.valueOf(result));
return string;
}
public String getJC(String str){
String re = "\\!(\\d+)";
//通过正则表达式获取目标
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
int n = 0;
String or ="";
while (m.find()){
or = m.group(0);
n= Integer.parseInt(or.replace("!",""));
}
//求阶乘:
String result = String.valueOf(JC(n));
//替换原式
return str.replace(or,result);
}
public int JC(int n){
//利用函数的调用计算阶乘
if (n==1){
return 1;
}
return JC(n-1)*n;
}
public String getFib(String str){
String re = "[f][i][b](\\d+)";
Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(str);
String or="";
int fib=0;
while (m.find()){
or =m.group();
fib = Integer.parseInt(or.substring(3));
}
System.out.println(Fib(fib));
//求值后替换原式
return str.replace(or,String.valueOf(Fib(fib)));
}
public int Fib(int fib){
//递归求斐波那锲
if(fib<=2){
return 1;
}
return Fib(fib-1) + Fib(fib-2);
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
@Override
public void run() {
try {
socket = server.accept();
//接受信息
InputStream is =socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader buufer = new BufferedReader(isr);
setStr(buufer.readLine());
//返回结果
setResult(GetValue(getStr()));
OutputStream os =socket.getOutputStream();
PrintStream ps = new PrintStream(os);
ps.println(getResult());
//返回成功
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭
try {
socket.close();
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
新手,做的不好,有些代码写的比较复杂,见谅!!