本课程设计有源文档,仅供各位参考,功能不完善
一、设计题目
2、计算器,相关功能要求如下:
主体要求:编写一个计算器软件, 程序设计要求为:
(1)采用交互工作方式,功能菜单下至少2项功能菜单(输入多项式、退出)并可进行连续操作,直至选择退出(可丰富功能);
(2)在选择输入多项式后,输入多项式,通过栈等数据结构实现至少+-*/()等基本计算器的相关运算操作,回车代表输入结束并计算打印多项式运算结果。
二、设计目的
本次课程设计的主要目的是综合运用所学的数据结构与算法相关知识解决一个比较实际问题,侧重对链表、数组、字符串、图、树等相关内容的综合应用,使同学们能进一步熟悉掌握数据结构的基础知识,进一步提升自己的解决问题和编程调试能力,为后续专业课程的学习打下良好的基础。
三、设计要求
1. 学生独立完成课程设计的主要内容的软件设计与开发;
2. 按照实验课表安排进行,不得无故旷课;
3.按照选题规则确定课程设计题目,不可随意更换,但可在完成规定的任务之后,根据个人兴趣选做其它题目;
4.严格按照报告格式撰写课程设计报告;
5.程序实现方式可以自选,但至少必须符合题目中的相关要求。
四、实现思路
程序运行环境:JDK8, Windows10 Ho
(1)主要功能
设计与开发一个具有交互式功能的计算器,能够进行简单的加减乘除、小数点和括号的基本运算。计算器可进行按钮输入表达式也可进行键盘输入。
(2)知识点涉及
计算机的设计主要涉及中序表达式转成后序表达式的过程,期间采用两个自定义的栈进行实现计算器整体功能,辅助需要用到Java GUI图形工具来做可交互式的图形界面。
五、实验截图
六、实现过程
package Passage1;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
/**
*
* 此计算器可用于带小数点以及括号的多位数四则运算(暂不支持开方以及多种函数的计算) 同时支持判断括号输入是否正确,判断分母是否为0
*
*/
class Stack1 { // 为了防止进栈出栈时各种类型转换出错,特定义两个栈
ArrayList<Double> list = new ArrayList<>(); // 此为存储中间数据以及最终结果的栈
public void push(Double o) {
list.add(o);
}
public int prior(char a) {
if (a == '*' || a == '/')
return 4;
else if (a == '+' || a == '-')
return 3;
else if (a == '(')
return 2;
else if (a == '#')
return 1;
else
return 0;
}
//获取栈顶元素
public Double getTop() {
Double o = list.get(list.size() - 1);
return o;
}
public Double pop() {
Double o = list.get(list.size() - 1);
list.remove(o);
return o;
}
public void output() {
System.out.println(list);
}
}
class Stack2 { // 存储运算符的栈
ArrayList<Character> list = new ArrayList<>();
public void push(Character o) {
list.add(o);
}
//获取栈顶元素
public Character getTop() {
Character o = list.get(list.size() - 1);
return o;
}
//判断是否为空
public boolean isEmpty() {
if (list.isEmpty()) {
return true;
} else {
return false;
}
}
//取出元素
public Character pop() {
Character o = list.get(list.size() - 1);
list.remove(o);
return o;
}
public void output() {
System.out.println(list);
}
}
//设置监听器及计算器的可视的界面
class CalculatorClass implements ActionListener {
JFrame f;
JPanel panel1, panel2, panel3, panel4, panel5, panel6, panel7;
JTextArea area;;
String[] a = { "MC", "7", "8", "9", "/", "sqrt", "(", "4", "5", "6", "*", "%", ")", "1", "2", "3", "-", "1/x", "0",
"+/-", "M+", ".", "+", "=" };
String[] b = { "BackSpace", "CE", "C" };
JButton[] Button1, Button2, Button3;
CalculatorClass() throws IOException { // 设置计算器的外观以及内容
f = new JFrame("计算器");
f.setLayout(new BorderLayout(0, 5));
panel1 = new JPanel(new BorderLayout(0, 5));
panel1.isBackgroundSet();
panel1.setBackground(Color.LIGHT_GRAY);
panel2 = new JPanel(new GridLayout(4, 6, 10, 10));
panel3 = new JPanel(new BorderLayout());
panel4 = new JPanel(new BorderLayout(0, 5));
panel5 = new JPanel();
panel5.setLayout(new FlowLayout(FlowLayout.LEFT));
panel5.setSize(300, 20);
panel6 = new JPanel();
panel6.setBorder(BorderFactory.createRaisedBevelBorder());
panel6.setBackground(Color.LIGHT_GRAY);
panel7 = new JPanel(new GridLayout(1, 3, 7, 20));
panel3.add(BorderLayout.WEST, panel6);
panel3.add(BorderLayout.CENTER, panel7);
panel3.setLayout(new FlowLayout(FlowLayout.CENTER));
f.setSize(400, 400);
f.add(BorderLayout.CENTER, panel1);
area = new JTextArea(2, 1);
area.setLineWrap(true);
panel4.add(BorderLayout.CENTER, area);
// 标签
JMenuBar bar = new JMenuBar();
f.setJMenuBar(bar);
JMenu help = new JMenu("帮助");
bar.add(help);
JMenuItem about1 = new JMenuItem("关于");
help.add(about1);
about1.addActionListener(new Myabout());
f.add(bar, BorderLayout.NORTH);
panel4.add(BorderLayout.NORTH, panel5);
f.add(BorderLayout.NORTH, panel4);
panel1.add(BorderLayout.CENTER, panel2);
panel1.add(BorderLayout.NORTH, panel3);
Font font = new Font("宋体", Font.BOLD, 20);
Button1 = new JButton[a.length];
Button2 = new JButton[b.length];
for (int i = 0; i < a.length; i++) {
Button1[i] = new JButton(a[i]);
Button1[i].setMargin(new Insets(0, 0, 0, 0));
Button1[i].setBackground(Color.lightGray);
if (i == 0 || i == 4 || i == 6 || i == 10 || i == 12 || i == 16 || i == 18 || i == 22 || i == 23) {
Button1[i].setForeground(Color.RED);
} else {
Button1[i].setForeground(Color.BLUE);
}
Button1[i].setFont(font);
Button1[i].addActionListener(this);
panel2.add(Button1[i]);
}
panel2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
for (int i = 0; i < b.length; i++) {
Button2[i] = new JButton(b[i]);
Button2[i].setMargin(new Insets(0, 0, 0, 0));
Button2[i].setBackground(Color.lightGray);
Button2[i].setForeground(Color.red);
Button2[i].setSize(250, 100);
Button2[i].setFont(font);
Button2[i].addActionListener(this);
panel7.add(Button2[i]);
}
f.setVisible(true);
}
boolean match(char str[]) // 括号匹配函数
{
Stack2 s = new Stack2();
int k, flag = 1;
Character ch, e;
for (k = 0; k < str.length && (flag == 1); k++) {
if (str[k] != '(' && str[k] != ')') {
continue; // 碰到不是括号的字符,继续向下读
}
switch (str[k]) {
case '(':
ch = str[k];
s.push(ch);
break; // 遇到左括号进栈
case ')':
if (!s.isEmpty()) {
e = s.getTop(); // 在栈不为空的情况下,若当前为右括号,栈顶左括号出栈
if (e == '(') {
ch = s.pop();
} else
flag = 0;
} else {
flag = 0;
}
break;
}
}
if (flag == 1 && s.isEmpty()) {
return true;
} else {
return false;
}
}
Double compute(char a2[]) { // 计算函数
Stack1 L1 = new Stack1();
Stack2 L2 = new Stack2(); // L2运算符栈,L1操作数栈
Character z, ch, y;
char[] a = new char[50];
char[] b = new char[50];
char[] c = new char[50];
Arrays.fill(b, '\0');
Arrays.fill(c, '\0');
Arrays.fill(a, '\0');
int i, j = 0, n, k = a2.length;
double x1, x2, x;
L2.push('#');
System.arraycopy(a2, 0, a, 0, a2.length);
a[k] = '#';
System.arraycopy(a, 0, b, 0, a.length);
if (a[0] == '-') { // 如果第一个字符为减号,在前面加0
for (n = 0; a[n] != '\0'; n++)
b[n + 1] = a[n];
b[0] = '0';
}
System.arraycopy(b, 0, a, 0, b.length);
for (i = 0; a[i] != '\0'; i++) {
if (a[i] == '(' && a[i + 1] == '-') { // 如果左括号之后为减号,在左括号之后加0
for (n = i; a[n] != '\0'; n++)
b[n + 2] = a[n + 1];
b[i + 1] = '0';
}
}
for (i = 0; b[i] != '\0'; i++) {
if (b[i] >= '0' && b[i] <= '9') {
while (b[i] >= '0' && b[i] <= '9' || b[i] == '.') { // 读取一个完整的操作数(包含小数点)
c[j] = b[i];
i++;
j++;
}
char[] d = new char[j];
System.arraycopy(c, 0, d, 0, j);
j = 0;
Double t = Double.parseDouble(new String(d));
L1.push(t);
Arrays.fill(c, '\0');
}
if (b[i] == '(') {
Character t = b[i];
L2.push(t); // 遇到左括号直接进运算符栈
}
if (b[i] == ')') {
do {
z = L2.pop(); // 遇到右括号,在遇到左括号之前,依次从运算符栈读取一个运算符
try {
switch (z) // 并连续从操作数栈读取两个数进行运算并将结果放入操作数栈,直到遇到左括号,左括号出栈
{
case '+':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 + x2);
break;
case '-':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 - x2);
break;
case '*':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 * x2);
break;
case '/':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 / x2);
break;
}
} catch (ArithmeticException e) {
area.append("\r\n" + "\t" + "分母不能为0!!!");
}
z = L2.getTop();
} while (z != '(');
z = L2.pop();
}
if (b[i] == '+' || b[i] == '-' || b[i] == '/' || b[i] == '*') { // 遇到运算符,与运算符栈栈顶运算符进行优先级比较,若栈顶运算符级别低直接入栈
ch = L2.getTop(); // 否则栈顶运算符出栈
if (L1.prior(b[i]) > L1.prior(ch)) {
Character t = b[i];
L2.push(t);
} else {
do {
ch = L2.pop();
try {
switch (ch) {
case '+':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 + x2);
break;
case '-':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 - x2);
break;
case '*':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 * x2);
break;
case '/':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 / x2);
break;
}
} catch (ArithmeticException e) {
area.append("\r\n" + "\t" + "分母不能为0!!!");
}
ch = L2.getTop();
} while (L1.prior(ch) >= L1.prior(b[i]));
Character t = b[i];
L2.push(t);
}
}
if (b[i] == '#') { // 扫描到#号,运算符栈内的运算符依次出栈直至扫描到的字符为'#'为止
y = L2.getTop();
while (y != '#') {
y = L2.pop();
try {
switch (y) {
case '+':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 + x2);
break;
case '-':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 - x2);
break;
case '*':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 * x2);
break;
case '/':
x2 = L1.pop();
x1 = L1.pop();
L1.push(x1 / x2);
break;
}
} catch (ArithmeticException e) {
area.append("\r\n" + "\t" + "分母不能为0!!!");
}
y = L2.getTop();
}
}
}
x = L1.pop(); // 操作数栈栈顶数据即为计算结果
return x;
}
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < a.length; i++) {
if (e.getActionCommand() == a[i] && i != 0 && i != 5 && i != 11 && i != 17 && i != 19 && i != 20) {
area.append(a[i]);
} else {
continue;
}
}
if (e.getActionCommand() == "BackSpace" && (area.getText()).length() != 0) {
area.setText(area.getText().substring(0, area.getText().length() - 1));
}
if (e.getActionCommand() == "C") {
area.setText("");
}
if (e.getActionCommand() == "=") {
StringBuffer a = new StringBuffer(area.getText());
a.deleteCharAt(a.length() - 1);
if (this.match(a.toString().toCharArray())) {
Double m = this.compute(a.toString().toCharArray());
double result = m;
area.append("\r\n" + "\t\t\t\t" + String.format("%.3f", result));
} else {
area.append("\r\n" + "\t" + "括号不匹配!请检查括号输入是否正确!!");
}
}
}
}
class Myabout implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
new MyDialog();
}
}
class MyDialog extends JDialog {
public MyDialog() {
Container container = getContentPane();
JPanel jPanel = new JPanel(new GridLayout(3, 1));
JLabel name = new JLabel("作者:xxx");
JLabel son = new JLabel("学号:xxxxxxxxxxx");
JLabel clas = new JLabel("班级:xxx");
jPanel.add(name);
jPanel.add(son);
jPanel.add(clas);
container.add(jPanel);
setTitle("关于");
setBounds(50, 150, 300, 200);
setVisible(true);
}
}
public class Calculator {
public static void main(String[] args) throws IOException {
new CalculatorClass();
}
}