Ob die Klammer richtig ist...

Terence86

Aktives Mitglied
Hi Leute habe ein paar Probleme mit folgender Aufgabe:
e2mh6vqo.jpg

Meine Idee war folgende: Scanner initialisieren.. ganze Line einlesen und dann überprüfen durch einen Zähler(Counter) ob die Anzahl der offenen Klammern mit der Anzahl der schließenden übereinstimmt. Fehlen würde mir die Beachtung der Reihenfolge, da zb. "}" + "{" auch gültige wären und die die Regel wenn sie zb. verschachtelt sind. Müsste ich ja die Positionen notieren wann diese vorkommen und ein Regel festlegen. Die Frage ist auch muss ich mit einem, ich nenns mal "offenen" Scanner (has.Next) das ganze angehen und jedes Token einzeln anschauen (mittels zb. while Schleife), oder wie ich gedacht hatte die ganzen Zeichenketten in einem String speichern und dann überprüfen? Oder vielleicht auch den Eingabe String als Array speichern und nach Klammern durchsuchen?
Was meinte er mit der Hilfsmethode? Die soll mir wenn ich einen gefundene offene Klammer finde, die schließende Klammer finden. Das würde nicht funktionieren wenn ich while (has.next) hätte da die Eingabe noch am laufen wäre. Ich tappe noch im Dunkeln vielleicht hat eine Idee oder weiß einen guten Hinweis.
 

Meniskusschaden

Top Contributor
Was meinte er mit der Hilfsmethode? Die soll mir wenn ich einen gefundene offene Klammer finde, die schließende Klammer finden. Das würde nicht funktionieren wenn ich while (has.next) hätte da die Eingabe noch am laufen wäre
Die Hilfsmethode soll die Zeichenketten bis zur nächsten schliessenden Klammer lesen. Wenn das die richtige Klammer ist, soll sie true liefern, andernfalls false. Bei einer öffnenden Klammer muß sie sich selbst mit passenden Parametern aufrufen und geeignet auf das Ergebnis reagieren. Deine ganzen Überlegungen mit Position notieren, Klammeranzahl etc. benötigst du nicht. Die Hilfsmethode ist im Grunde schon die vollständige Lösung.
 

Terence86

Aktives Mitglied
Ah also wird die Eingabe eingelesen bis eine öffnende Klammer kommt, und dann wird in der "hilfsMethode" weiter gelesen und geprüft ob die richtige schließende Klammer kommt oder nicht. D.h ich lese die Eingabe nicht komplett und speicher sie als String oder Array .. Richtig? Also Zeichenkette für Zeichenkette.
 

Terence86

Aktives Mitglied
Oha dann habe ich das auch mit der Verschachtelung ja in einem Abwasch?
So grad mal das Beispiel: ... { ... ( ... ) ... } ... "..." -> Zeichenkette.
Ablauf: ... { // Öffnende Klammer gefunden
-> Gibt "}" + Scanner weiter an hilfsMethode -> ... ( .... ) ... } -> Gefunden. Aber jetzt war doch vorher eine andere geschlossene Klammer, habe ich da grade einen Denkfehler gemacht? Oder läuft das anders ab? Sonst müsste ich doch in der Hilfsmethode noch sagen wenn eine neue geöffnete gefunden wird, das er dann erst diejenige schließende Klammer sucht oder nicht?
 

Terence86

Aktives Mitglied
Mhhh irgendwas stimmt nicht so ganz. Mein Code soweit:
Java:
    public static Boolean pruefeKlammern() {
        Scanner sc = new Scanner(System.in);
      
        while (sc.hasNext()) {
            String eingabe = sc.next();
            if (eingabe.equals("{")) {
                return hilfsMethode(sc, "}");
            }
            if (eingabe.equals("(")) {
                return hilfsMethode(sc, ")");
            }
            if (eingabe.equals("[")) {
                return hilfsMethode(sc, "]");
            }
          
        } sc.close();
        return false;

    }

    private static Boolean hilfsMethode(Scanner sc, String n) {
        String eingabe = sc.next();
        if (eingabe.equals(n)) {
            return true;
        }
        return hilfsMethode(sc, n);

    }
 

Terence86

