简易计算器------Java实现(优先级,连续输入)


本程序包含+、-、*、/的优先级运算,包含等于,清除,删除三种功能。
使用到了基础的栈的知识
完整代码在页面底部,传统手艺复制粘贴(手动狗头)可直接运行。

一.页面布局

使用的WindowBuilder对界面进行布局,简单直接。使用方法:安装WindowBuilder插件,然后在eclipse右键-----Open With-----WindowBuilder Editor-----点击底部Design即可。
没安装WindowBuilder也不影响使用。
所有的按钮都是JButton,输出框是JTextField。

二.栈的设计

分为两个栈,数字栈和符号栈。

    Stack<Double> stack1 = new Stack<Double>();       // 数字栈
    Stack<Character> stack2 = new Stack<Character>(); // 符号栈

数字栈:
从输入串起始位置开始读取,读取连续数字并保存为double型,若此时读取到小数点,则读取小数点后的连续数字直到遇见+、-、*、/,作为之前整数的小数部分并入栈,否则就直接入栈。

temp = inputFormula.charAt(i);     // String 取其某一个元素
if ((temp >= '0' && temp <= '9') || temp == '.'){  //获得各个数字
	double sum = temp - '0';
	int j = i + 1;
	boolean flag = true;     //是否为小数
	int index =  1;         // 记录第几位小数
	while(j < inputFormula.length()){      //获得了这个完整的数但是它可能为负数
		temp = inputFormula.charAt(j);
		if (temp == '.'){   // 如果下一位是小数点
			flag = false;
			index = 1;
			++j;
			continue;
	        }
		else if (flag && (temp >= '0' && temp <= '9')){   // 如果下一位是数字
			sum = sum * 10 + temp - '0';
			++j;
	        }
		else if (!flag && (temp >= '0' && temp <= '9')){  //如果下一位不是数字
			sum += Math.pow(0.1,index) * (temp -  '0');
			index ++;
			++j;
			}
		else break;
	}           //到此时截止,sum为一个正确的实数

符号栈:
当字符栈为空时,运算符直接入栈;当栈外优先级大于等于栈内优先级,入栈;当栈不为空并且栈外优先级低于栈内优先级,将高优先级的运算先计算了,然后入栈。(此处只有+和*运算,因为我将“-”后面的数保存为负数,将/后的数变为倒数,详情见后面)

else if (temp == '+' || temp == '-' || temp == '*' || temp == '/'  ){ // 处理字符
// 当栈中为空时  或者  栈外优先级大于等于栈内优先级,入栈
	if (stack2.empty() || getPriority(temp) >= getPriority(stack2.peek().charValue())) // 有优先级的
	{
		if(temp == '+' || temp == '-')
		{
			stack2.push('+');
		}
		else if(temp == '*' ||temp == '/')
		{
			stack2.push('*');
		}
	}
	else{
// 当栈不为空  并且  栈外优先级低于栈内优先级,将高优先级的运算先计算了,然后入栈。
		while(!stack2.empty() && (getPriority(temp) < getPriority(stack2.peek().charValue()))){
			char c = stack2.peek().charValue();
			stack2.pop();
			double num2 = stack1.peek().doubleValue();
			stack1.pop();
			double num1 = stack1.peek().doubleValue();
			stack1.pop();
			if (c == '+') stack1.push(num1 + num2);
			if (c == '-') stack1.push(num1 + num2);       
			if (c == '*') stack1.push(num1 * num2);
			if (c == '/') stack1.push(num1 * num2);
			}
		stack2.push(temp); // 实际保存进去的运算符未变,变的是需要计算的几个数
		}
	}

三.删除处理

分为归零操作和删除末尾字符的操作。
归零操作直接将文本框的内容设置为0即可

删除末尾字符操作是从尾部删除输入串,符合删除条件时删除尾部,当删的剩第一个数的整数部分时,如果这个数绝对值大于十就可以继续删,绝对值小于十再删将值设置为0。
当字符串内含+、-、*、/、.时说明符合删除条件,可以继续删除。

int returnToZero(String getInput)
{
	if(getInput.contains(".")||getInput.contains("+")||getInput.contains("-")
			||getInput.contains("*")||getInput.contains("/"))
		return 1;
	return 0;
}

点击事件:

btnDelete.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
		inputFormula = textField.getText();
		if(returnToZero(textField.getText()) == 1)  // 可以删的情况(含加减乘除小数点)
		{
			textField.setText(textField.getText().substring(0,inputFormula.length()-1));
		}
		// 此时只剩下整数部分,在范围内则设置为0
		else if(Integer.parseInt(textField.getText()) < 10 && Integer.parseInt(textField.getText()) > -10)
		{
			textField.setText("0");
		}
		else // 如123  -123
		{						
			textField.setText(textField.getText().substring(0,inputFormula.length()-1));
		}
	}
});

