实验一:
package 计算器;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.stream.Collectors;
public class Calculator extends JFrame implements ActionListener {
Calculator() {
init();
}
/**
* 定义按钮
*/
private JTextField textField1;
private JTextArea textField2;
private JButton buttonzuo;//(
private JButton buttonyou;//)
private JButton buttonC;//c
private JButton buttonCE;//CE
private JButton buttondele;//<- 删除
private JButton buttonDiv;//÷
private JButton button7;//7
private JButton button8;//8
private JButton button9;//9
private JButton buttonAdd;//+
private JButton button4;//4
private JButton button5;//5
private JButton button6;//6
private JButton buttonSub;//-
private JButton button1;//1
private JButton button2;//2
private JButton button3;//3
private JButton buttonMul;//x
private JButton buttonequl;//=
private JButton button0;//0
private JButton buttonPoint;//.
public void init() {
JFrame frame = new JFrame("The Calculator Of Czf"); //普通窗口顶层容器 创建标题为“计算器”;
frame.setLayout(null); //设置使用特定的布局管理器;
//单选项按钮
//按键的排版以及设计需要提前考虑整体的布局合理性,不可出现按键重叠;为了保证美观又需要考虑排版整齐;
//放置数字0
button0 = new JButton("0"); //注:在给按键命名时要根据按键的大小,否则按键上的标注无法完全显示;
button0.setBounds(100, 400, 110, 50);
frame.add(button0);
//放置数字1
button1 = new JButton("1");
button1.setBounds(40, 340, 50, 50);
frame.add(button1);
//放置数字2
button2 = new JButton("2");
button2.setBounds(100, 340, 50, 50);
frame.add(button2);
//放置数字3
button3 = new JButton("3");
button3.setBounds(160, 340, 50, 50);
frame.add(button3);
//放置数字4
button4 = new JButton("4");
button4.setBounds(40, 280, 50, 50);
frame.add(button4);
//放置数字5
button5 = new JButton("5");
button5.setBounds(100, 280, 50, 50);
frame.add(button5);
//放置数字6
button6 = new JButton("6");
button6.setBounds(160, 280, 50, 50);
frame.add(button6);
//放置数字7
button7 = new JButton("7");
button7.setBounds(40, 220, 50, 50);
frame.add(button7);
//放置数字8
button8 = new JButton("8");
button8.setBounds(100, 220, 50, 50);
frame.add(button8);
//放置数字9
button9 = new JButton("9");
button9.setBounds(160, 220, 50, 50);
frame.add(button9);
//放置 .
buttonPoint = new JButton("."); //text:为自动生成的参数的解释词
buttonPoint.setBounds(40, 400, 50, 50); //自动补齐的参数解释词
frame.add(buttonPoint);
//放置 +
buttonAdd = new JButton("+");
buttonAdd.setBounds(220, 400, 50, 50);
frame.add(buttonAdd);
//放置 -
buttonSub = new JButton("-");
buttonSub.setBounds(220, 340, 50, 50);
frame.add(buttonSub);
//放置 *
buttonMul = new JButton("*");
buttonMul.setBounds(220, 280, 50, 50);
frame.add(buttonMul);
//放置 /
buttonDiv = new JButton("/");
buttonDiv.setBounds(220, 220, 50, 50);
frame.add(buttonDiv);
//放置 =
buttonequl = new JButton("=");
buttonequl.setBounds(280, 340, 110, 110);
frame.add(buttonequl);
//退位键
buttondele = new JButton("B");
buttondele.setBounds(280, 220, 110, 110);
frame.add(buttondele);
//放置左括号(
buttonzuo = new JButton("(");
buttonzuo.setBounds(40, 160, 80, 50);
frame.add(buttonzuo);
//放置右括号)
buttonyou = new JButton(")");
buttonyou.setBounds(130, 160, 80, 50);
frame.add(buttonyou);
//放置C 消除所有输入
buttonC = new JButton("C");
buttonC.setBounds(220, 160, 80, 50);
frame.add(buttonC);
//放置CE 消除当前输入
buttonCE = new JButton("CE");
buttonCE.setBounds(310, 160, 80, 50);
frame.add(buttonCE);
//添加表达式文本框 用以输入计算公式
textField1 = new JTextField(); //文本框
textField1.setBounds(40, 20, 350, 60);
frame.add(textField1);
textField2 = new JTextArea();
textField2.setBounds(400, 20, 280, 430);
frame.add(textField2);
textField1.addActionListener(this);
buttonzuo.addActionListener(this);
buttonyou.addActionListener(this);
buttonC.addActionListener(this);
buttonCE.addActionListener(this);
buttondele.addActionListener(this);
buttonDiv.addActionListener(this);
button7.addActionListener(this);
button8.addActionListener(this);
button9.addActionListener(this);
buttonAdd.addActionListener(this);
button4.addActionListener(this);
button5.addActionListener(this);
button6.addActionListener(this);
buttonSub.addActionListener(this);
button1.addActionListener(this);
button2.addActionListener(this);
button3.addActionListener(this);
buttonMul.addActionListener(this);
buttonequl.addActionListener(this);
button0.addActionListener(this);
buttonPoint.addActionListener(this);
frame.setBounds(0, 0, 700, 520); //设置整个图形窗口的大小;(通过窗口名调用)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE),当点击窗口的关闭按钮时退出程序(没有这一句,程序不会退出)
frame.setVisible(true);
}
String str = null;
int pointbook = 0;
int equalbook = 0;
int zuonum = 0;
int younum = 0;
int equnum = 0;
public void actionPerformed(ActionEvent e) {
if (equnum == 1) {
textField1.setText("0");
equnum = 0;
}
//按0
if (e.getSource().equals(button0)) {
str = textField1.getText();
if (str.length() > 16 || str.equals("0") || equalbook == 1) {
} else {
textField1.setText(str + "0");
}
}
//按1
if (e.getSource().equals(button1)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("1");
} else {
textField1.setText(str + "1");
}
}
//当按钮为2时
if (e.getSource().equals(button2)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("2");
} else {
textField1.setText(str + "2");
}
}
//当按钮为3时
if (e.getSource().equals(button3)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("3");
} else {
textField1.setText(str + "3");
}
}
//当按钮为4时
if (e.getSource().equals(button4)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("4");
} else {
textField1.setText(str + "4");
}
}
//当按钮为5时
if (e.getSource().equals(button5)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("5");
} else {
textField1.setText(str + "5");
}
}
//当按钮为6时
if (e.getSource().equals(button6)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("6");
} else {
textField1.setText(str + "6");
}
}
//当按钮为7时
if (e.getSource().equals(button7)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("7");
} else {
textField1.setText(str + "7");
}
}
//当按钮为8时
if (e.getSource().equals(button8)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("8");
} else {
textField1.setText(str + "8");
}
}
//当按钮为9时
if (e.getSource().equals(button9)) {
str = textField1.getText();
if (str.length() > 16 || equalbook == 1) {
} else if (str.equals("0") || str.equals("")) {
textField1.setText("9");
} else {
textField1.setText(str + "9");
}
}
//当按钮为小数点时
if (e.getSource().equals(buttonPoint)) {
str = textField1.getText();
if (str.length() > 15 || equalbook == 1) { //小数点位于操作数的最后一位不执行操作;
}
if (pointbook == 0) { //一个操作数仅能有一个小数点,若已经有小数点则不再添加小数点;
textField1.setText(str + ".");
pointbook = 1; //小数点判断位置1;
}
}
//每次输入都是一个数字+运算符,一起从数字文本框转而输入到表达式文本框中;
//当按钮为加号时
if (e.getSource().equals(buttonAdd)) {
str = textField1.getText(); //获取运算符前一个操作数;
char ch1[] = str.toCharArray(); //把第一操作数连同+号 进行字符串转字符数组的操作 赋予ch1;
int length1 = str.length() - 1; //length1获取除+号外的第一操作数的位数;
if ((length1 == -1 || ch1[length1] != ')') && (str.equals("0") || str.equals("") || ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {
//当数字为空或为0(操作无意义);或数字的最后一位是小数点(未输入完毕或输入出错,等待)
} else {
textField1.setText(str + "+"); //合并现有表达式和新增表达式
// 这里解释以下为什么s没有提取到数字框里的符号,因为输入符号时并没有更新数字框,而是直接执行一系列操作,数字框从未出现过运算符;
}
pointbook = 0;
}
//当按钮为减号时
if (e.getSource().equals(buttonSub)) {
str = textField1.getText();
char ch1[] = str.toCharArray();
int length1 = str.length() - 1;
if ((length1 == -1 || ch1[length1] != ')') && (str.equals("0") || str.equals("") || ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {
} else {
textField1.setText(str + "-");
}
pointbook = 0;
}
//当按钮为乘号时
if (e.getSource().equals(buttonMul)) {
str = textField1.getText();
char ch1[] = str.toCharArray();
int length1 = str.length() - 1;
if ((length1 == -1 || ch1[length1] != ')') && (str.equals("0") || str.equals("") || ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {
} else {
textField1.setText(str + "*");
}
pointbook = 0;
}
//当按钮为除号时
if (e.getSource().equals(buttonDiv)) {
str = textField1.getText();
char ch1[] = str.toCharArray();
int length1 = str.length() - 1;
if ((length1 == -1 || ch1[length1] != ')') && (str.equals("0") || str.equals("") || ch1[length1] == '.' || ch1[length1] == '+' || ch1[length1] == '-' || ch1[length1] == '*' || ch1[length1] == '/' || ch1[length1] == '(' || ch1[length1] == ')')) {
} else {
textField1.setText(str + "/");
}
pointbook = 0;
}
//当按钮为左括号时
if (e.getSource().equals(buttonzuo)) {
str = textField1.getText();
char ch[] = str.toCharArray();
int length = str.length() - 1;
if (length == -1 || ch[length] == '+' || ch[length] == '-' || ch[length] == '*' || ch[length] == '/') {
//括号左边是否有数或符号类别的判断;
textField1.setText(str + '('); //满足条件则加入左括号;
zuonum++; //左括号数加一标记;
}
if (length == -1 || ch[length] == '+' || ch[length] == '-' || ch[length] == '*' || ch[length] == '/')
pointbook = 0;
if (length == 0 || ch[length] == 0) {
textField1.setText("(");
zuonum++;
}
}
//当按钮为右括号时;
if (e.getSource().equals(buttonyou)) {
str = textField1.getText();
char ch[] = str.toCharArray();
int length = str.length() - 1;
if (Character.isDigit(ch[length]) && zuonum > younum) { //只有前面是数字的时候且左括号的数量大于右括号的数量的时候才能加右括号;
younum++; //右括号数加一标记;
textField1.setText(str + ')');
}
pointbook = 0;
}
//当按下C键时;
if (e.getSource().equals(buttonC)) {
textField1.setText("0"); //置当前数字框为0;
zuonum = 0; //当一次计算完成之后,只有按CE按钮才能进行新的计算,因为要清除所有标志位否则会影响下一次操作;
younum = 0;
pointbook = 0;
equalbook = 0;
textField2.setText(" ");
}
//当按钮为CE时,
if (e.getSource().equals(buttonCE)) {
textField1.setText("0"); //清除当前数字框中内容;
pointbook = 0; //更新小数点状态为0;
}
//当按下B时,
if (e.getSource().equals(buttondele)) {
str = textField1.getText();
char []nums=str.toCharArray();
if (nums[str.length()-1]=='('){
zuonum--;
}
str = str.substring(0, str.length() - 1);
textField1.setText(str);
}
//当按下=时,
if (e.getSource().equals(buttonequl)) {
str = textField1.getText();
if (zuonum != younum) {
textField1.setText("关系式错误。");
} else {
ans(str);
}
String s = str + "=" + textField1.getText();
textField2.setText(s + "\r\n" + textField2.getText()); //将表达式存放在历史记录里。
equnum = 1;
}
}
/**
* 提前将 符号的优先级定义好
*/
private static final Map<Character, Integer> basic = new HashMap<Character, Integer>();
static {
basic.put('-', 1);
basic.put('+', 1);
basic.put('*', 2);
basic.put('/', 2);
basic.put('(', 0);//在运算中 ()的优先级最高,但是此处因程序中需要 故设置为0
}
public void ans(String str) {
String a = toSuffix(str);//传入 一串 算数公式
textField1.setText(dealEquation(a));
}
/**
* 将 中缀表达式 转化为 后缀表达式
*/
public String toSuffix(String infix) {
List<String> queue = new ArrayList<String>(); //定义队列 用于存储 数字 以及最后的 后缀表达式
List<Character> stack = new ArrayList<Character>(); //定义栈 用于存储 运算符 最后stack中会被 弹空
char[] charArr = infix.trim().toCharArray(); //字符数组 用于拆分数字或符号
String standard = "*/+-()"; //判定标准 将表达式中会出现的运算符写出来
char ch = '&'; //在循环中用来保存 字符数组的当前循环变量的 这里仅仅是初始化一个值 没有意义
int len = 0; //用于记录字符长度 【例如100*2,则记录的len为3 到时候截取字符串的前三位就是数字】
for (int i = 0; i < charArr.length; i++) { //开始迭代
ch = charArr[i]; //保存当前迭代变量
if (Character.isDigit(ch)) { //如果当前变量为 数字
len++;
} else if (Character.isLetter(ch)) { //如果当前变量为 字母
len++;
} else if (ch == '.') { //如果当前变量为 . 会出现在小数里面
len++;
} else if (Character.isSpaceChar(ch)) { //如果当前变量为 空格 支持表达式中有空格出现
if (len > 0) { //若为空格 代表 一段结束 ,就可以往队列中 存入了 【例如100 * 2 100后面有空格 就可以将空格之前的存入队列了】
queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); //往 队列存入 截取的 字符串
len = 0;