问题分析
解决所有复杂问题都是一样的思路,所有复杂的问题都是由一个个简单的问题组合而成的。所以第一步是将问题分解,分解,在分解。可以将计算器程序分成两部分,一部分是数据的处理,另一部分是界面的显示。
一、计算机界面显示
1.计算器界面显示
界面可以分为两部分,一部分为按钮部分,即零到九的数字按钮,加减乘除、小括号、删,等于等运算符按钮。另一部分为显示部分,即文本,用于显示用户的输入,和运算结果的显示。
2.计算器界面显示代码及部分说明
public static void showCalculate(JFrame jframe) {
int x,y;
for(int i=1;i<=9;i++) {
x=(i-1)*(int)width/3%(width);
y=(i-1)/3*((int)height/6);
addButton(i+"", x, y, width/3,(int)height/6, jframe);
}
//因为创建按钮是比较重复的过程,所以写一个函数进行按钮的添加,按钮上的文本信息,长宽,位置等作为参数来改变按钮就行,其实只要文本信息和位置信息,就可以了,因为该计算机的其他信息如按钮宽高等信息都是相同的。*/
addButton("(", 0, height/2, width/3, height/6, jframe);
addButton("0", width/3, height/2, width/3, height/6, jframe);
addButton(")", width/3*2, height/2, width/3, height/6, jframe);
addButton("+", 0, height*2/3, width/3, height/6, jframe);
addButton("-", width/3, height*2/3, width/3, height/6, jframe);
addButton("*", width/3*2, height*2/3, width/3, height/6, jframe);
addButton("/", 0, height/6*5, width/3, height/6, jframe);
addButton("delete", width/3, height/6*5, width/3, height/6, jframe);
addButton("=", width/3*2, height/6*5, width/3, height/6, jframe);
//显示文本框,用于显示用户输入,和计算结果。
jLabel.setBounds(0,0,width-40,40);
jLabel.setHorizontalAlignment(JLabel.RIGHT);
jLabel.setFont(new Font("",Font.BOLD,20));
jframe.add(jLabel);
}
//用于生成按钮。
public static void addButton(String name,int x,int y,int width,int height,JFrame frame) {
JButton jb=new JButton(name);
jb.setBounds(x, y+40, width, height);
frame.add(jb);
ButtonHandler btnHandler=new ButtonHandler(name);
jb.addActionListener(btnHandler);
}
//用于为按钮添加事件的类,继承ActionListener接口
public static class ButtonHandler implements ActionListener{
private String typeString;
public ButtonHandler(String type) {
typeString=type;
}
@Override
public void actionPerformed(ActionEvent e) {
if(!isNewBoolean) {
isNewBoolean=true;
jLabel.setText("");
}
if(typeString=="=") {
calculateResult();
}else if(typeString=="delete") {
String tempString=jLabel.getText();
if(tempString.length()>0) {
jLabel.setText(tempString.substring(0,tempString.length()-1));
}
}
else {
jLabel.setText(jLabel.getText()+typeString);
}
}
}
3.计算器界面显示截图
二、 计算器计算数据处理
1.数据处理
数据处理即算式的计算,用户输入的是中缀算式表达式,我们需要做的第一件事情是将中缀表达式改成后缀表达式以方便后面的运算。
中缀表达式转换原理:从左向右扫描用户输入的中缀表达式,遇到数字就加入到后缀表达式的数值后面,处理运算符需要用到运算符栈,如果扫描到运算符,若栈中没有元素,则直接进栈,若栈中有元素,且运算优先级高与现有运算符,则出栈该运算符,然后加入到后缀表达式中,接着按照上方的原则,继续扫描栈顶元素,直到现有运算符优先级大于该栈顶元素时,进栈现有元素。如果运算符是小括号的前半部分,则直接进栈,如果是小括号的后半部分,则出栈元素,并加入到后缀表达式中,直到出栈元素是小括号的前半部分。当扫描完毕后,将运算符栈里面的所有元素出栈加入后缀表达式中。
接着是后缀表达式的计算:从左到右扫描后缀表达式,遇到数值就直接进栈,遇到运算符,就出栈两个操作数,后出栈的作为被操作数,先出栈的做操作数,运算的结果重新进栈。最后栈内只剩一个元素,即运算结果。
2.算式查错
用户输入的算式不一定正确,错误的算式没有必要计算,且程序如果对错误的算式进行错误检查就进行计算,会导致程序崩溃。
算式查错需要检查很多方面。运算符的左右两端必须是操作数,或者运算符左端可以是小括号的右端,运算符的右端可以是小括号的左端。除运算符的右端不能是零。等等…
3.计算器计算源码及部分说明
//当用户按下“=”按钮时,就会调用这个函数进行结果计算
public static void calculateResult() {
//因为输入的算式一整个都是String类型,为了后续的计算,需要将这一整个String类型中的运算符//和操作数分割开来存在String类数组中。此时是中缀表达式。
ArrayList<String> origStrings=new ArrayList<String>();
String tempString="";
char singleChar;
for(int i=0;i<jLabel.getText().length();i++) {
singleChar=jLabel.getText().charAt(i);
if(Character.isDigit(singleChar)) {
tempString+=singleChar;
}else {
if(tempString!="") {
origStrings.add(tempString);
tempString="";
}
tempString+=singleChar;
origStrings.add(tempString);
tempString="";
}
}
if(tempString!="") {
origStrings.add(tempString);
}
//将中缀表达式转换成后缀表达式
origStrings=transToHouZui(origStrings);
//将后缀表达式带入进行计算。
float result=calculateTheResult(origStrings);
//将结果输出到界面。
jLabel.setText(jLabel.getText()+"="+result);
//这个bool类型数据是为了计算完结果后下次输入算式时可以从头开始,刷新显示界面。
isNewBoolean=false;
}
//用于计算后缀表达式
public static float calculateTheResult(ArrayList<String> strings) {
Stack<Float> stack=new Stack<Float>();
String tempString;
float x,y;
for(int i=0;i<strings.size();i++) {
tempString=strings.get(i);
if(tempString.equals("+")) {
y=stack.pop();
x=stack.pop();
x=x+y;
stack.push(x);
}else if(tempString.equals("-")) {
y=stack.pop();
x=stack.pop();
x=x-y;
stack.push(x);
}else if(tempString.equals("*")) {
y=stack.pop();
x=stack.pop();
System.out.println("X:"+x+"Y"+y);
x=x*y;
stack.push(x);
}else if(tempString.equals("/")){
y=stack.pop();
x=stack.pop();
x=x/y;
stack.push(x);
}else {
stack.push(Float.parseFloat(tempString));
}
}
return stack.pop();
}
//用于将中缀表达式转换成后缀表达式
public static ArrayList<String> transToHouZui(ArrayList<String> strings) {
System.out.println("strings"+strings);
String tempString="";
ArrayList<String> resultStrings=new ArrayList<String>();
Stack<String> stack=new Stack<String>();
for(int i=0;i<strings.size();i++) {
tempString=strings.get(i);
System.out.println("strings"+tempString.equals("*"));
if(tempString.equals("(")) {
stack.push("(");
}else if(tempString.equals(")")) {
while(!stack.peek().equals("(")) {
resultStrings.add(stack.pop());
}
stack.pop();
}else if(tempString.equals("+")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(!stack.peek().equals("(")) {
resultStrings.add(stack.pop());
}else {
break;
}
}while(!stack.empty());
stack.push(tempString);
}
}else if(tempString.equals("-")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(!stack.peek().equals("(")) {
resultStrings.add(stack.pop());
}else {
break;
}
}while(!stack.empty());
stack.push(tempString);
}
}else if(tempString.equals("*")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(stack.peek().equals("*")||stack.peek().equals("/")) {
resultStrings.add(stack.pop());
}else {
stack.push(tempString);
break;
}
}while(!stack.empty());
}
}else if(tempString.equals("/")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(stack.peek().equals("*")||stack.peek().equals("/")) {
resultStrings.add(stack.pop());
}else {
stack.push(tempString);
break;
}
}while(!stack.empty());
}
}else {
resultStrings.add(tempString);
}
}
while(!stack.empty()) {
resultStrings.add(stack.pop());
}
return resultStrings;
}
三、 部分源代码(该源码未加入算式查错,文件资源正在上传)
package calculateMachine;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Stack;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class calculateMachine {
private static int width=400;
private static int height=200;
public static JLabel jLabel=new JLabel("");
public static Boolean isNewBoolean=true;
public static void main(String args[]) {
JFrame frame=new JFrame("计算机");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
showCalculate(frame);
frame.setBounds(200,200,width,height+78);
frame.setVisible(true);
}
public static void addButton(String name,int x,int y,int width,int height,JFrame frame) {
JButton jb=new JButton(name);
jb.setBounds(x, y+40, width, height);
frame.add(jb);
ButtonHandler btnHandler=new ButtonHandler(name);
jb.addActionListener(btnHandler);
}
public static void showCalculate(JFrame jframe) {
int x,y;
for(int i=1;i<=9;i++) {
x=(i-1)*(int)width/3%(width);
y=(i-1)/3*((int)height/6);
addButton(i+"", x, y, width/3,(int)height/6, jframe);
}
addButton("(", 0, height/2, width/3, height/6, jframe);
addButton("0", width/3, height/2, width/3, height/6, jframe);
addButton(")", width/3*2, height/2, width/3, height/6, jframe);
addButton("+", 0, height*2/3, width/3, height/6, jframe);
addButton("-", width/3, height*2/3, width/3, height/6, jframe);
addButton("*", width/3*2, height*2/3, width/3, height/6, jframe);
addButton("/", 0, height/6*5, width/3, height/6, jframe);
addButton("delete", width/3, height/6*5, width/3, height/6, jframe);
addButton("=", width/3*2, height/6*5, width/3, height/6, jframe);
jLabel.setBounds(0,0,width-40,40);
jLabel.setHorizontalAlignment(JLabel.RIGHT);
jLabel.setFont(new Font("",Font.BOLD,20));
jframe.add(jLabel);
}
public static class ButtonHandler implements ActionListener{
private String typeString;
public ButtonHandler(String type) {
typeString=type;
}
@Override
public void actionPerformed(ActionEvent e) {
if(!isNewBoolean) {
isNewBoolean=true;
jLabel.setText("");
}
if(typeString=="=") {
calculateResult();
}else if(typeString=="delete") {
String tempString=jLabel.getText();
if(tempString.length()>0) {
jLabel.setText(tempString.substring(0,tempString.length()-1));
}
}
else {
jLabel.setText(jLabel.getText()+typeString);
}
}
}
public static void calculateResult() {
ArrayList<String> origStrings=new ArrayList<String>();
String tempString="";
char singleChar;
for(int i=0;i<jLabel.getText().length();i++) {
singleChar=jLabel.getText().charAt(i);
if(Character.isDigit(singleChar)) {
tempString+=singleChar;
}else {
if(tempString!="") {
origStrings.add(tempString);
tempString="";
}
tempString+=singleChar;
origStrings.add(tempString);
tempString="";
}
}
if(tempString!="") {
origStrings.add(tempString);
}
origStrings=transToHouZui(origStrings);
float result=calculateTheResult(origStrings);
jLabel.setText(jLabel.getText()+"="+result);
isNewBoolean=false;
}
public static float calculateTheResult(ArrayList<String> strings) {
Stack<Float> stack=new Stack<Float>();
String tempString;
float x,y;
//System.out.println(strings);
for(int i=0;i<strings.size();i++) {
tempString=strings.get(i);
if(tempString.equals("+")) {
y=stack.pop();
x=stack.pop();
x=x+y;
stack.push(x);
}else if(tempString.equals("-")) {
y=stack.pop();
x=stack.pop();
x=x-y;
stack.push(x);
}else if(tempString.equals("*")) {
y=stack.pop();
x=stack.pop();
System.out.println("X:"+x+"Y"+y);
x=x*y;
stack.push(x);
}else if(tempString.equals("/")){
y=stack.pop();
x=stack.pop();
x=x/y;
stack.push(x);
}else {
stack.push(Float.parseFloat(tempString));
}
}
return stack.pop();
}
public static ArrayList<String> transToHouZui(ArrayList<String> strings) {
System.out.println("strings"+strings);
String tempString="";
ArrayList<String> resultStrings=new ArrayList<String>();
Stack<String> stack=new Stack<String>();
for(int i=0;i<strings.size();i++) {
tempString=strings.get(i);
System.out.println("strings"+tempString.equals("*"));
if(tempString.equals("(")) {
stack.push("(");
}else if(tempString.equals(")")) {
while(!stack.peek().equals("(")) {
resultStrings.add(stack.pop());
}
stack.pop();
}else if(tempString.equals("+")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(!stack.peek().equals("(")) {
resultStrings.add(stack.pop());
}else {
break;
}
}while(!stack.empty());
stack.push(tempString);
}
}else if(tempString.equals("-")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(!stack.peek().equals("(")) {
resultStrings.add(stack.pop());
}else {
break;
}
}while(!stack.empty());
stack.push(tempString);
}
}else if(tempString.equals("*")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(stack.peek().equals("*")||stack.peek().equals("/")) {
resultStrings.add(stack.pop());
}else {
stack.push(tempString);
break;
}
}while(!stack.empty());
}
}else if(tempString.equals("/")) {
if(stack.empty()) {
stack.push(tempString);
}else {
do{
if(stack.peek().equals("*")||stack.peek().equals("/")) {
resultStrings.add(stack.pop());
}else {
stack.push(tempString);
break;
}
}while(!stack.empty());
}
}else {
resultStrings.add(tempString);
}
}
while(!stack.empty()) {
resultStrings.add(stack.pop());
}
return resultStrings;
}
}