우선순위를 고려한 사칙연산 (스택이용)

Posted by ceyx
2011. 1. 29. 18:15 카테고리 없음

스택을 이용하여, 우선순위를 고려한 사칙연산을 수행해주는 source입니다. 임의로 우선순위 숫자를 부여하고, 그에 따라 스택을 이용하여 postfix 로 변환한 후,연산을 수행하게 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import java.lang.String;
import java.util.StringTokenizer;
import javax.swing.JOptionPane;
 
class StackArray     // 스택 클래스
{
    Object firstStack[];
    
    int top;
    
    StackArray(int size) // 생성자
    {
        firstStack = new Object[size];
        top = -1// empty로 초기화
    }
    
    Object getItem(int index)  // index번째의 원소 리턴
    {
        return firstStack[index];
    }
    
    void push(Object ele)      // top에 원소 집어넣기
    {
        firstStack[++top] = ele;
    } 
 
    Object peek()            // top의 원소 보기
    {
        return firstStack[top];
    }
    
    Object pop()             // top의 원소 빼오기
    {
        return firstStack[top--];
    }
}
 
 
class Priority    // 우선순위 알려주는 클래스
{
    int getPri(Object ob)     // 우선순위를 리턴해 주는 메소드
    {
        String operator = (String)ob;
        int pri = -1
        
        if ( operator.equals("+") ) pri = 12;
        if ( operator.equals("-") ) pri = 12
        if ( operator.equals("*") ) pri = 13
        if ( operator.equals("/") ) pri = 13
        if ( operator.equals("%") ) pri = 13
        if ( operator.equals("^") ) pri = 14;
        
        return pri;
     }
}
 
 
 
public class toPostArith
{
    static StackArray mainStack;  //postfix 형태로 변형시킨 식이 들어가 있음.
    static StackArray rStack; // 최종결과가 들어있는 스택 
 
    public static void main(String args[])
    {
        String s1 = JOptionPane.showInputDialog("수식을입력하세요.."); // infix형태의 수식 inputData
        String ConvertPost = makePostFix(s1); // postfix형태로 만드는 메소드 호출. 
        makeFinal();
        JOptionPane.showMessageDialog(null,"PostFix로 전환하면 = "+ConvertPost+"\n"+"최종결과"+rStack.pop());
        System.exit(0);
    }
 
    static String makePostFix(String s2)
    {
        String inputData = s2;
        String nToken; // 토큰을 하나씩 받아와서 저장
        StringTokenizer parser;
        
        parser = new StringTokenizer(inputData,"+-*/^%",true);
        
        int num = parser.countTokens();    // 각 원소 갯수를 알아냄.
        mainStack = new StackArray(num);  // 실제로 필요한 스택자료저장 
 
        StackArray tempStack = new StackArray(num);  // +-/ 등(연산자)을 임시 저장하기위해 
 
          // 스택 사이즈로 num을 쓴 이유는 스택에는 각 원소(변수와 연산자)가 들어가므로 
          // 최대 사이즈가 그 원소의 총 개수와 같거나 작을뿐이기에 여유있게 잡아줌..
        
        String operators = "+-*/^%"// nToken의 값이 연산자인지 구별 
 
        while (parser.hasMoreTokens())      // 토큰이 없을때까지 실행
        {
            nToken = parser.nextToken(); 
 
            boolean isOperator = false;
                        // 연산자인지 아닌지 판별. 기본적으로 false. 즉 연산자 아님을 뜻함. 
 
            for ( int i=0 ; i < operators.length() ; i++ )
            {
                if ( nToken.equals(operators.substring(i,i+1)) ) // 만약 nToken이 연산자이면 true 
                { isOperator = true; } // 연산자일경우만 isOperator에 true를 넣어줌. 
            } 
 
            if ( isOperator == true )   // 연산자일경우 , 연산자 우선순위에 따라 처리..
            {
                Priority p = new Priority(); //  우선순위 관련 클래스를 만든다. 
 
                while ( (tempStack.top >= 0 && p.getPri(nToken) <= p.getPri(tempStack.peek())) )
                {
                    /* nToken의 우선순위와 스택 top에 있는 연산자의 우선순위를 비교하여 
                                             스택 top의 것이 같거나 클때, 반복수행됨. 
                                              연산자가 저장된 스택(tempStack)의 top의 것을 pop하여 
                                              다른 스택에 아래와 같이 push한다.중요!  */ 
                    
                    mainStack.push(tempStack.pop());  // 변수가 저장되는 스택에 pop한것을 push한다. 
                }
                
                tempStack.push(nToken);  // nToken의 우선순위가 스택 top에 있는 연산자 우선순위보다 
                  //큰것을 만족할때 nToken(연산자가 들어가있음)을 연산자가 들어가는 스택에 push한다. 
            }
            
            if ( isOperator == false// 일반 숫자일 경우는 그냥 push한다. 
            {   mainStack.push(nToken);   } 
        }
        
        while ( tempStack.top >= 0 )
        { 
 // 일단 모든 parser에 관해 처리를 했다면 남아있는 것(tempStack)들을 모두 pop해서 mainStack에 push한다. 
            mainStack.push(tempStack.pop());
        }
        
        String userView="";
        
        for (int i=0; i<=mainStack.top ;i++ )
        {
            userView = userView + mainStack.getItem(i);
                // 화면에는 pop을 이용해서 보이게 할수 없으므로..처음부터 get.. 
        }
        
        return userView;
    }
    
    static void makeFinal()
    {
        rStack = new StackArray(mainStack.top+1);
          // 만약 3개가 들어있으면 top은 2라는 값을 가지므로 +1 해 줘야 
          // 안전하게 스택사이즈 결정할수 있다.
        
        for ( int i=0; i <= mainStack.top ; i++ )
        {
            Object t = mainStack.getItem(i);  //i 번째 원소를 리턴해서 t에 대입.
            
            if ( t.equals("+")||t.equals("-")||t.equals("*")||t.equals("/")||t.equals("%")||t.equals("^"))
            {              // 연산자일경우.   아래와 같이 두번 팝(pop)한다.
                double latter = Double.valueOf((String)rStack.pop()).doubleValue(); 
                      //pop는 뒤에서부터 가져오는것이므로  먼저가져온것이 실제로 후자.
                double former = Double.valueOf((String)rStack.pop()).doubleValue();
                double temp = -1// 계산결과를 저장하는 변수,일단 임의의 값 -1대입. 
                
                if ( t.equals("+") )  { temp = former+latter; }
                if ( t.equals("-") )  { temp = former-latter; }
                if ( t.equals("*") )  { temp = former*latter; }
                if ( t.equals("/") )  { temp = former/latter; }
                if ( t.equals("%") )  { temp = former%latter; }
                if ( t.equals("^") )  { temp = getSquare(former,latter); }
                
                rStack.push(temp+"");  // 계산결과(temp)를 push해 준다.
            }
            else   // 연산자가 아닐경우
            {
                rStack.push(t); // 그냥 push해줌.
            }
        }
    }
    
    static double getSquare(double x,double exp)       // 거듭제곱
    {
        int i;
        double temp=1;
        
        for (i=1 ; i<=exp ; i++ )
        {   temp = temp * x;   }
        
        return temp;
    }
cs

 

 

자바 배운지 얼마 안됐을 때라.. 기억도 가물가물하고.. 지금보니 뭔가 ㅎㅎㅎㅎ