数据结构课程设计-----计算器

        本课程设计有源文档,仅供各位参考,功能不完善

一、设计题目

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();

	}

}

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 摘 要 1 前 言 2 正 文 3 1. 采用类C语言定义相关的数据类型 3 2. 各模块的伪码算法 5 3. 函数的调用关系图 9 4. 调试分析 10 5. 测试结果 11 6. 源程序(带注释) 14 总 结 22 参考文献 23 致 谢 24 摘 要 目前,计算器应用很广泛,本程序是关于这方面的,其主要功能是进行简单的四则运算 ,其特点之一是支持带括号的四则运算;二是用到栈的一些相关操作,不但对操作有提示,还对与异常输入信息报错。 通过该题目的设计过程,可以加深理解线性表及栈的逻辑结构、存储结构,掌握线性表及栈上基本运算的实现,进一步理解和熟练掌握课本中所学的各种数据结构,学会如何把学到的知识用于解决实际问题,培养学生的动手能力。 关键字:堆栈,初始化栈,入栈,出栈。 前 言 很多涉及计算器程序的的算法都是以栈的相关操作为基础,通过计算器设计,有利于在学习中更好的理解栈及其相关的操作。 通过对计算器计算过程演示,看到了到它的一些性能及相关优势。 我们在写程序时,大框架已成的情况下,仍然发现有些错误很难找到,对于这样的问题,可以利用计算机纠错功能,先运行,再根据题提示修改和完善程序。 在计算器用到的算法中,c语言算法可读性很强,一方面,是因为c语言是高级语言,是面向程序员的语言,二是c语言的功能是很完备的,可以达到事半功倍的效果,和其他语言相比量是比较少。栈的应用使该程序更出色。 正 文 1. 采用类c语言定义相关的数据类型 计算器的演示功能如下: A. 提示输入格式 B. 提示输入 C. 显示输入信息 D. 对有异常的输入报错并重新输入 E. 使用顺序栈实现数据的输入 (1)/*定义堆栈*/ typedef struct{ double data[M]; int top; }Stack; (2)/*初始化堆栈*/ InitStack(Stack *s) { s->top=0; } (3)/*判断栈是否为空*/ int StEmpty(Stack *s) { if(s->top==0) { return 1; } else { return 0; } } (4)/*入栈操作*/ StPush(Stack *s,double x) { if(s->top==M) { printf("The stack is overflow!"); } else { s->top=s->top+1; s->data[s->top]=x; } }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值