Hi @ all,
ich soll für die FH einen Mathe Parser schreiben, ich habe vier Testfälle, Exceptions für ungültige Ausdrücke wollte ich erst schreiben wenn die gültigen Funktionieren, die ersten drei Testfälle funktionieren auch, aber das letzte Funktioniert nicht.
Bei dem Ausdruck "1 + 2 * ( i + 2 * k - 1 ) / 2 + j" mit i = 3, k = 4 und j = 9 berechnet mein Parser 30, anstatt 20.
Vielleich kann jemand einmal drüber gucken und mir den Fehler sagen.
Gucke nämlich schon seit 3 Tagen drüber und bin irgendwie zu blind um es zu sehen.
Danke schonmal.
Hier der Quelltext:
Der Parser
Die Klasse Ausdruck
Die Klasse OperatorAusdrucl
Die Klasse Konstante
Die Klasse Variable
Die Klasse Variablenbelegung
Und der Parser Test
Danke nochmal.....
ich soll für die FH einen Mathe Parser schreiben, ich habe vier Testfälle, Exceptions für ungültige Ausdrücke wollte ich erst schreiben wenn die gültigen Funktionieren, die ersten drei Testfälle funktionieren auch, aber das letzte Funktioniert nicht.
Bei dem Ausdruck "1 + 2 * ( i + 2 * k - 1 ) / 2 + j" mit i = 3, k = 4 und j = 9 berechnet mein Parser 30, anstatt 20.
Vielleich kann jemand einmal drüber gucken und mir den Fehler sagen.
Gucke nämlich schon seit 3 Tagen drüber und bin irgendwie zu blind um es zu sehen.
Danke schonmal.
Hier der Quelltext:
Der Parser
Java:
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Klasse zum Parsen.
*
*/
public class Parser {
/** Arrayliste fuer die einzelnen Tokens. */
private ArrayList<String> tokenListe = new ArrayList();
/** Objekt der den vorherigen geparsten Ausdruck speichert */
private Ausdruck vorheriger;
/** Speichert das geparste Ergebnis */
private Ausdruck ergebnis;
/** Instantzvariable zum Speichern des Index */
private int parserIndex = 0;
/**
* Methode zum Parsen eines Ausdrucks.
*
* @param infixdarstellung Infixdarstellung die geparst werden soll.
*
* @return der geparste Ausdruck.
*/
public Ausdruck parse(String infixdarstellung) {
/* Initaliesiert die Arrayliste der einzelnen Tokens. */
initArrayListe(infixdarstellung);
/* Variable zum Speichern des geparsten Ausdruck */
Ausdruck geparsterAusdruck = null;
/*
* Durchläuft jedes Token solange der ParserIndex kleiner
* der groeße der TokenListe ist.
*/
while(parserIndex < tokenListe.size()) {
geparsterAusdruck = parseAusdruck(parserIndex);
vorheriger = geparsterAusdruck;
parserIndex++;
}
return geparsterAusdruck;
}
/**
* Parst einen Summand oder eine Folge von Summanden die mit '+'
* oder '-' verbunden sind.
*
* @return geparster Ausdruck fuer Summanden.
*/
private Ausdruck parseAusdruck(int index) {
ergebnis = parseSummand(index);
if (tokenListe.get(index).equalsIgnoreCase("+")) {
parserIndex++;
ergebnis = new OperatorAusdruck
(vorheriger, '+',
parseAusdruck(index + 1));
}
else if (tokenListe.get(index).equalsIgnoreCase("-")) {
parserIndex++;
ergebnis = new OperatorAusdruck
(vorheriger, '-',
parseAusdruck(index + 1));
}
return ergebnis;
}
/**
* Parst einen Faktor oder eine Folge von Faktoren die mit '*'
* oder '/' verbunden sind.
*
* @return geparster Ausdruck fuer Faktoren.
*/
private Ausdruck parseSummand(int index) {
ergebnis = parseFaktor(index);
if (tokenListe.get(index).equalsIgnoreCase("*")) {
parserIndex++;
ergebnis = new OperatorAusdruck
(vorheriger, '*',
parseAusdruck(index + 1));
}
else if (tokenListe.get(index).equalsIgnoreCase("/")) {
parserIndex++;
ergebnis = new OperatorAusdruck
(vorheriger, '/',
parseAusdruck(index + 1));
}
return ergebnis;
}
/**
* Parst eine Konstante, eine Variable oder Klammerausdruecke.
*
* @return geparster Ausdruck fuer Variablen oder Konstanten.
*/
private Ausdruck parseFaktor(int index) {
/* Regulaerer Ausdruck fuer Klammer auf. */
Pattern klammerAuf = Pattern.compile("\\(");
//Matcher fuer dem Regulaeren Ausdruck Klammer auf.
Matcher matcherklammerAuf = klammerAuf.matcher(tokenListe.get(index));
/* Das gleiche fuer die Klammer zu. */
Pattern klammerZu = Pattern.compile("\\)");
//Matcher fuer dem Regulaeren Ausdruck Klammer zu.
Matcher matcherklammerZu = klammerZu.matcher(tokenListe.get(index));
/* Regulaerer Ausdruck fuer Zahlen. */
Pattern zahlen = Pattern.compile("[0-9]+");
//Matcher fuer dem Regulaeren Ausdruck Zahlen.
Matcher matcherzahlen = zahlen.matcher(tokenListe.get(index));
/* Regulaerer Ausdruck fuer Zahlen. */
Pattern variablen = Pattern.compile("[a-z]+");
//Matcher fuer dem Regulaeren Ausdruck Zahlen.
Matcher matchervariablen = variablen.matcher(tokenListe.get(index));
if (matcherklammerAuf.find() == true) {
parserIndex++;
ergebnis = parseAusdruck(parserIndex);
}
if (matcherklammerZu.find() == true) {
if (parserIndex < tokenListe.size()) {
parserIndex++;
ergebnis = parseAusdruck(parserIndex);
}
}
if (matcherzahlen.find() == true) {
ergebnis = new Konstante(Integer.parseInt(tokenListe.get(index)));
}
if (matchervariablen.find() == true) {
ergebnis = new Variable(tokenListe.get(index));
}
return ergebnis;
}
/**
* Initaliesiert die Liste aller Tokens.
*/
private void initArrayListe(String infixdarstellung) {
java.util.StringTokenizer st =
new java.util.StringTokenizer(infixdarstellung, " ");
while(st.hasMoreTokens()) {
tokenListe.add(st.nextToken());
}
}
}
Die Klasse Ausdruck
Java:
/**
* Oberklasse Ausdruck, die alles Ausdruecke repraesentiert.
*
*/
public abstract class Ausdruck {
/**
* Abstrakte Methode, die den Wert dieses Ausdrucks
* basierend auf der Variablenbelegung liefert.
*
* @return Wert der zuruekgegeben wird.
*/
public abstract int gibWert(Variablenbelegung variablenbelegung);
}
Die Klasse OperatorAusdrucl
Java:
/**
* Klasse zur Darstellung eines Operationsausdrucks.
*
*/
public class OperatorAusdruck extends Ausdruck {
/** Erzeugt einen neuen Ausdruck. */
private Ausdruck linkerAusdruck;
/** Erzeugt einen neuen Ausdruck. */
private Ausdruck rechterAusdruck;
/** Erzeugt ein neues char zeichen. */
private char operator;
/**
* Erzeugt ein Objekt dieser Klasse für die angegebenen Daten.
*
* @param linkerAusdruck Wert des ersten Ausdrucks.
* @param operator Wert des char Zeichen.
* @param rechterAusdruck Wert des zweiten Ausdrucks.
*/
public OperatorAusdruck(Ausdruck linkerAusdruck, char operator,
Ausdruck rechterAusdruck) {
this.linkerAusdruck = linkerAusdruck;
this.rechterAusdruck = rechterAusdruck;
this.operator = operator;
}
@Override
/**
* Prueft, ob zwei Operatorausdruecke gleich sind.
*
* @param obj ein beliebiges Objekt
* @return <code>true</code> genau dann, wenn das uebergebene Objekt
* denselben Wert repraesentiert wie dieses Objekt.
*/
public boolean equals(Object obj) {
boolean istGleich = false;
if (obj instanceof OperatorAusdruck) {
OperatorAusdruck operatorAusdruck = (OperatorAusdruck) obj;
istGleich =
operatorAusdruck.linkerAusdruck.equals(this.linkerAusdruck)
&& operatorAusdruck.rechterAusdruck.equals(this.rechterAusdruck)
&& operatorAusdruck.operator == this.operator;
}
return istGleich;
}
@Override
/**
* Methode, die den Wert des Operatorausdrucks zurueck gibt.
*
*/
public int gibWert(Variablenbelegung variablenbelegung) {
int ergebnis = 0;
switch(operator) {
case '+':
ergebnis = linkerAusdruck.gibWert(variablenbelegung) +
rechterAusdruck.gibWert(variablenbelegung);
break;
case '-':
ergebnis = linkerAusdruck.gibWert(variablenbelegung) -
rechterAusdruck.gibWert(variablenbelegung);
break;
case '*':
ergebnis = linkerAusdruck.gibWert(variablenbelegung) *
rechterAusdruck.gibWert(variablenbelegung);
break;
case '/':
ergebnis = linkerAusdruck.gibWert(variablenbelegung) /
rechterAusdruck.gibWert(variablenbelegung);
break;
}
return ergebnis;
}
}
Die Klasse Konstante
Java:
/**
* Klasse zur Darstellung einer Konstante.
*
*/
public class Konstante extends Ausdruck {
/** Erzeugt eine neue Konstante. */
private final int wert;
/**
* Erzeugt ein Objekt dieser Klasse.
*
* @param wert Wert der Konstanten.
*/
public Konstante(int wert) {
this.wert = wert;
}
@Override
/**
* Prueft, ob zwei Objekte gleich sind.
*
* @param obj ein beliebiges Objekt
* @return <code>true</code> genau dann, wenn das uebergebene Objekt
* denselben Wert repraesentiert wie dieses Objekt
*/
public boolean equals(Object obj) {
boolean istGleich = false;
if (obj instanceof Konstante) {
Konstante konstante = (Konstante) obj;
if (konstante.wert == this.wert) {
istGleich = true;
}
}
return istGleich;
}
@Override
/**
* Methode, die den Wert der Konstante zurueck gibt.
*/
public int gibWert(Variablenbelegung variablenbelegung) {
return this.wert;
}
}
Die Klasse Variable
Java:
/**
* Klasse zur Darstellung einer Variable.
*
*/
public class Variable extends Ausdruck {
/** Variablennamen als String. */
private String name;
/**
* Erzeugt ein Objekt dieser Klasse für die angegebenen Daten.
*
* @param name Name der Variable.
*/
public Variable(String name) {
this.name = name;
}
@Override
/**
* Prueft, ob dieses Objekt gleich dem uebergebenen Objekt ist.
*
* @param obj ein beliebiges Objekt.
* @return <code>true</code> genau dann, wenn das uebergebene Objekt
* denselben Wert repraesentiert wie dieses Objekt.
*/
public boolean equals(Object obj) {
boolean istGleich = false;
if (obj instanceof Variable) {
Variable variable = (Variable) obj;
if (variable.name.equalsIgnoreCase(this.name)) {
istGleich = true;
}
}
return istGleich;
}
@Override
/**
* Methode, die den Wert der Variable zurück gibt.
*/
public int gibWert(Variablenbelegung variablenbelegung) {
return variablenbelegung.gibWert(this.name);
}
}
Die Klasse Variablenbelegung
Java:
import java.util.HashMap;
/**
* Klasse zum Belegen einzelner Variablen.
*
*/
public class Variablenbelegung {
private HashMap<String, Integer> map;
/**
* Erzeugt ein Objekt dieser Klasse.
*/
public Variablenbelegung() {
map = new HashMap();
}
/**
* Methode belge zum belegen der Variablen.
*
* @param name Name der Variable.
* @param wert Wert der Variable.
*/
public void belege(String name, int wert) {
map.put(name, wert);
}
/**
* Methode, die den Wert der Variable zurueck gibt.
*
* @param name Name der Variable.
*
* @return Wert der Variable.
*/
public int gibWert(String name) {
return map.get(name);
}
}
Und der Parser Test
Java:
import junit.framework.TestCase;
/**
* Testklasse fuer Methoden der Klasse Parser.
*
*/
public class ParserTest extends TestCase {
/** Erzeugt ein Parser. */
private Parser parser;
/** Erzeugt ein Variablenbelegungsobjekt. */
private Variablenbelegung variablenbelegung;
/**
* Erzeugt ein Objekt dieser Klasse
* mit dem angegebenen Namen.
*
* @param name Name dieses Tests
*/
public ParserTest(String name) {
super(name);
}
/**
* Testdaten aufbauen.
*/
protected void setUp() {
parser = new Parser();
variablenbelegung = new Variablenbelegung();
/* Erzeugt eine neue Variablenbelegung fuer i = 3. */
variablenbelegung.belege("i", 3);
/* Erzeugt eine neue Variablenbelegung fuer i = 3. */
variablenbelegung.belege("k", 4);
/* Erzeugt eine neue Variablenbelegung fuer i = 3. */
variablenbelegung.belege("j", 9);
}
/**
* Testet die Methode Parse in der KLasse Parser.
*/
public void testParse() {
/** Parst den Ausdruck "10". */
assertEquals(10 , parser.parse("10").gibWert(variablenbelegung) );
/** Parst den Ausdruck "7 + i" mit i = 3. */
assertEquals(10 , parser.parse("7 + i").gibWert(variablenbelegung));
/** Parst den Ausdruck "( i + 18 ) / 2".
* i = 3.
*/
assertEquals(10 , parser.parse("( i + 18 ) / 2")
.gibWert(variablenbelegung));
/* Parst den Ausdruck "1 + 2 * ( i + 2 * k - 1 ) / 2 + j".
* mit i = 3, k = 4 und j = 9.
*/
assertEquals(20, parser.parse("1 + 2 * ( i + 2 * k - 1 ) / 2 + j")
.gibWert(variablenbelegung));
}
/**
* Startet den Test.
*
* @param args wird nicht verwendet
*/
public static void main(String[] args) {
junit.textui.TestRunner.run(ParserTest.class);
}
}
Danke nochmal.....