Java实现简单计算器1.0版

       近半个月的时间学习了Java的一些基础语法。为了巩固近段的学习以及增强记忆,手写一个简单的GUI计算器小程序。搜索了一下网上的一些计算器小程序,大部分缺少括号运算、小数点运算、有些仅仅实现了一位数字运算。所以写了一个1.0版的小计算器。话不多说,先上图:

    先说一下用到的一些主要的Java基础吧:GUI、事件监听、容器、异常抛出等等吧。

主要的思路:该计算器的实现过程主要是字符串的处理,其中计算过程用了前缀表达式转为后缀表达式,最后再将后缀表达式计算输出结果。

一、GUI界面的设计

        界面的设计首先新建一个CalFrame类继承了Frame父类,在Frame中使用了BorderLayout自动布局,又新建了一个TField和一个Panel,Panel中放置了20个Button分别表示数字键,运算符号键等等。其中一些特别的按键做了颜色区别,给每个按键添加事件监听。这是这一部分的设计,这一部分中没有遇到什么大的问题,主要就是页面的调整。其中添加按键时用了一个字符串数组里面存入了每一个按键的名字,一个for循环添加所有的按键,比较方便。

class CalFrame extends Frame {
	Panel p1 = new Panel();
	String StartString = "请输入...";
	TextField TField = new TextField(StartString);
	String input = "";
	boolean RestFlag = false ;
	CalFrame() {
		super("My first Calculator By Java");
		setBackground(new Color(204,204,255));
		setLayout(new BorderLayout());//
		setBounds(200,200,400,400);
		Panel1Set();
		TField.setFont(new Font("宋体",Font.PLAIN,20));
		add(TField,BorderLayout.NORTH);
		add(p1,BorderLayout.CENTER);
		//pack();
		
		this.addWindowListener( new WindowAdapter() {		//监听Windows
			public void windowClosing(WindowEvent e) {
					setVisible(false);
					System.exit(0);
				}
			}
		);
		
		setVisible(true);
	}
	
	void Panel1Set() {
		p1.setBackground(new Color(204,204,255));
		p1.setLayout(new GridLayout(4, 5,5,5));//
		Button[] button = new Button[20];
		String[] buName = {"7","8","9","+","Rest","4","5","6","-","C","1","2","3","*","(","0",".","=","/",")"} ;
		ButtonActionMonitor BAM = new ButtonActionMonitor();
		for(int i = 0;i<20;i++)
		{
			button[i] = new Button(buName[i]);
			button[i].setBackground(new Color(192,192,192));  //设置按键的背景色
			button[i].setFont(new Font("宋体",Font.PLAIN,20));
			if ((i+1) % 5 == 4)
      	button[i].setForeground(Color.BLUE);
			button[i].addActionListener(BAM);	//添加监听器
			p1.add(button[i]);
		}
		button[17].setForeground(Color.RED);
		
		p1.setVisible(true);
	}
二、按键监听器类的实现

        按键监听类新建在了CalFrame主类的内部,可以方便的调用主类中的成员变量。监听到即可更改其TFiled的显示。这里用了一个input的字符串,每当监听到某个按键的按下除了等号和Rest复位键,就把对应按键的名字添加到input字符串中去,如果遇到等号按键按下,则处理此时字符串,遇到C键则清楚input中的一个字符,遇到Rest,则复位字符串。下面是该类的代码:

class ButtonActionMonitor implements ActionListener {
		public void actionPerformed (ActionEvent e) {	
			String tmpStr = e.getActionCommand();
			System.out.println("a button has been pressed  " + tmpStr);
			if (tmpStr == "=") {
				RestFlag = true ;
				Compute(input);
			} else if (tmpStr == "Rest") {
				input = StartString;
				RestFlag = true ;
			} else if (tmpStr == "C") {	//退格
				input = input.substring(0,input.length() - 1);
			}else {
				if (RestFlag == true) {
					input = "";RestFlag = false;	//按过等号键后复位操作
				}
				input += tmpStr;
			}
			TField.setText(input);
		}
	}
三、输入字符串的处理

        这一部分也是核心代码了,编写过程中也遇到了许多问题。一开始是直接利用输入字符串转为字符数组,然后再进行后缀转前缀等处理,这样就不能实现多位数字以及包含小数点的数字进行运算了。所以后面改为利用一个ArrayList<String> 进行分割处理。分割过程中新建了一个Queue,遇到数字和小数点就先进队列,遇到运算符号或者括号后再将队列中内容输出为一个String,并将该字符串也输出为一个字符串。这样就完成了数字和运算符的分割处理。