Aktives Mitglied
Update:
Java:
    public static Boolean pruefeKlammern() {
        Scanner sc = new Scanner(System.in);

        while (sc.hasNext()) {
            String eingabe = sc.next();

            if (eingabe.equals("{")) {
                return hilfsMethode(sc, "}");
            }
            if (eingabe.equals("(")) {
                return hilfsMethode(sc, ")");
            }
            if (eingabe.equals("[")) {
                return hilfsMethode(sc, "]");
            }

        }
        return false;

    }

    private static Boolean hilfsMethode(Scanner sc, String n) {
        String eingabe = sc.next();
        if (eingabe.equals(n)) {
            return true;
        }
        else if (eingabe.equals("}") || eingabe.equals(")") || eingabe.equals("]")) {
            return false;
        }
        if (eingabe.equals("{")) {
            return hilfsMethode(sc, "}");
        }
        if (eingabe.equals("(")) {
            return hilfsMethode(sc, ")");
        }
        if (eingabe.equals("[")) {
            return hilfsMethode(sc, "]");
        }
        return hilfsMethode(sc, n);

    }
 

Meniskusschaden

Top Contributor
Wofür brauchst du denn die pruefeKlammern-Methode? Ich würde die Hilfsmethode direkt aus der main-Methode aufrufen. Da ist bei dir doch irgendwie dieselbe Logik doppelt implementiert.

Ausserdem verarbeitest du in der Hilfsmethode nur eine Zeichenkette. Das würde nur funktionieren, wenn nach einer öffnenden Klammer sofort eine schließende kommt. Es kann aber auch mal etwas dazwischen stehen.

Das:
Java:
if (eingabe.equals("{")) {
  return hilfsMethode(sc, "}");
}
kannst du nicht so machen, denn dann würdest du ja auch dann aus der aktuellen Ebene herausspringen, wenn in der gerade untersuchten tieferen Ebene kein Fehler gefunden wurde. In dem Fall musst du aber noch bis zur passenden Klammer der aktuellen Ebene weiter lesen.
 

Terence86

Aktives Mitglied
Ja das mit der doppelten Implementierung hatte ich auch schon gemacht. Habe nur den Scanner initialisiert da ich den zum Übergeben brauche und dann die hilfsMethode aufgerufen. Ja mein Problem das ich noch zu lösen hatte dachte ich wäre genau das : ... ( ... { ... } .. ) .. , da springt er nach der Geschlossenen raus ohne die letzte Klammer überprüft zu haben.
Ausserdem verarbeitest du in der Hilfsmethode nur eine Zeichenkette.
Meine Klammern als Zeichenketten, oder alle Token von der Eingabe? Dann müsste ich ja anders vorgehen.
Das:
kannst du nicht so machen, denn dann würdest du ja auch dann aus der aktuellen Ebene herausspringen, wenn in der gerade untersuchten tieferen Ebene kein Fehler gefunden wurde.
Wie realisiere ich den das? Sobald eine neue geöffnete Klammer vorkommt muss ich doch erst diese überprüfen. Sonst wäre das ja auch richtig ... [ .. (... ] ...) ..
 
Zuletzt bearbeitet:
X

Xyz1

Gast
Mal schnell, wie es mit einem Stack funktionieren würd:
Java:
    public static void main(String[] args) throws IOException {
        System.out.println(klammern(" a { b ( c ) d { e [ f ] g ( h ) i } j } k "));
        System.out.println(klammern(" a { b ( c ) d { e{ [ f ] g ( h ) i } j } k "));
    }

    static boolean klammern(String s) {
        LinkedList<String> stack = new LinkedList<>();
        for (char c : s.toCharArray()) {
            String cs = String.valueOf(c);
            if ("{([".contains(cs)) {
                stack.add(cs);
            } else {
                String cs2 = null;
                switch (cs) {
                    case "}":
                        cs2 = "{";
                        break;
                    case ")":
                        cs2 = "(";
                        break;
                    case "]":
                        cs2 = "[";
                        break;
                }
                if (cs2 != null) {
                    if (stack.getLast().equals(cs2)) {
                        stack.removeLast();
                    } else {
                        return false;
                    }
                }
            }
        }
        return stack.isEmpty();
    }

IDE ist aber auch nicht dumm und markiert das:

ide.PNG

o_O
 

Meniskusschaden

