Java之实现计算器

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();
            }
        }
    }
}

新手,做的不好,有些代码写的比较复杂,见谅!!

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值