	ArrayList<String> DataHandle(String input) {
		ArrayList<String> c = new ArrayList<String>();
		Queue<Character> queue = new LinkedList<Character>();
		String numStr = "";
		for(int i=0; i<input.length(); i++) {
			char tmp = input.charAt(i);
			if(Character.isDigit(tmp) || tmp == '.') {
				queue.offer(tmp);
			} else {
				while(queue.size() > 0) {
					numStr += queue.poll();
				}
				if(numStr.length()>0)
					c.add(numStr);
				c.add(String.valueOf(tmp));
				numStr = "";
			}
		}
		while(queue.size() > 0) {		//清空队列
			numStr += queue.poll();
		}
		if(numStr.length()>0)
			c.add(numStr);
		numStr = "";
		
		return c;
	}

四、前缀转后缀,以及后缀转为数字运算的处理

        这一部分主要参考了大话数据结构一书中的处理办法,网上也有很多讲解,具体不在赘述。其中遇到的一个问题是,对于一个字符串进行switch操作时可以直接匹配字符串,但是在其他匹配中不能使用某个String对象 == “ 需要匹配的字符串”,这种操作是不对的。因为这么操作是匹配的字符串的引用,实际上是两个地址在比较。此处必须使用equals()方法。至于为什么使用Switch语句可以直接匹配,我也不知道为什么。下面直接赋值代码

ArrayList<String> infixToSuffix(ArrayList<String> infix) {
		Stack<String> s = new Stack<String>();
		ArrayList<String> suffix = new ArrayList<String> ();
		
		for(int i = 0;i < infix.size(); i++) {
			String tmp = infix.get(i);
			String c = "";
			switch (tmp) {
				case " ":
					break;
				case "(":
					s.push(tmp);	break;
				case "+":
				case "-":
					while(s.size() != 0) {
						c = s.pop();
						if(c.equals("(")) {
							s.push("("); break;
						}
						
						suffix.add(c) ;
					}
					s.push(tmp);
					break;	
				case "*":
				case "/":
					while(s.size() != 0) {
						c = s.pop();
						if(c.equals("+") || c.equals("-") || c.equals("(")) {
							s.push(c); 
							break;
						} else {
							suffix.add(c) ;
						}
					}
					s.push(tmp);
					break;
				case ")":
					while(!s.isEmpty()) {
						c = s.pop();
						if(c.equals("(")) {
							break;
						} else {
							suffix.add(c) ;
						}
					}
					break;
				default:
					suffix.add(tmp);
					break;
			}
		}
		while(s.size() != 0) {
			suffix.add(s.pop());
		}		
		return suffix;
	}
	
	Double suffixToNum (ArrayList<String> suffix) {
		Stack<Double> stack = new Stack<Double>();
		 // 使用正则表达式匹配数字
		Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)");
		
		for(int i = 0; i < suffix.size(); i++) {
			 if (suffix.get(i).equals("")) {
       		continue;
       }
       if (pattern.matcher(suffix.get(i)).matches()) {
          stack.push(Double.parseDouble(suffix.get(i)));		//匹配数字
       }
            // 如果是运算符,则弹出栈顶的两个数进行计算
       else {
          double y = stack.pop();
          double x = stack.pop();
          stack.push(calculate(x, y, suffix.get(i))); // 将运算结果重新压栈
       }
		}
		return stack.pop();
	}
	
	Double calculate(double x, double y, String string) {
		if(string.trim().equals("+")) {
			return x + y;
		}
		if(string.trim().equals("-")) {
			return x - y;
		}
		if(string.trim().equals("*")) {
			return x * y;
		}
		if(string.trim().equals("/")) {
			return x / y;
		}
		return (double) 0;
	}
五、最后的异常处理

        因为可能产生不是一个正确的运算表达式就按下等号进行后续运算。此处就会抛出Exception,这里直接catch到进行了一个请输入合法表达式的提示。

	void Compute(String Input) {
		Double result = 0.0;
		try {
			result = suffixToNum(infixToSuffix(DataHandle(Input)));
			input = result.toString();
		}catch (Exception e) {
			input = "请输入合法的表达式!";
			return ;
		}
		
		System.out.println(result);
	}
	
        第一次尝试写一个Java小程序。不足之处,多多指教。后续进行学习的过程中,有时间再对该计算器进行改进,可以实现科学计算器、程序员计算器的一些额外功能。后面又尝试着将代码打包成exe文件,然而在没有JVM的电脑环境上还是不能运行,暂时不知道怎么解决。最后放上代码完整版 https://github.com/lxycomeon/Calculator1.0.git


        

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值