四.运算逻辑

加减运算

因为是用栈进行保存数据,遵行后进先出的原则,进行减法运算时,取一个运算符“-”和两个数,若为连续的减法运算,倒数第二个数字被当做正数,故此运算逻辑有误。
直接将“-”后的数字保存为负数,所以运算时使用的只是加法规则且运算逻辑正确。
标记负号

if (inputFormula.charAt(i) == '-' )    // 将后一个数负数保存
{
	if(i == 0)                         // 如果第一位是“-”,则传一个0进去,不然数不够用
		stack1.push(0.0);
	isNegative = 1;
}

存为负数

if (isNegative == 1)            // 当标志为1说明sum是一个负数
{
	sum = sum * -1;
	isNegative = 0;
}

只入栈加号

if(temp == '+' || temp == '-')
{
	stack2.push('+');
}

运算

while(!stack2.empty()){
	char c = stack2.peek().charValue();
	stack2.pop();
	double num2 = stack1.peek().doubleValue();
	stack1.pop();
	double num1 = stack1.peek().doubleValue();
	stack1.pop();
	if (c == '+') stack1.push(num1 + num2);
	if (c == '-') stack1.push(num1 + num2);
	if (c == '*') stack1.push(num1 * num2);
	if (c == '/') stack1.push(num1 * num2);
}  

乘除运算

因为是用栈进行保存数据,遵行后进先出的原则,进行除法运算时,取一个运算符“/”和两个数,若为连续的除法运算,倒数第二个数字被当做被除数,故此运算逻辑有误。
直接将“/”后的数字保存为本身的倒数,所以运算时使用的只是乘法规则且运算逻辑正确。
标记除号-----存为倒数-----只入栈乘号-----运算
代码与加减运算类似,就不上代码了。

五.总结

1.功能的正常使用上完全没有问题,根据用户正确的输入按照运算优先级顺序输出正确结果。
2.用户输入不规范时,由于符号太多,数字栈中的数字出栈完了无法进行运算,所以会报空栈错误,此处有待改进。(如2----3)

六.完整代码

点个赞吧!大哥

package calculator;

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.SwingConstants;
import java.awt.event.ActionListener;
import java.util.Stack;
import java.awt.event.ActionEvent;
public class Calculator {

	//减法运算有问题
	private JFrame frame;
	private static JTextField textField;
	private static int isNegative = 0;              //如果为0则为首字母为负号而不是运算符
	private static String inputFormula ;
	private static boolean isDivision = false;
    Stack<Double> stack1 = new Stack<Double>();       // 数字栈
    Stack<Character> stack2 = new Stack<Character>(); // 符号栈
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Calculator window = new Calculator();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	
	public Calculator() {
		initialize();
	}
	