Top Contributor
Ausserdem verarbeitest du in der Hilfsmethode nur eine Zeichenkette.
Meine Klammern als Zeichenketten, oder alle Token von der Eingabe? Dann müsste ich ja anders vorgehen.
Die Hilfsmethode verarbeitet alle Zeichenketten bis zur nächsten schliessenden Klammer. Für die Zeichenketten der tieferen Ebenen (inklusive zugehöriger schliessender Klammern) tut sie es, indem sie die Hilfsmethode nochmals aufruft, für die Zeichenketten der eigenen Ebene erledigt sie es selbst.
Das:
kannst du nicht so machen, denn dann würdest du ja auch dann aus der aktuellen Ebene herausspringen, wenn in der gerade untersuchten tieferen Ebene kein Fehler gefunden wurde.
Wie realisiere ich den das?
Indem du abhängig vom Rückgabewert der Hilfsmethode entweder raus springst oder weiter liest.
Sobald eine neue geöffnete Klammer vorkommt muss ich doch erst diese überprüfen. Sonst wäre das ja auch richtig ... [ .. (... ] ...) ..
Das erledigst du durch erneutes Aufrufen der Hilfsmethode.
 
X

Xyz1

Gast
Mal schnell eine Frage... ich finde die Aufgabe gar nicht so leicht (zu verstehen)... Wenn man den stack oben als Klassen- oder Objektvariable schreiben würd, wäre diese Aufgabe damit dann gelöst?
 

Meniskusschaden

Top Contributor
Bin mir nicht ganz sicher, ob die Hinweise der Aufgabenstellung als Tipps oder als Vorgaben zu verstehen sind. Ich glaube eher Letzteres und dann wäre eine rekursive Lösung nötig.
 
X

Xyz1

Gast
Nagut, recursive method calls bilden aber (quasi) einen Stack ab (JVM internals), wäre nun die Frage, wie man das nun umsetzt.
Also mich verwirrt diese Aufgabe schon etwas. Ich warte einfach mal Lösung(en) ab. :)
 

Terence86

Aktives Mitglied
Habe das ganze nun so gelöst wurde auch angenommen:
Java:
public class Eingabe {

    public static Boolean pruefeKlammern() {
        Scanner sc = new Scanner(System.in);

        return hilfsMethode(sc, null);

    }

    private static Boolean hilfsMethode(Scanner sc, String n) {

        while (sc.hasNext()) {

            String eingabe = sc.next();
            if (eingabe.equals(n)) {
                return true;
            }
            if (eingabe.equals("{")) {
                if(!hilfsMethode(sc, "}"))
                        return false;
            }
            if (eingabe.equals("(")) {
                if(!hilfsMethode(sc, ")"))
                    return false;
            }
            if (eingabe.equals("[")) {
                if(!hilfsMethode(sc, "]"))
                    return false;
            }

            if (eingabe.equals("}") || eingabe.equals(")") || eingabe.equals("]")) {
                return false;
            }
            //return hilfsMethode(sc, n);
        }
        if(n==null)
            return true;
        else
        return false;

    }

Habe ich was nicht Bedacht? Morgen werden verschiedene Tests noch durchgeführt.(nach Abgabe Termin)
 

Meniskusschaden

Top Contributor
Ich finde, das sieht gut aus. Unter dem Leerstring, der im Hinweis zum ursprünglichen Aufruf erwähnt wird, hätte ich allerdings nicht null sondern "" verstanden. Das könnte unter Umständen kritisiert werden.
 

Terence86

Aktives Mitglied
Ist schon spät aber habe null durch "" ersetzt, da bekam ich ein Fehler :
Code:
return hilfsMethode(sc, "");
Fehler:
Code:
PreTest...

testPruefeKlammern1:
Eingabe von:
--------------------------------
public class Hi {
public static void main ( String [ ] args ) {
System.out.println ( "Hi!" ) ;
}
}
--------------------------------
ueber System.in
FEHLER: zuletzt erwarteter und tatsächlich erhaltener Wert unterscheiden sich
erwartet wurde: true
erhalten wurde: false

testPruefeKlammern2:
OK
testPruefeKlammern3:
OK
testPruefeKlammern4:
OK
testPruefeKlammern5:
OK
testPruefeKlammern6:
OK
testPruefeKlammern7:
OK

...PreTest fehlgeschlagen :-(
 

Neue Themen


Oben