# "String ausführen" ? --> ähnliches wie eval() ?



## Sladda (18. Jun 2008)

Hallo!

Ich habe einen String, zB: "true && (false || !true)"  .
Kann ich den irgendwie "ausführen" ? d.h. ich bräuchte eine Funktion, die diesen String als Param bekommt und mir n boolean zurückgibt, hier also false. 
Gibt es so eine Funktion schon? 
Wenn nicht, hat jemand eine Idee wie man sich das schreiben könnte? Ein kleiner Tip würde mir schon reichen.

Vielen Dank
mfg
Sladda


----------



## SlaterB (18. Jun 2008)

hier gibts einen Parser für mathematische Formeln:
http://www.java-forum.org/de/viewtopic.php?t=13378

da müsstest du etwas die Operatoren und Rückgabewerte ändern (boolean statt double)
dann gehts vielleicht recht schnell


----------



## Sladda (18. Jun 2008)

ui ui ui... ob ich es da hinkriege irgendwas zu ändern so dass das dann funktioniert...

ich habe mir grad folgendes überlegt, was aber noch nicht so dolle ist:

ich mache mir einfach ein Object-Array, in das ich nach und nach die bestandteile reinlese. die werte, true und false, kann man ja ganz einfach dann schon als Boolean in dem Array speichern. die hätte ich dann also schon mal (sogar an der richtigen stelle) jetzt muss ich nur noch die Operationen (&&, ||, !) und die Klammern, die ich ja auch einzeln als String in das Array schreiben kann, irgendwie in den logischen Ausdruck reinbringen, sodass der ausgewertet werden kann... 
hmmm... naja, eigentlich bin ich damit dann wieder am anfang...


----------



## diggaa1984 (18. Jun 2008)

wir ham das immer super über bäume gelöst im studium 
is aber eben auch aufwendig wenn man bei 0 anfangen muss, bissel mathematik wirst da schon brauchen


----------



## Sladda (24. Jun 2008)

hi ich bin es wieder... 
ich habe nun verzweifelt versucht einen solchen Parser zu schreiben für meine boolschen Terme, leider scheitere ich wohl an der richtigen Umsetzung der Rekursion:


```
private static String evaluate(String expr, int begin){
						
			if (isSimpleTerm(expr)) //simpler Termin ist z.B. true&false  --> RekursionsAnker
				return(reduce(expr));
			
			for (int i =begin;i<expr.length();i++){
				if (expr.charAt(i) == '(') 
                expr = Misc.replaceSubstring(expr,begin-1,i,evaluate(expr, i+1)); //rekursiver aufruf, entfernt gleich die Klammern mit und schreibt den ausgewerten wert an die Stelle in expr wo vorher der einfache Term stand					
				
				if (expr.charAt(i) == ')')    //Teilstring ohne innere Klammern gefunden, kann also sofort ausgewertet und ersetzt werden:						
					return reduce(expr.substring(begin, i));
				
							}
			return expr;
		}
		
		public static String evaluate(String expr){
			//leerzeichen entfernen: 
			expr = expr.replaceAll(" ", "");
			return evaluate(expr,0);
		}
		
			
	public static void main(String[] args) {
			
			System.out.println(evaluate("(true & false |(true & true))"));
	}
```

und die reduce Methode, die einen boolschen Term ohne Klammer (z.B. true | false & true) auswertet und den entsprechenden String zurück gibt:

```
/**
*     reduce rechnet einen einfachen boolschen Term ohne Klammern (zB false | false & true) aus und gibt das ergebnis als String zurück
*/
public static  String reduce(String s){
		//zunächst zählen wie viele Operatoren und Operanden es gibt:
		int countOperators=0;
		for (int c = 0; c<s.length();c++){
			if (s.charAt(c) == '&'   ||  s.charAt(c)=='|')
				countOperators++;
		}
		//evtl. vorhandene Leerzeichen entfernen:
		s = s.replaceAll(" ","");
		//System.out.println(s);
		
		if (countOperators==0) return s; // anker;
		
		boolean [] bValues = new boolean[2];
		String operator="";
		int charactersToDelete = 0;
		int bValuesFilled = 0;
		//die ersten beiden boolschen Werte parsen und in Array in der richtigen Reihenfolge ablegen:
		for (int i =0;i<s.length();i++){
			if(s.charAt(i) == 't') {
				bValues[bValuesFilled]=true;
				bValuesFilled++;
				i = i+4;
				charactersToDelete+=4;
				if (bValuesFilled > 1) break;
			}
			if (s.charAt(i) == 'f'){
				bValues[bValuesFilled]=false;
				bValuesFilled++;
				i = i+5;
				charactersToDelete+=5;
				if (bValuesFilled > 1) break;
			}
			if (s.charAt(i)=='&'){
				operator="&";
				charactersToDelete++;
			}
			if (s.charAt(i)=='|'){
				operator="|";
				charactersToDelete++;
			}
		}
		// jetzt "ausrechnen":
		if (operator.equals("&"))
			return reduce((bValues[0]&& bValues[1]) +s.substring(charactersToDelete));
		else
			if (operator.equals("|"))
				return reduce((bValues[0]|| bValues[1]) +s.substring(charactersToDelete));
			else
				throw new RuntimeException("reduce: operator '"+operator+"' undefined");
		
	}
```