	private void initialize() {
		frame = new JFrame();
		frame.setTitle("计算器");
		frame.setBounds(100, 100, 345, 342);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // 默认退出模式
		frame.getContentPane().setLayout(null);
		
		textField = new JTextField();                          // 文本框
		textField.setHorizontalAlignment(SwingConstants.RIGHT);
		textField.setFont(new Font("宋体", Font.PLAIN, 27));
		textField.setText("0");
		textField.setBounds(14, 0, 296, 45);
		frame.getContentPane().add(textField);
		textField.setColumns(10);
		
		//为了方便看,将Button的初始化放在一起
		JButton btn7 = new JButton("7");
		btn7.setBounds(14, 62, 45, 47);
		frame.getContentPane().add(btn7);
		JButton btn8 = new JButton("8");
		btn8.setBounds(73, 62, 45, 47);
		frame.getContentPane().add(btn8);
		JButton btn9 = new JButton("9");
		btn9.setBounds(132, 62, 45, 47);
		frame.getContentPane().add(btn9);
		JButton btn4 = new JButton("4");
		btn4.setBounds(14, 122, 45, 47);
		frame.getContentPane().add(btn4);
		JButton btn5 = new JButton("5");
		btn5.setBounds(73, 122, 45, 47);
		frame.getContentPane().add(btn5);
		JButton btn6 = new JButton("6");
		btn6.setBounds(132, 122, 45, 47);
		frame.getContentPane().add(btn6);
		JButton btn1 = new JButton("1");
		btn1.setBounds(14, 182, 45, 47);
		frame.getContentPane().add(btn1);
		JButton btn2 = new JButton("2");
		btn2.setBounds(73, 182, 45, 47);
		frame.getContentPane().add(btn2);
		JButton btn3 = new JButton("3");
		btn3.setBounds(132, 182, 45, 47);
		frame.getContentPane().add(btn3);
		JButton btnpoint = new JButton(".");
		btnpoint.setBounds(14, 240, 45, 47);
		frame.getContentPane().add(btnpoint);
		JButton btn0 = new JButton("0");
		btn0.setBounds(73, 240, 45, 47);
		frame.getContentPane().add(btn0);
		JButton btnc = new JButton("C");
		btnc.setBounds(132, 240, 45, 47);
		frame.getContentPane().add(btnc);
		JButton btndivision = new JButton("/");
		btndivision.setBounds(194, 240, 45, 47);
		frame.getContentPane().add(btndivision);
		JButton btnadd = new JButton("+");
		btnadd.setBounds(194, 62, 45, 47);
		frame.getContentPane().add(btnadd);
		JButton btnminus = new JButton("-");
		btnminus.setBounds(194, 122, 45, 47);
		frame.getContentPane().add(btnminus);
		JButton btnmultiply = new JButton("*");
		btnmultiply.setBounds(194, 182, 45, 47);
		frame.getContentPane().add(btnmultiply);
		JButton btnequals = new JButton("=");
		btnequals.setBounds(253, 182, 57, 105);
		frame.getContentPane().add(btnequals);
		JButton btnDelete = new JButton("<--");
		btnDelete.setBounds(253, 62, 57, 107);
		frame.getContentPane().add(btnDelete);
		
		//以下为各个Button的点击事件
		btn7.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("7");
				else
					textField.setText(textField.getText()+"7");
			}
		});
		btn8.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("8");
				else
					textField.setText(textField.getText()+"8");
			}
		});
		btn9.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("9");
				else
					textField.setText(textField.getText()+"9");
			}
		});
		btn4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("4");
				else
					textField.setText(textField.getText()+"4");
			}
		});
		btn5.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("5");
				else
					textField.setText(textField.getText()+"5");
			}
		});
		btn6.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("6");
				else
					textField.setText(textField.getText()+"6");
			}
		});
		btn1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("1");
				else
					textField.setText(textField.getText()+"1");
			}
		});
		btn2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("2");
				else
					textField.setText(textField.getText()+"2");
			}
		});
		btn3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("3");
				else
					textField.setText(textField.getText()+"3");
			}
		});
		btn0.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("0");
				else
					textField.setText(textField.getText()+"0");
			}
		});
		btnpoint.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("0.");
			}
		});
		btnc.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				textField.setText("0");
				//inputAllOperation = null;     
			}
		});
		btndivision.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("0"); // 
				else 
				{
					textField.setText(textField.getText()+"/");
				}
			}
		});
		btnadd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("0"); // 
				else 
				{
					textField.setText(textField.getText()+"+");
				}
			}
		});
		btnminus.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("-"); // 
				else
					textField.setText(textField.getText()+"-");
			}
		});
		btnmultiply.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(textField.getText().equals("0"))
					textField.setText("0"); // 
				else
					textField.setText(textField.getText()+"*");
			}
		});
		btnDelete.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				inputFormula = textField.getText();
				if(returnToZero(textField.getText()) == 1)  // 可以删的情况(含加减乘除小数点)
				{	
					textField.setText(textField.getText().substring(0,inputFormula.length()-1));
				}
				// 此时只剩下整数部分,在范围内则设置为0
				else if(Integer.parseInt(textField.getText()) < 10 && Integer.parseInt(textField.getText()) > -10)
				{
					textField.setText("0");
				}
				else // 如123  -123
				{
					textField.setText(textField.getText().substring(0,inputFormula.length()-1));
				}
			}
		});
		btnequals.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {                  
				inputFormula = textField.getText();
				char temp;
	            System.out.println(inputFormula);
	            for (int i = 0; i < inputFormula.length(); ++i)      // 遍历所有字符
	            {
	            	if (inputFormula.charAt(i) == '-' )    // 将后一个数负数保存
	            	{
	            		if(i == 0)                         // 如果第一位是“-”,则传一个0进去,不然数不够用
	            			stack1.push(0.0);
	            		isNegative = 1;
	            	}
	            	if(inputFormula.charAt(i) == '/')
	            	{
	            		isDivision = true;
	            	}
	                temp = inputFormula.charAt(i);     // String 取其某一个元素
	                if ((temp >= '0' && temp <= '9') || temp == '.'){  //获得各个数字
	                	double sum = temp - '0';
	                    int j = i + 1;
	                    boolean flag = true;     //是否为小数
	                    int index =  1;         // 记录第几位小数
	                    while(j < inputFormula.length()){      //获得了这个完整的数但是它可能为负数
	                        temp = inputFormula.charAt(j);
	                        if (temp == '.'){   // 如果下一位是小数点
	                            flag = false;
	                            index = 1;
	                            ++j;
	                            continue;
	                        }
	                        else if (flag && (temp >= '0' && temp <= '9')){   // 如果下一位是数字
	                           sum = sum * 10 + temp - '0';
	                            ++j;
	                        }else if (!flag && (temp >= '0' && temp <= '9')){  //如果下一位不是数字
	                            sum += Math.pow(0.1,index) * (temp -  '0');
	                            index ++;
	                            ++j;
	                        }
	                        else break;
	                    }           //到此时截止,sum为一个正确的实数
	                    if (isNegative == 1)            // 当标志为1说明sum是一个负数
	                    {
	                    	sum = sum * -1;
	                    	isNegative = 0;             
	                    }
	                    if (isDivision)                 // 当标志为true将其保存为倒数,用以乘法运算
	                    {
	                    	sum = 1.0 / sum;
	                    	isDivision = false;
	                    }
	                    System.out.println(sum);        // sum代表每一个独立的数字
	                    stack1.push(sum);     // 进栈
	                    i = j - 1;                      // 将标签移到数字之后
	                }
	                else if (temp == '+' || temp == '-' || temp == '*' || temp == '/'  ){ // 处理字符
	                	// 当栈中为空时  或者  栈外优先级大于等于栈内优先级,入栈
	                    if (stack2.empty() || getPriority(temp) >= getPriority(stack2.peek().charValue())) // 有优先级的
	                    {
	                    	if(temp == '+' || temp == '-')
	                    	{
	                    		stack2.push('+');
	                    	}
	                    	else if(temp == '*' ||temp == '/')
	                    	{
	                    		stack2.push('*');
	                    	}
	                    }
	                    else{
	                    	// 当栈不为空  并且  栈外优先级低于栈内优先级,将高优先级的运算先计算了,然后入栈。
	                        while(!stack2.empty() && (getPriority(temp) < getPriority(stack2.peek().charValue()))){
	                        	char c = stack2.peek().charValue();
	    	                    stack2.pop();
	    	                    double num2 = stack1.peek().doubleValue();
	    	                    stack1.pop();
	    	                    double num1 = stack1.peek().doubleValue();
	    	                    stack1.pop();
	    	                    if (c == '+') stack1.push(num1 + num2);
	    	                    if (c == '-') stack1.push(num1 + num2);       
	    	                    if (c == '*') stack1.push(num1 * num2);
	    	                    if (c == '/') stack1.push(num1 * num2);
	                        }
	                        stack2.push(temp); // 实际保存进去的运算符未变,变的是需要计算的几个数
	                    }
	                }
	            }
	            
	            if (!stack2.empty()){     // 符号栈不为空就一直出
	                while(!stack2.empty()){
	                    char c = stack2.peek().charValue();
	                    stack2.pop();
	                    double num2 = stack1.peek().doubleValue();
	                    stack1.pop();
	                    double num1 = stack1.peek().doubleValue();
	                    stack1.pop();
	                    if (c == '+') stack1.push(num1 + num2);
	                    if (c == '-') stack1.push(num1 + num2);
	                    if (c == '*') stack1.push(num1 * num2);
	                    if (c == '/') stack1.push(num1 * num2);
	                }            
	            }
	            textField.setText((stack1.peek().toString()));
	            System.out.println(stack1.peek().doubleValue());
	            stack1.pop();    // 虽然结果出栈了,但它显示在文本框中,仍然会被在此记录,避免栈内有无效数据	 
			}
		});
	}
	
    public int getPriority(char temp)
    {
        if (temp == '+')  return 3;
        if (temp == '-')  return 3;
        if (temp == '*')  return 4;
        if (temp == '/')  return 4;
        return 0;
    }

    // 专门写一个函数看它是否应该设置为0   包含加减乘除小数点时 可以删
    int returnToZero(String getInput)
    {
    	if(getInput.contains(".")||getInput.contains("+")||getInput.contains("-")
    			||getInput.contains("*")||getInput.contains("/"))
    		return 1;
    	return 0;
    }
}


  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值