实验内容:
- 学习GUI图形界面的设计,Python Tinker或 Java Swing/Awt 或C++ QT框架,创建交互友好的应用程序;
- 能通过界面按钮控件输入并实现算术表达式,输入的表达式即时在控件中显示,按下“=”按钮能实现运算,并将运算结果输出在控件中显示;要求能保存和浏览历史表达式的运算记录。
- 算术表达式求解,是指算术表达式中包括加、减、乘、除、括号等运算符,能求解包含括号的四则混合运算;并且能够检验表达式的合法性。
中缀表达式转换为后缀表达式:
①遇到‘)’,将操作符栈内运算符弹出,直到‘(’
②当中缀表达式扫描结束,判断操作符栈是否为空,未空则,将操作符栈内运算符全部弹出
①后缀表达式队列:postQueue,用于存储逆波兰表达式(其实不用队列排序直接输出也行) ②操作符栈:opStack,对用户输入的操作符进行处理,用于存储运算符
算法思想:从左向右依次读取算术表达式的元素X,分以下情况进行不同的处理: (1)如果X是操作数,直接入队 (2)如果X是运算符,再分以下情况: a)如果栈为空,直接入栈。 b)如果X==”(“,直接入栈。 c)如果X==”)“,则将栈里的元素逐个出栈,并入队到后缀表达式队列中,直到第一个配对的”(”出栈。(注:“(”和“)”都不 入队) d)如果是其他操作符(+ - * /),则和栈顶元素进行比较优先级。 如果栈顶元素的优先级大于等于X,则出栈并把栈中弹出的元素入队,直到栈顶元素的优先级小于X或者栈为空。弹出完这些元素后,才将遇到的操作符压入到栈中。 (3)最后将栈中剩余的操作符全部入队。
后缀表达式值的计算:使用一个栈opStack来进行值的计算。 从左向右扫描后缀表达式,遇到操作数压入opStack栈,遇到运算符,将栈顶的2个元素出栈计算,再将结果压入opStack栈;直到结束,将栈中唯一的元素出栈。
后缀表达式求解 需要用到一个结果栈opStack :用于存放计算的中间过程的值和最终结果
算法思想:首先准备一个栈opStack. 1、从左开始向右遍历后缀表达式的元素。 2、如果取到的元素是操作数,直接入栈opStack,如果是运算符,从栈中弹出2个数进行运算,然后把运算结果入栈 3、当遍历完后缀表达式时,计算结果就保存在栈里了。
整个面板用了BorderLayout布局,分为北,左和中。中部采用网格布局。定义这个类为Carculator。
实验代码:
package start; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Objects; public class Carculator extends JFrame implements ActionListener { private JPanel jp_north = new JPanel(); private JTextField input_text = new JTextField(); private JButton c_Btn = new JButton("c"); private static String b = ""; private JPanel jp_center = new JPanel(); private JTextField History = new JTextField();// 历史记录文本框初始值设为空 public Carculator() throws HeadlessException { this.a(); this.addNorthComponent(); this.addCenterButton(); } public void a() { this.setTitle("计算器"); this.setSize(300, 300); this.setLayout(new BorderLayout()); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void addNorthComponent() { this.input_text.setPreferredSize(new Dimension(200, 30)); jp_north.add(input_text); jp_north.add(c_Btn); this.add(jp_north, BorderLayout.NORTH); c_Btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { input_text.setText(" "); b=" "; } }); } public void addCenterButton() { String btn_text = "1234567890+-*/.=()"; this.jp_center.setLayout(new GridLayout(6, 3)); for (int i = 0; i <= 17; i++) { String temp = btn_text.substring(i, i + 1); JButton btn = new JButton(); btn.setText(temp); btn.addActionListener(this); jp_center.add(btn); } this.add(jp_center, BorderLayout.CENTER); this.setResizable(false); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { String label = e.getActionCommand();// 获得事件源的标签 if(".0123456789+-*/=()".indexOf(label)!=-1) { this.input_text.setText(input_text.getText() +label); } if (Objects.equals(label,"=")) { String s[] = houzhui(this.b); String result = Result(s); this.b = result + ""; input_text.setText(this.b); History.setText(History.getText()+"="+input_text.getText()+"\n"); } else if(Objects.equals(label, "c"))// 清空按钮,消除显示屏文本框前面所有的输入和结果 { this.b = ""; input_text.setText("");// 更新文本域的显示,显示初始值; } else { this.b=this.b+label; input_text.setText(this.b); // History.setText(History.getText()+this.b); } } private String[] houzhui(String str) { String s = "";// 用于承接多位数的字符串 char opStack[] = new char[100];// 静态栈,对用户输入的操作符进行处理,用于存储运算符 String postQueue[] = new String[100];// 后缀表达式字符串数组,为了将多位数存储为独立的字符串 int top = -1, j = 0;// 静态指针top,控制变量j for (int i = 0; i < str.length(); i++)// 遍历中缀表达式 // indexof函数,返回字串首次出现的位置;charAt函数返回index位置处的字符; { if ("0123456789.".indexOf(str.charAt(i)) >= 0) // 遇到数字字符的情况 { s = "";// 作为承接字符,每次开始时都要清空 for (; i < str.length() && "0123456789.".indexOf(str.charAt(i)) >= 0; i++) { s = s + str.charAt(i); } i--; postQueue[j] = s;// 数字字符直接加入后缀表达式 j++; } else if ("(".indexOf(str.charAt(i)) >= 0) {// 遇到左括号 top++; opStack[top] = str.charAt(i);// 左括号入栈 } else if (")".indexOf(str.charAt(i)) >= 0) {// 遇到右括号 for (; ; )// 栈顶元素循环出栈,直到遇到左括号为止 { if (opStack[top] != '(') {// 栈顶元素不是左括号 postQueue[j] = opStack[top] + "";// 栈顶元素出栈 j++; top--; } else { // 找到栈顶元素是左括号 top--;// 删除栈顶左括号 break;// 循环结束 } } } if ("*%/".indexOf(str.charAt(i)) >= 0)// 遇到高优先级运算符 { if (top == -1) {// 若栈为空则直接入栈 top++; opStack[top] = str.charAt(i); } else {// 栈不为空,把栈中弹出的元素入队,直到栈顶元素优先级小于x或者栈为空 if ("*%/".indexOf(opStack[top]) >= 0) { // 栈顶元素也为高优先级运算符 postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后缀表达式 j++; opStack[top] = str.charAt(i);// 当前运算符入栈 } else if ("(".indexOf(opStack[top]) >= 0) {// 栈顶元素为左括号,当前运算符入栈 top++; opStack[top] = str.charAt(i); } else if ("+-".indexOf(str.charAt(i)) >= 0) {// 遇到低优先级运算符 postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后缀表达式 j++; opStack[top] = str.charAt(i);// 当前元素入栈 } } } else if ("+-".indexOf(str.charAt(i)) >= 0) { if (top == -1) { top++; opStack[top] = str.charAt(i); } else { if ("*%/".indexOf(opStack[top]) >= 0) { // 栈顶元素也为高优先级运算符 postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后缀表达式 j++; opStack[top] = str.charAt(i);// 当前运算符入栈 } else if ("(".indexOf(opStack[top]) >= 0) {// 栈顶元素为左括号,当前运算符入栈 top++; opStack[top] = str.charAt(i); } else if ("+-".indexOf(str.charAt(i)) >= 0) {// 遇到低优先级运算符 postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后最表达式 j++; opStack[top] = str.charAt(i);// 当前元素入栈 } } } } for (; top != -1; ) {// 遍历结束后将栈中剩余元素依次出栈进入后缀表达式 postQueue[j] = opStack[top] + ""; j++; top--; } return postQueue; } public String Result(String str[]) { String Result[] = new String[100];// 顺序存储的栈,数据类型为字符串 int Top = -1;// 静态指针Top for (int i = 0; str[i] != null; i++) { if ("+-*%/".indexOf(str[i]) < 0) { Top++; Result[Top] = str[i]; } if ("+-*%/".indexOf(str[i]) >= 0)// 遇到运算符字符,将栈顶两个元素出栈计算并将结果返回栈顶 { double x, y, n; x = Double.parseDouble(Result[Top]);// 顺序出栈两个数字字符串,并转换为double类型 Top--; y = Double.parseDouble(Result[Top]); Top--; if ("*".indexOf(str[i]) >= 0) { n = y * x; Top++; Result[Top] = String.valueOf(n);// 将运算结果重新入栈 } if ("/".indexOf(str[i]) >= 0) { if (x == 0)// 被除数不允许为0 { String s = "error!"; return s; } else { n = y / x; Top++; Result[Top] = String.valueOf(n);// 将运算结果重新入栈 } } if ("%".indexOf(str[i]) >= 0) { if (x == 0)// 被除数不允许为0 { String s = "error!"; return s; } else { n = y % x; Top++; Result[Top] = String.valueOf(n);// 将运算结果重新入栈 } } if ("-".indexOf(str[i]) >= 0) { n = y - x; Top++; Result[Top] = String.valueOf(n);// 将运算结果重新入栈 } if ("+".indexOf(str[i]) >= 0) { n = y + x; Top++; Result[Top] = String.valueOf(n);// 将运算结果重新入栈 } } } return Result[Top];// 返回最终结果 } public static void main(String[] args) { Carculator carculator = new Carculator(); } }
文章评论