Kann mir jemand bei der evaluate-methode vielleicht einen Tip geben, wie ich das am schlausten ändere ?
die reduce methode funktioniert wunderbar für einfache Terme...
Das würde mir SEHR helfen!
Vielen Dank und Grüße
Sladda


----------



## OceanDriver (25. Jun 2008)

Ich glaube du machst es dir viel zu kompliziert!

Sind das wirklich nur so einfache boolsche Ausdrücke mit true, false  und eventuellen Vergleichen? Dann sollte das schon reichen:


```
public static boolean testBoolean(String param)
    {
        return new Boolean(param);
    }
```


Der funktioniert ohne Probleme mit  Ausdrücken wie:  "5 > 3 && !false && true! "


----------



## SlaterB (25. Jun 2008)

was ist das denn für ein überzeugender Aprilscherz?

hast du eine andere Boolean-Klasse als ich? 

```
/**
     * Allocates a <code>Boolean</code> object representing the value 
     * <code>true</code> if the string argument is not <code>null</code> 
     * and is equal, ignoring case, to the string <code>"true"</code>. 
     * Otherwise, allocate a <code>Boolean</code> object representing the 
     * value <code>false</code>. Examples:


     * <tt>new&Boolean("True")</tt> produces a <tt>Boolean</tt> object 
     * that represents <tt>true</tt>.

     * <tt>new&Boolean("yes")</tt> produces a <tt>Boolean</tt> object 
     * that represents <tt>false</tt>.
     *
     * @param   s   the string to be converted to a <code>Boolean</code>.
     */
    public Boolean(String s) {
	this(toBoolean(s));
    }


    private static boolean toBoolean(String name) { 
	return ((name != null) && name.equalsIgnoreCase("true"));
    }
```


----------



## tfa (25. Jun 2008)

OceanDriver hat gesagt.:
			
		

> Der funktioniert ohne Probleme mit  Ausdrücken wie:  "5 > 3 && !false && true! "


Aber nur, wenn der Ausdruck zufälligerweise _false_ ergibt. (Davon abgesehen sollte man den Boolean-Konstruktor niemals verwenden sondern valueOf.


----------



## OceanDriver (25. Jun 2008)

Ich weiß gerade nicht was du von mir willst ^^

funktioniert doch? Du hast doch auch den Konstruktor der nen String annimmt ^^


----------



## OceanDriver (25. Jun 2008)

Also bei mir funktioniert das auch mit Ausdrücken die wahr (true) sind, hier mal ein Beispiel:

true && !false && 5 > 3 


 --> true


----------



## SlaterB (25. Jun 2008)

du musst ganz gewiss eine besondere Java-Version haben


----------



## tfa (25. Jun 2008)

Von welcher Sprache reden wir hier? Java?

```
public class BooleanTest  {
    public static void main(String... args) {
        System.out.println(new Boolean("true && !false && 5 > 3"));
    }
}
```
-> false


----------



## Gast (25. Jun 2008)

gut den konstruktor intessiert wohl wirklich nur der erste ausdruck ^^


----------



## SlaterB (25. Jun 2008)

nein, auch nicht den, sondern den Gesamtstring..


----------



## tfa (26. Jun 2008)

Jedenfalls ein nettes Beispiel für eine völlig kaputte Implementierung in der Standard-API.


----------



## ARadauer (26. Jun 2008)

hab mir das jetzt nicht alles durchgelesen, ich hab einen anderen ansatz für sowas.

man kann scripstsprachen in java einbinden (zb javascript)
in javascript gibt es sowas wie eval, voila!

http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html


----------



## ARadauer (26. Jun 2008)

wow geil, das funktioniert ja wirklich!


```
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Test {
    public static void main(String[] args) throws Exception {
        // create a script engine manager
        ScriptEngineManager factory = new ScriptEngineManager();
        // create a JavaScript engine
        ScriptEngine engine = factory.getEngineByName("JavaScript");
        // evaluate JavaScript code from String           
        
        engine.eval("var b = eval('true && !false && 5 < 3')");        
        Boolean b =(Boolean) engine.get("b");

        System.out.println(b);
    }
}
```


----------

