Hier noch der gesamte Sourcecode von Einhexpr.java. Die relevanten Stellen habe ich bereits kommentiert. Sollte es zu anderen Stellen Fragen geben oder generell irgendwelche Bemerkungen, bitte im Kommentarbereich schreiben.
Ich freue mich über jeden Kommentar!
1 import eprog.*;
2
3 import java.io.*;
4 import java.util.*;
5
6 class Einhexpr {
7
8
9 private final static String ERROR="FALSCHE EINGABE";
10 private static ArrayList ausdruck;
11
12
13 // ---------------- HILFSFUNKTIONEN ------------------------------------------------
14 //
15
16
17 public static final boolean debugging=false;
18
19 public static void debug(String s) throws Exception {
20 if(debugging)
21 System.out.println(s);
22 }
23
24 public static void reset() throws Exception {
25 ausdruck=new ArrayList();
26 }
27
28
29 public static String ArrayListRangeToString(ArrayList al, int von, int bis)
30 throws Exception {
31
32 if(von==bis)
33 return("[]");
34
35 if((bis-von)==1)
36 return("["+al.get(von)+"]");
37
38
39 String s="[";
40
41 for(int i=von; i
42 s=s+al.get(i)+",";
43
44 s=s+al.get(bis);
45
46 return(s+"]");
47 }
48
49
50 // ----------------- HAUPTFUNKTIONEN -----------------------------------------------
51 //
52 public static void tokenize(String s)
53 throws Exception {
54
55 // siehe: http://java.sun.com/j2se/1.3/docs/
56 // api/java/util/StringTokenizer.html
57
58 StringTokenizer st=new StringTokenizer(
59 s, "()+-*/", true);
60
61 int Klammerebene=0;
62 String token;
63
64 while(st.hasMoreTokens()) {
65 token=st.nextToken();
66
67
68 // Klammern sind was ganz spezielles...
69
70 if(token.equals("("))
71 Klammerebene++;
72 else
73 if(token.equals(")")) {
74 Klammerebene--;
75 if(Klammerebene<0)
76 throw(new Exception("Zuviele schließende Klammern!"));
77 }
78
79 ausdruck.add(token);
80
81 }
82
83
84 if(Klammerebene!=0)
85 throw(new Exception("Zuviele öffnende Klammern!"));
86
87 return;
88 }
89
90
91 public static void verify() throws Exception {
92 for(int i=0; i
93 if( !Berechner.isValidWert((String)ausdruck.get(i)) &&
94 !Berechner.isValidOperator((String)ausdruck.get(i)) )
95
96 throw(new Exception("Token "+i+" ('"+
97 (String)(ausdruck.get(i))+"') ist weder "+
98 "Operator noch Wert."));
99 }
100
101
102 public static boolean isGeklammert() throws Exception {
103 // Annahme: Korrekt geklammert. Sollte ja mit tokenize
104 // gecheckt worden sein!
105
106 return(ausdruck.contains(new String("(")));
107 }
108
109
110 public static int posMulDiv(int von, int bis) throws Exception {
111 for(int i=von; i
112 if(ausdruck.get(i).equals("*") ||
113 ausdruck.get(i).equals("/"))
114 return(i);
115
116 return(-1);
117 }
118
119
120 public static int posAddSub(int von, int bis) throws Exception {
121 for(int i=von; i
122 if(ausdruck.get(i).equals("+") ||
123 ausdruck.get(i).equals("-"))
124 return(i);
125
126 return(-1);
127 }
128
129
130 // berechne(int i)
131 // ..................................................................
132 // ersetzt im Ausdrucksarray eine Stelle der Form
133 // ...ausdruck[i-1]=A, ausdruck[i]=operator, ausdruck[i+1]=B
134 // durch
135 // ...ausdruck[i]=A operator B
136 //
137 // --> A und B werden ausdruck gelöscht, ausdruck verliert somit
138 // zwei Elemente. Übrig bleibt das Ergebnis, von A und B, ver-
139 // knüpft mit dem operator
140 //
141 // das Ergebnis wird ZUSÄTZLICH als String zurückgegeben, kann aber
142 // genausogut ignoriert werden.
143 //
144 public static String berechne(int i) throws Exception {
145
146 debug("berechne(): vor Berechnung");
147 String resultat=Berechner.berechne( (String)ausdruck.get(i-1),
148 (String)ausdruck.get(i),
149 (String)ausdruck.get(i+1));
150
151 debug("berechne(): nach Berechnung");
152 ausdruck.set(i, resultat);
153
154 debug("berechne(): entferne Operatoren");
155 ausdruck.remove(i+1);
156 ausdruck.remove(i-1);
157
158 debug("berechne(): liefere "+resultat);
159 return(resultat);
160 }
161
162
163 public static String berechne(int von, int bis) throws Exception {
164
165 int i;
166
167 while( (i=posMulDiv(von,bis)) != -1) {
168 berechne(i);
169 bis-=2;
170 }
171
172 while( (i=posAddSub(von,bis)) != -1) {
173 berechne(i);
174 bis-=2;
175 }
176
177 if(bis-von>1)
178 throw(new Exception("beim Berechnen von "+von+
179 " bis "+bis+" ist was übrig geblieben: "+
180 ArrayListRangeToString(ausdruck,von,bis)));
181
182 return((String)(ausdruck.get(von)));
183 }
184
185
186 public static int posInnersteKlammerAuf() throws Exception {
187 int Klammerebene=-1, MaxKlammerebene=-1, MaxI=-1;
188
189 for(int i=0; i
190 if(ausdruck.get(i).equals("(")) {
191 Klammerebene++;
192
193 if(Klammerebene > MaxKlammerebene) {
194 MaxKlammerebene=Klammerebene;
195 MaxI=i;
196 }
197 } else
198 if(ausdruck.get(i).equals(")"))
199 Klammerebene--;
200
201 if(MaxI==-1)
202 throw(new Exception("Es gibt keine innerste Klammerebene!"));
203
204 return(MaxI);
205 }
206
207
208 public static int posInnersteKlammerZu(int posKlammerAuf) throws Exception {
209
210 for(int i=posKlammerAuf; i
211 if(((String)ausdruck.get(i)).equals(")"))
212 return(i);
213
214 throw(new Exception("Es gibt keine anschließende schließende Klammer!"));
215
216 }
217
218
219 public static String berechneInnersteKlammer() throws Exception {
220
221 int auf=posInnersteKlammerAuf();
222 int zu=posInnersteKlammerZu(auf);
223
224
225 if(zu-auf<=1)
226 throw(new Exception("() ist ungültig!"));
227
228
229 berechne(auf+1,zu-1);
230
231
232 // Klammern entfernen
233
234 ausdruck.remove(auf+2);
235 ausdruck.remove(auf);
236
237 return((String)(ausdruck.get(auf)));
238 }
239
240
241 public static String beautify(String s) throws Exception {
242 return( Berechner.normalisiereWert(
243 Berechner.getWertNumeric(s))+
244 " "+Berechner.getEinheit(s));
245 }
246
247
248 public static String berechne(String s) throws Exception {
249
250 // 1. Platz für den zerlegten Ausdruck reservieren
251 //
252 reset();
253
254 // 2. Ausdruck in mundgerechte Stücke zerteilen
255 // (dabei gleich auf die Klammern schauen)
256 //
257 tokenize(s);
258
259
260 // 3. Happen genauer analysieren. Alles syntaktisch
261 // korrekt ?
262 //
263 verify();
264
265
266 // 4. zuerst alle Klammern auflösen (innerste zuerst)...
267
268 while(isGeklammert())
269 berechneInnersteKlammer();
270
271
272 // 5. ...und dann den gesamten verbleibenden Ausdruck
273 // gab's bis jetzt keine Exception, können wir das
274 // Ergebnis gleich ausgeben.
275
276 s=berechne(0, ausdruck.size());
277
278
279 // 6. nachdem die Eingabe OHNE Leerzeichen, die Ausgabe
280 // aber mit ist, das ganze noch anpassen & gleich
281 // ausgeben.
282 //
283 return(beautify(s));
284 }
285
286
287 public static void main(String[] args) {
288 // EprogIO.readln gibt's leider keins,
289 // readWord() funktioniert nicht so wirklich...
290 //
291 InputStreamReader ins=new InputStreamReader(System.in);
292 BufferedReader reader=new BufferedReader(ins);
293
294 try {
295
296 EprogIO.println(berechne(reader.readLine()));
297
298 } catch(Exception e) {
299 EprogIO.println(ERROR);
300 }
301 }
302 }
|