오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(신입사원채용무료교육, 오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷)
JAVA에서 직접 구현한 스택, 스윙(Stack, Swing)을 이용한 GUI 계산기 소스
1. ArrayStack.java
import java.util.*;
interface Stack {
public boolean isEmpty();
public Object peek();
public void push(Object theObject);
public Object pop();
}
public class ArrayStack implements Stack {
int top; // current top of stack
Object [] stack; // element array
public boolean isEmpty();
public Object peek();
public void push(Object theObject);
public Object pop();
}
public class ArrayStack implements Stack {
int top; // current top of stack
Object [] stack; // element array
public ArrayStack(int initialCapacity) {
if (initialCapacity < 1)
throw new IllegalArgumentException
("initialCapacity must be >= 1");
stack = new Object [initialCapacity] ;
top = -1;
}
public ArrayStack() {
this(10);
}
public boolean isEmpty( ) {
return top == -1;
}
public Object peek() {
if (isEmpty() )
throw new EmptyStackException();
return stack[top];
}
public void push(Object theElement) {
// increase array size if necessary
if (top == stack.length - 1) ensureCapacity();
// put theElement at the top of the stack
stack[++top] = theElement;
}
public Object pop() {
if (isEmpty())
throw new EmptyStackException();
Object topElement = stack[top];
stack[top--] = null; // enable garbage collection
return topElement;
}
private void ensureCapacity() {
Object[] larger = new Object[stack.length*2];
Object[] larger = new Object[stack.length*2];
for (int index=0; index < stack.length; index++)
larger[index] = stack[index];
larger[index] = stack[index];
stack = larger;
}
}
public String toString() {
if (isEmpty())
return "<empty stack>";
String result = "<stack :";
for (int i = top; i >= 0; i--)
result += stack[i] + " ";
return result + ">";
} // end toString
}
if (isEmpty())
return "<empty stack>";
String result = "<stack :";
for (int i = top; i >= 0; i--)
result += stack[i] + " ";
return result + ">";
} // end toString
}
2. MessageBox.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.*;
public class MessageBox extends JDialog implements ActionListener
{
public MessageBox(Frame parent, String title, String message) {
super(parent, title, true);
public MessageBox(Frame parent, String title, String message) {
super(parent, title, true);
//대화상자를 내부에 위치시킴
Dimension parentSize = parent.getSize();
Point p = parent.getLocation();
setLocation(p.x+parentSize.width/4, p.y+parentSize.height/4);
Dimension parentSize = parent.getSize();
Point p = parent.getLocation();
setLocation(p.x+parentSize.width/4, p.y+parentSize.height/4);
//메시지 패널을 생성
JPanel panel = new JPanel();
panel.add(new JLabel(message));
getContentPane().add(panel);
JPanel panel = new JPanel();
panel.add(new JLabel(message));
getContentPane().add(panel);
//버튼패널을 생성한다.
JPanel bpanel = new JPanel();
JButton button = new JButton("OK");
bpanel.add(button);
button.addActionListener(this);
JPanel bpanel = new JPanel();
JButton button = new JButton("OK");
bpanel.add(button);
button.addActionListener(this);
getContentPane().add(bpanel,
BorderLayout.SOUTH);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
setVisible(false);
dispose();
}
}
setVisible(false);
dispose();
}
}
3. Calculation.java
import java.util.*;
class Calculation {
//-------------------------------------------------------------------
//스택을 이용하여 중위표현을 후위표현으로 바꾸는 메소드
//-------------------------------------------------------------------
String postfix(String infixExp) {
Double value;
//숫자의 끝임을 알려주는 flag
//소수점 수식도 처리하기 위해서...
boolean endOfNumber = false;
String postfixExp = new String();
ArrayStack stk = new ArrayStack();
//-------------------------------------------------------------------
//스택을 이용하여 중위표현을 후위표현으로 바꾸는 메소드
//-------------------------------------------------------------------
String postfix(String infixExp) {
Double value;
//숫자의 끝임을 알려주는 flag
//소수점 수식도 처리하기 위해서...
boolean endOfNumber = false;
String postfixExp = new String();
ArrayStack stk = new ArrayStack();
for(int i = 0; i < infixExp.length(); i++)
{
switch(infixExp.charAt(i))
{
//피연산자는 그대로 출력한다.
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
postfixExp = postfixExp.concat(infixExp.charAt(i)+"");
endOfNumber = true;
break;
//왼쪽괄호인 경우에는 스택에 push 한다.
case '(':
if(endOfNumber == true) {
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
{
switch(infixExp.charAt(i))
{
//피연산자는 그대로 출력한다.
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
postfixExp = postfixExp.concat(infixExp.charAt(i)+"");
endOfNumber = true;
break;
//왼쪽괄호인 경우에는 스택에 push 한다.
case '(':
if(endOfNumber == true) {
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
stk.push(new Character('('));
break;
//우측괄호인 경우 좌괄호가 나올때까지 pop하여 출력하고
//좌괄호는 pop하여 버린다.
case ')':
if(endOfNumber == true) {
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
while(((Character)stk.peek()).charValue() != '(' )
postfixExp = postfixExp.concat(((Character)stk.pop()).toString());
Object openParen = stk.pop();
break;
case '+':
case '-':
case '*':
case '/':
if(endOfNumber == true) {
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
//연산자를 만나면 스택에서 그 연산자보다 낮은 우선순위의 연산자를 만날 때까지
//팝하여 출력한 뒤에 자신을 푸시한다.(우선순위가 같거나 높은것은 팝한다.)
while ( !stk.isEmpty() && ((Character)stk.peek()).charValue() != '('
&& getPrec(infixExp.charAt(i)) <= getPrec(((Character)stk.peek()).charValue()) ) {
postfixExp = postfixExp.concat(((Character)stk.pop()).toString());
}
stk.push(new Character(infixExp.charAt(i)));
break;
}
}
break;
//우측괄호인 경우 좌괄호가 나올때까지 pop하여 출력하고
//좌괄호는 pop하여 버린다.
case ')':
if(endOfNumber == true) {
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
while(((Character)stk.peek()).charValue() != '(' )
postfixExp = postfixExp.concat(((Character)stk.pop()).toString());
Object openParen = stk.pop();
break;
case '+':
case '-':
case '*':
case '/':
if(endOfNumber == true) {
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
//연산자를 만나면 스택에서 그 연산자보다 낮은 우선순위의 연산자를 만날 때까지
//팝하여 출력한 뒤에 자신을 푸시한다.(우선순위가 같거나 높은것은 팝한다.)
while ( !stk.isEmpty() && ((Character)stk.peek()).charValue() != '('
&& getPrec(infixExp.charAt(i)) <= getPrec(((Character)stk.peek()).charValue()) ) {
postfixExp = postfixExp.concat(((Character)stk.pop()).toString());
}
stk.push(new Character(infixExp.charAt(i)));
break;
}
}
if(endOfNumber == true) {
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
postfixExp = postfixExp.concat(" ");
endOfNumber = false;
}
//모든 작업이 끝나면 스택에 있는 연산자들을 모두 팝하여 출력한다.
while( !stk.isEmpty()) {
postfixExp = postfixExp.concat(((Character)stk.pop()).toString());
}
return postfixExp;
}
while( !stk.isEmpty()) {
postfixExp = postfixExp.concat(((Character)stk.pop()).toString());
}
return postfixExp;
}
//----------------------------------------------------------------------
//후위표기 수식을 스택을 이용한 연산을 수행하는 메소드
//----------------------------------------------------------------------
Double result(String postfixExp) {
Double value, buffer;
String temp = new String();
ArrayStack stk = new ArrayStack();
//후위표기 수식을 스택을 이용한 연산을 수행하는 메소드
//----------------------------------------------------------------------
Double result(String postfixExp) {
Double value, buffer;
String temp = new String();
ArrayStack stk = new ArrayStack();
for(int i=0; i<postfixExp.length(); i++) {
switch(postfixExp.charAt(i)) {
switch(postfixExp.charAt(i)) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
//여기까지는 아직 공백을 만나지 않았으므로 수식의 끝이 아니다.
temp = temp.concat(postfixExp.charAt(i)+"");
break;
case ' ':
//공백을 만나서야 비로서 수식을 스택에 넣는다.
//공백을 만나기전에 수식이 여러개 있었다면 temp에 붙어서 저장되어 있다.
stk.push(new Double(temp));
temp = new String();
break;
case '+':
value = new Double(((Double)stk.pop()).doubleValue() + ((Double)stk.pop()).doubleValue());
stk.push(value);
break;
case '-':
buffer = new Double(((Double)stk.pop()).doubleValue());
value = new Double(((Double)stk.pop()).doubleValue() - buffer.doubleValue());
stk.push(value);
break;
case '*':
value = new Double(((Double)stk.pop()).doubleValue() * ((Double)stk.pop()).doubleValue());
stk.push(value);
break;
case '/':
buffer = new Double(((Double)stk.pop()).doubleValue());
value = new Double(((Double)stk.pop()).doubleValue() / buffer.doubleValue());
stk.push(value);
break;
}
}
return (Double)stk.peek();
}
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
//여기까지는 아직 공백을 만나지 않았으므로 수식의 끝이 아니다.
temp = temp.concat(postfixExp.charAt(i)+"");
break;
case ' ':
//공백을 만나서야 비로서 수식을 스택에 넣는다.
//공백을 만나기전에 수식이 여러개 있었다면 temp에 붙어서 저장되어 있다.
stk.push(new Double(temp));
temp = new String();
break;
case '+':
value = new Double(((Double)stk.pop()).doubleValue() + ((Double)stk.pop()).doubleValue());
stk.push(value);
break;
case '-':
buffer = new Double(((Double)stk.pop()).doubleValue());
value = new Double(((Double)stk.pop()).doubleValue() - buffer.doubleValue());
stk.push(value);
break;
case '*':
value = new Double(((Double)stk.pop()).doubleValue() * ((Double)stk.pop()).doubleValue());
stk.push(value);
break;
case '/':
buffer = new Double(((Double)stk.pop()).doubleValue());
value = new Double(((Double)stk.pop()).doubleValue() / buffer.doubleValue());
stk.push(value);
break;
}
}
return (Double)stk.peek();
}
//------------------------------------------
//연산자의 우선순위를 Return
//------------------------------------------
int getPrec(char op) {
int prec = 0;
switch (op) {
case '+':
case '-':
prec = 1;
break;
case '*':
case '/':
prec = 2;
break;
}
return prec;
}
//연산자의 우선순위를 Return
//------------------------------------------
int getPrec(char op) {
int prec = 0;
switch (op) {
case '+':
case '-':
prec = 1;
break;
case '*':
case '/':
prec = 2;
break;
}
return prec;
}
//-----------------------------------------
//괄호의 정확성 검사
//-----------------------------------------
static boolean bracketsBalance (String exp) {
ArrayStack stk = new ArrayStack(exp.length() +1);
for (int i = 0; i < exp.length(); i++) {
//Scan across the __EXPRESSION__
char ch = exp.charAt(i);
if ( ch== '[' || ch == '(' ) {
stk.push( new Character(ch));
}
else if(ch == ']' || ch == ')') {
//empty means brackets unmatched
if (stk.isEmpty()) return false;
char charFromStack = ((Character)stk.pop()).charValue();
if ( ch == ']' && charFromStack != '['
|| (ch == ')' && charFromStack != '(') )
return false;
} // end if
} // end for loop
return stk.isEmpty(); //empty means matched, else unmatched
}
}
//괄호의 정확성 검사
//-----------------------------------------
static boolean bracketsBalance (String exp) {
ArrayStack stk = new ArrayStack(exp.length() +1);
for (int i = 0; i < exp.length(); i++) {
//Scan across the __EXPRESSION__
char ch = exp.charAt(i);
if ( ch== '[' || ch == '(' ) {
stk.push( new Character(ch));
}
else if(ch == ']' || ch == ')') {
//empty means brackets unmatched
if (stk.isEmpty()) return false;
char charFromStack = ((Character)stk.pop()).charValue();
if ( ch == ']' && charFromStack != '['
|| (ch == ')' && charFromStack != '(') )
return false;
} // end if
} // end for loop
return stk.isEmpty(); //empty means matched, else unmatched
}
}
4. Calc.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
//------------------------------------------------------------------
//
//
// Main Class
// - main method
//
//------------------------------------------------------------------
class Calc extends JFrame {
public static void main(String[] args) {
JFrame myCalc = new CalcWindow(); // Call the constructor
//System exit로 종료, 오직 Application에서만 사용가능
myCalc.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myCalc.setVisible(true);
}
}
//
//
// Main Class
// - main method
//
//------------------------------------------------------------------
class Calc extends JFrame {
public static void main(String[] args) {
JFrame myCalc = new CalcWindow(); // Call the constructor
//System exit로 종료, 오직 Application에서만 사용가능
myCalc.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myCalc.setVisible(true);
}
}
//--------------------------------------------------------------------------------
// Class Name : CalcWindow
// Desc : 계산기의 GUI를 구성합니다.
// Method :
// Constructot : 생성자에서 GUI 부분을 완성한다.
// void action_display(ActionEvent e) : 버튼등 만들어진 객체의 실제 이벤트 처리를 합니다.
//
// 아래는 생성자 부분의 리스너를 만드는 부분입니다.
// ActionListener calcListener = new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// action_display(e); // process the
// }
// };
//
// 이부분에서 action_display 메소드를 call 합니다. 즉 버튼등 이벤트
// 처리할것을 만들면 리스너를 addActionListener 명령으로
// 리스너를 Add해야 이벤트 처리가 가능합니다.
//
//
//----------------------------------------------------------------------------------
class CalcWindow extends JFrame {
JTextField displayField; // 수식을 입력, 결과 display창
double resultValue = 0.0; // 스택에 의한 계산 결과값을 받는변수
String postfix; // 후위로 바꾸어 이를 보고나하는 변수
static Font biggerFont = new Font("monspaced", Font.PLAIN, 24);
public CalcWindow() {
//--- 상단의 TextField
displayField = new JTextField(" ", 12);
displayField.setHorizontalAlignment(JTextField.TRAILING);
displayField.setFont(biggerFont);
//--- 상단의 TextField
displayField = new JTextField(" ", 12);
displayField.setHorizontalAlignment(JTextField.TRAILING);
displayField.setFont(biggerFont);
//--- Clear button
JButton clearButton = new JButton("CLEAR");
clearButton.setFont(biggerFont);
JButton clearButton = new JButton("CLEAR");
clearButton.setFont(biggerFont);
//--- 리스너들, 여기서는 clear용및 상단의 displayField 에
//--- 값을 추가시키는 두가지의 리스너 종류가 존재한다.
//--- Clear Button 이벤트 처리용 리스너
clearButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_clear();
}
});
//--- 값을 추가시키는 두가지의 리스너 종류가 존재한다.
//--- Clear Button 이벤트 처리용 리스너
clearButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_clear();
}
});
//--- 버튼을 누르면 상단의 JTextField에 출력하기 위한 리스너
ActionListener calcListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_display(e); // process the
}
};
// 계산기 숫자키 및 괄호 키 Button Create
String buttonOrder = "1234567890().";
JPanel buttonPanel = new JPanel(new GridLayout(5, 3));
for (int i = 0; i < buttonOrder.length(); i++) {
JButton b = new JButton(buttonOrder.substring(i, i+1));
b.addActionListener(calcListener);
b.setFont(biggerFont);
buttonPanel.add(b);
}
ActionListener calcListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_display(e); // process the
}
};
// 계산기 숫자키 및 괄호 키 Button Create
String buttonOrder = "1234567890().";
JPanel buttonPanel = new JPanel(new GridLayout(5, 3));
for (int i = 0; i < buttonOrder.length(); i++) {
JButton b = new JButton(buttonOrder.substring(i, i+1));
b.addActionListener(calcListener);
b.setFont(biggerFont);
buttonPanel.add(b);
}
//--- Create panel, listener, and buttons for all the operations
JPanel opPanel = new JPanel(new GridLayout(5, 1));
String opOrder = "+-*/=";
for (int i = 0; i < opOrder.length(); i++) {
JButton b = new JButton(opOrder.substring(i, i+1));
b.addActionListener(calcListener);
b.setFont(biggerFont);
opPanel.add(b);
}
//--- Layout the top-level content panel
Container content = this.getContentPane();
content.setLayout(new BorderLayout(4, 4)); //4,4는 hgap, vgap
content.add(displayField, BorderLayout.NORTH );
content.add(buttonPanel , BorderLayout.CENTER);
content.add(opPanel , BorderLayout.EAST );
content.add(clearButton , BorderLayout.SOUTH );
Container content = this.getContentPane();
content.setLayout(new BorderLayout(4, 4)); //4,4는 hgap, vgap
content.add(displayField, BorderLayout.NORTH );
content.add(buttonPanel , BorderLayout.CENTER);
content.add(opPanel , BorderLayout.EAST );
content.add(clearButton , BorderLayout.SOUTH );
this.setTitle("Calc");
this.pack();
}//end constructor
this.pack();
}//end constructor
// Called by the action listener for numeric keys
void action_display(ActionEvent e) {
String string = e.getActionCommand(); //눌러진 키 값
/////////////////////////////////////////////////////등호가 넘어오는 경우엔 스택을 이용하자...
if (string.equals("=")) {
Calculation c = new Calculation();
boolean isOK = c.bracketsBalance(displayField.getText()); //괄호검사
if (isOK) {
postfix = c.postfix(displayField.getText()); //후위표기로 바꿈
resultValue = c.result(postfix).doubleValue(); //계산후 결과받음
displayField.setText("" + resultValue); //화면에 뿌려줌
}
else {
MessageBox m = new MessageBox(this, "오류!", "괄호가 잘못 되었습니다...");
action_clear();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
else {
// 등호가 아니라면 텍스트필드에 추가
displayField.setText(displayField.getText() + string);
}
}
//clear 버튼 처리시 호출되는 메소드
void action_clear() {
displayField.setText(" ");
resultValue = 0;
}
}
댓글 없음:
댓글 쓰기