Stack mit bestimmter Aufgabe

Heinrich500

Bekanntes Mitglied
Hallo,
ich will mittels eines Stacks eine Klasse implementieren, die die Korrektheit eines Klammerausdrucks überprüft. Das Programm bekomt dabei als Programmargument den Pfad einer Textdatei übergeben. Das erste Problem ist jetzt schon, wie ich auf diese Textdatei dann zugreifen könnte. Hier mein Versuch:
Java:
public class Klammern {

    public static boolean rightBrackets(String s) {
        Stack<Character> stack  = new Stack<Character>();
        for(int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if(c == '[' || c == '(' || c == '{' ) {     
                stack.push(c);
            } else if(c == ']') {
                if(stack.empty() || stack.pop() != '[') {
                    return false;
                }
            } else if(c == ')') {
                if(stack.empty() || stack.pop() != '(') {
                    return false;
                }           
            } else if(c == '}') {
                if(stack.empty() || stack.pop() != '{') {
                    return false;
                }
            }

        }
        return stack.empty();
    }

    
    
    
    
    public static void main(String[] args) {
        String path = args[0];
        File CP_file = new File(path);
        
        //Wie übergebe ich meiner Methode jetzt die Textdatei?
      
      
    }
 

Heinrich500

Bekanntes Mitglied
Also dann so:
Java:
           String path = args[0];
        File CP_file = new File(path);
        FileReader fr = new FileReader(CP_file);
Das funktioniert leider nicht und ich wüsste auch nicht, wie ich das in einen String umwandeln könnte?
 

Heinrich500

Bekanntes Mitglied
Ich verstehe leider nicht alle Anweisungen mihe. Würde es vllt auch so gehen:
Java:
 String path = args[0];
       File CP_file = new File(path);
       BufferedReader in = new BufferedReader (new FileReader (CP_file) );
       String ausgabe=in.readLine()    ;
 

mihe7

Top Contributor
Ja, damit liest Du eine Zeile ein, wobei Du in dem Fall try-with-resources verwenden solltest, damit der Reader auch wieder geschlossen wird:
Java:
try(BufferedReader in = new BufferedReader(new FileReader (CP_file))) {
    String line = in.readLine();
    verarbeite(line);
}
Um alle Zeilen der Datei zu behandeln, packt man das in eine Schleife:
Java:
try(BufferedReader in = new BufferedReader(new FileReader (CP_file))) {
    String line;
    while ((line = in.readLine()) != null) {
        verarbeite(line);
    }
}
Natürlich kann man erst alle Zeilen einlesen, z. B. in eine Liste und dann über die Liste iterieren:
Java:
List<String> lines = new ArrayList<>();
try(BufferedReader in = new BufferedReader(new FileReader (CP_file))) {
    String line;
    while ((line = in.readLine()) != null) {
        lines.add(zeile);
    }
}

for (String line : lines) {
    verarbeite(line);
}
Und den ersten Teil kann man mit Hilfe von java.nio.file.Files kurz schreiben:
Java:
List<String> lines = java.nio.file.Files.readAllLines(CP_file.toPath());

for (String line : lines) {
    verarbeite(line);
}
Alles klar?
 

Heinrich500

Bekanntes Mitglied
List<String> lines = new ArrayList<>(); try(BufferedReader in = new BufferedReader(new FileReader (CP_file))) { String line; while ((line = in.readLine()) != null) { lines.add(zeile); } } for (String line : lines) { verarbeite(line); }
Alles klar. Das zeile müsste dann doch line sein oder?

Wie könnte ich mit meinem Stack die Positionen des zusammengehörigen Klammerpaares ausgeben?
 

mihe7

Top Contributor

Heinrich500

Bekanntes Mitglied
Ich habe eine Methode vorgegeben, die folgendes macht:
Die Methode erhält als Parameter die Zeile und Spalte der öffnenden undschließenden Klammern sowie die Klammern selbst als Zeichen. Dies führt zu eine runseren Testfällen genügenden Ausgabe wie z. B.:Matching brackets: ’[’ at line 1, column 10 and ’]’ at line 1, column 11

Dann muss ich mir ja auch noch merken, in welcher Zeile die Klammer steht.
Wie merke ich mir die Zeile und Spalte.
Kannst du mir da noch einen Tipp geben?
 

Heinrich500

Bekanntes Mitglied
Ja dürfen sie:
Z.b gibt es folgende Ausgabe:
Matching·brackets:·'{'·at·line·1,·column·16·and·'}'·at·line·3,·column·1
Also kann ich mein obiges Programm nicht verwenden?
Könntest du vllt den Anfang von deiner Idee zeigen bitte?
Vllt würde ich es dann besser verstehen.
 

mihe7

Top Contributor
Du willst Dir die Zeile und die Spalte eines Zeichens sowie das Zeichen selbst merken:
Java:
class CharacterPosition {
    public final int row;
    public final int col;
    public final char character;

    public CharacterPosition(int row, int col, char character) {
        this.row = row;
        this.col = col;
        this.character = character;
    }
}

Statt einfach nur ein '{' auf den Stack zu legen, verwendest Du also ein Objekt vom Typ CharacterPosition. Die Zeilen und Spalten kannst Du in den Schleifen mitzählen.
 

Heinrich500

Bekanntes Mitglied
Aso vielen Dank:)
Was mir gerade noch leider erst jetzt auffällt, muss ich alles in einer Klasse machen.
Geht es theoretisch die class CharacterPosition mit in die Klasse Klammer einzubetten?
 

mihe7

Top Contributor
Naja, Du hast die Zeilen ja jetzt in einer Liste und die ist "nummeriert":
Java:
for (int row = 0, n = lines.size(); row < n; row++) {
    String line = lines.get(row);
}
row ist der Zeilenindex, die Zeilennummer (für die Ausgabe) wäre dann row+1.
 

mihe7

Top Contributor
Wie meinst Du das? Du gehst ja Zeile für Zeile und jede Zeile Zeichen für Zeichen durch. Wenn Du auf eine öffnende Klammer stößt, kennst Du also Zeile (row), Spalte (col) und das Zeichen (ch) mit der öffnenden Klammer. Dann legst Du ein new CharacterPosition(row, col, ch) auf den Stack.

Stößt Du auf eine schließende Klammer, kennst Du wieder die Zeile (row), Spalte (col) und das Zeichen (ch) mit der schließenden Klammer. Auf dem Stack liegt ggf. die CharacterPosition der öffnenden Klammer.
 

Heinrich500

Bekanntes Mitglied
Ok ja jetzt habe ich es. Man geht ja hier die Zeilen entlang:
Java:
for (String line : lines) {
            verarbeite(line);
        }

Das Problem ist, dass ich die Methoden mit Objekten nicht ausführen kann, z.b ist push so implementiert:
Java:
public void push(T t) {
        
        StackNode<T> tmp=new StackNode<T>(t);
        tmp.next=topElement;
        topElement=tmp;
        counter++;
    }

Wie kann man das dann machen?
 

mihe7

Top Contributor
Ich weiß nicht, was Du hier betreibst:
Java:
import java.util.*;

public class Klammern {
    static class CharacterPosition {
        public final int row;
        public final int col;
        public final char character;

        public CharacterPosition(int row, int col, char character) {
            this.row = row;
            this.col = col;
            this.character = character;
        }
    }

    public static void process(List<String> lines) {
        Stack<CharacterPosition> positions = new Stack<>();
        for (int row = 0, n = lines.size(); row < n; row++) {
            String line = lines.get(row);
            for (int col = 0, m = line.length(); col < m; col++) {
                char ch = line.charAt(col);
                if (ch == '(') {
                    positions.push(new CharacterPosition(row, col, ch));
                }
            }
        }

        while (!positions.isEmpty()) {
            CharacterPosition pos = positions.pop();
            System.out.printf("%c gefunden in Zeile %d, Spalte %d\n", pos.character, pos.row+1, pos.col+1);
        }
    }

    public static void main(String[] args) {
        List<String> lines = Arrays.asList(
            "Dies ist ein Beispiel (wirklich), das zeigt, ",
            "dass Positionen (Zeilen und Spalten) von Klammern ",
            "ausgegeben werden");
        Klammern.process(lines);
    }
}
 

Heinrich500

Bekanntes Mitglied
Ich bin selber etwas verwirrt. Vielen Dank für dein Programm. Jetzt muss ich noch einbauen, dass Klammerpaare erkannt werden. Solte man dazu die while-Schleife entfernen und nach dem
Java:
 if(ch=='('))
folgendes einbauen:
Java:
else if(c == ')') {
                if(!stack.empty() && stack.pop() == '(') {
                printMatch(row, col, ch)
                }
 

Heinrich500

Bekanntes Mitglied
Java:
 public static void process(List<String> lines) {
        Stack<CharacterPosition> positions = new Stack<>();
        for (int row = 0;row <  lines.size(); row++) {
            String line = lines.get(row);
            for (int col = 0, m = line.length(); col < m; col++) {
                char ch = line.charAt(col);
                if (ch == '(' || ch == '[' || ch == '{' ) {
                    positions.push(new CharacterPosition(row, col, ch));
                }
                else if(ch == ']') {
                    if(!positions.empty() || positions.pop() != '[') {
                       Printall(row,col,ch);
                    }
                }
                else if(ch == ')') {
                    if(!positions.empty() || positions.pop() != '(') {
                        Printall(row,col,ch);
                    }           
                }
                else if(ch == '}') {
                    if(!positions.empty() || positions.pop() != '{') {
                        Printall(row,col,ch);
                    }
                }
            }   
        }     
        

      
    }

Das Problem ist, dass
Java:
positions.pop() != '[')
nicht funktioniert. Folgender Fehler:
Incompatible operand types Klammer.CharacterPosition and char
Wie kann ich das lösen?
 

mihe7

Top Contributor
positions.pop() liefert ein Objekt vom Typ CharacterPosition. Daher musst Du mit den Methoden/Attributen dieses Typs arbeiten:
Java:
CharacterPosition p = positions.pop();
if (p.character == '}') {
...
}
 

Heinrich500

Bekanntes Mitglied
Ist nicht so schön wsl, aber wäre das dann insgesamt korrekt:
Java:
  if (ch == '(' || ch == '[' || ch == '{' ) {
                    positions.push(new CharacterPosition(row, col, ch));
                }
              
                else if(ch == ']') {
                    CharacterPosition p = positions.pop();
                    if(!positions.empty() && p.character == ']') {
                       Printall(row,col,ch);
                    }
                }
                else if(ch == ')') {
                    haracterPosition p = positions.pop();
                    if(!positions.empty() && p.character == ')') {
                        Printall(row,col,ch);
                    }           
                }
                else if(ch == '}') {
                    CharacterPosition p = positions.pop();
                    if(!positions.empty()&& p.character == '}') {
                        Printall(row,col,ch);
                    }
 

Heinrich500

Bekanntes Mitglied
Oh man. Tut mir leid. Also dann wäre es doch beispielhaft so:
Java:
 else if(ch == ']') {
                    
                    if(!positions.empty()) {
                        CharacterPosition p = positions.pop();
                        if(p.character == ']') {
                            Printall(row,col,ch);
                        }   
                    }
                }
 

Heinrich500

Bekanntes Mitglied
Danke:) In meiner main-Methode läuft das einlesen dann so:
Java:
String path = args[0];
        File CP_file = new File(path);
        BufferedReader in = new BufferedReader(new FileReader (CP_file));
             List<String> lines = new ArrayList<String>();
             String line;
             while ((line = in.readLine()) != null) {
                    lines.add(line);
             }
             CheckBracketExpressions.process(lines);
Wäre das ok. Ich bin mir nicht ganz sicher
 

Heinrich500

Bekanntes Mitglied
Vielen Dank.
Ich habe ja immer die printall-Methode verwendet. Jedoch brauche ich nicht nur 3 sondern 6 Parameter. Ich habe dann diese wie folgt implementiert:
Java:
 public static void printMatch(int rowL, int columnL, char leftBracket, int rowR, int columnR, char rightBracket) {
        System.out.println( "Matching brackets: '" + leftBracket+ "' at line " + rowL + ", column " + columnL
                + " and '" + rightBracket + "' at line " + rowR + ", column " + columnR );
    }

Wie füge ich die am besten nun in das Programm ein?
 

mihe7

Top Contributor
Jetzt schau Dir mal Deinen Code an:
Java:
                else if(ch == ']') {
                        CharacterPosition p = positions.pop();
                        if(p.character == ']') {
                            Printall(row,col,ch);
                        }
Wie Du siehst, hast Du: row, col, ch und... p. Dabei sind row, col, ch die Zeile, Spalte und das Zeichen der schließenden Klammer. In p findest Du die Angaben für die linke Klammer: p.col, p.row, p.character.

Da fällt mir auf, dass mir vorhin ein Fehler unterlaufen ist: die if-Bedingung muss natürlich die öffnende Klammer prüfen:
Java:
                else if(ch == ']') {
                        CharacterPosition p = positions.pop();
                        if(p.character == '[') {
                            Printall(row,col,ch);
                        }
 

Heinrich500

Bekanntes Mitglied
Vielen Dank. Es hat geklappt:)
Jetzt stimmen nur nicht die Indizes der Zeilen und Spalten.
Java:
lse if(ch == ']') {
                    
                    if(!positions.empty()) {
                        CharacterPosition p = positions.pop();
                        if(p.character == '[') {
                            printMatch(p.row,p.col,p.character, row, col,ch);
                        }   
                    }
                }
Müsste ich nicht row, col jeweils um 1 erhöhen?
 

mihe7

Top Contributor
Ja, row und col sind Indizes (beginnend bei 0). Für die Ausgabe der Spalten- und Zeilennummern musst du jeweils um 1 erhöhen: printMatch(p.row+1, p.col+1, p.character, row+1, col+1, ch);
 

Heinrich500

Bekanntes Mitglied
Es geht. Ich habe
if(p.character == ']') nicht verändert. Jetzt funktioniert es.
Es soll noch eine Fehlerbehandlung durchgeführt werden:
printUnmatchedClosingBracket: Erhält als Parameter die Zeile und Spalte der gefundenen, schließenden Klammer, welche eingelesen wurde, obwohl der Stack leer ist.
Das habe ich dann wie folgt, umgesetzt:
Java:
else if(ch == ']') {
                   
                    if(!positions.empty()) {
                        CharacterPosition p = positions.pop();
                        if(p.character == '[') {
                            printMatch(p.row+1,p.col+1,p.character, row+1, col+1,ch);
                        }  
                    }
                    else {
                        printUnmatchedClosingBracket(row+1, col+1,ch);
                    }
                }
Jedoch scheint das nicht richtig zu sein, Wenn ich in den else Zweig komme, dann ist doch der Stack leer?
 

mihe7

Top Contributor
Es gibt zwei Fälle:
1. der Stack enthält z. B. ein '(', wenn Du auf ein ']' triffst: unmatched :)
2. der Stack ist leer, wenn Du auf eine schließende Klammer triffst.
 

mihe7

Top Contributor
Und: es gibt noch einen weiteren Fall. Wenn alle Zeilen verarbeitet wurden und der Stack nicht leer ist, dann hast Du öffnende Klammern, die nicht geschlossen wurden.
 

Heinrich500

Bekanntes Mitglied
1. der Stack enthält z. B. ein '(', wenn Du auf ein ']' triffst: unmatched
Ich muss das ja am Anfang z.b von
Java:
if else ch==']
prüfen.
Java:
else if(ch == ']') {
                    CharacterPosition x = positions.top();
                    if(x.character!='[') printUnmatchedClosingBracket(row+1, col+1,ch);
                    if(!positions.empty()) {
                        CharacterPosition p = positions.pop();
                        if(p.character == '[') {
                            printMatch(p.row+1,p.col+1,p.character, row+1, col+1,ch);
                        }   
                    }
                    else {
                        printUnmatchedClosingBracket(row+1, col+1,ch);
                    }
                }
Etwas redudant, was sagst du?
 

Heinrich500

Bekanntes Mitglied
Dann so:
Java:
lse if(ch == ']') {
                    
                    if(!positions.empty()) {
                        CharacterPosition p = positions.pop();
                        if(p.character == '[') {
                            printMatch(p.row+1,p.col+1,p.character, row+1, col+1,ch);
                        }
                        else {
                            printUnmatchedClosingBracket(row+1, col+1,ch);
                        }
                    }
                    else {
                        printUnmatchedClosingBracket(row+1, col+1,ch);
                    }
                }
Den letzen Fall weis ich nicht genau, wo ich den unterbringen soll,
 

mihe7

Top Contributor
Nach der Schleife:
Java:
while (!positions.empty()) {
    CharacterPosition p = positions.pop();
    printUnmatchedOpeningBracket(p.row+1, p.col+1, p.character);
}
 

Heinrich500

Bekanntes Mitglied
Funktioniert leider nicht ganz: Siehst du den Fehler?
Java:
public static void process(List<String> lines) {
        Stack<CharacterPosition> positions = new Stack<>();
        for (int row = 0;row <  lines.size(); row++) {
            String line = lines.get(row);
            
            for (int col = 0; col < line.length(); col++) {
                    char ch = line.charAt(col);
                
                
                if (ch == '(' || ch == '[' || ch == '{' ) {
                    positions.push(new CharacterPosition(row, col, ch));
                }
              
                else if(ch == ']') {
                    
                    if(!positions.empty()) {
                        CharacterPosition p = positions.pop();
                        if(p.character == '[') {
                            Main.printMatch(p.row+1,p.col+1,p.character, row+1, col+1,ch);
                        }
                        else {
                            Main.printUnmatchedClosingBracket(row+1, col+1,ch);
                        }
                    }
                    else {
                        Main.printUnmatchedClosingBracket(row+1, col+1,ch);
                    }
                }
                else if(ch == ')') {
                     if(!positions.empty()) {
                         CharacterPosition p = positions.pop();
                         if(p.character == '(') {
                             Main.printMatch(p.row+1,p.col+1,p.character, row+1, col+1,ch);
                         }
                         else {
                            Main.printUnmatchedClosingBracket(row+1, col+1,ch);
                        }
                     }
                     else {
                         Main.printUnmatchedClosingBracket(row+1, col+1,ch);
                     }
                }
                else if(ch == '}') {
                     if(!positions.empty()) {
                         CharacterPosition p = positions.pop();
                         if(p.character == '{') {
                             Main.printMatch(p.row+1,p.col+1,p.character, row+1, col+1,ch);
                         }
                         else {
                            Main.printUnmatchedClosingBracket(row+1, col+1,ch);
                        }
                     }
                     else {
                         Main.printUnmatchedClosingBracket(row+1, col+1,ch);
                     }
                }   
            } 
        }
        while (!positions.empty()) {
        CharacterPosition p = positions.pop();
        Main.printUnmatchedOpeningBracket(p.row+1, p.col+1, p.character);
        }
    }
 

Blender3D

Top Contributor
Vielen Dank.
Ich habe ja immer die printall-Methode verwendet. Jedoch brauche ich nicht nur 3 sondern 6 Parameter. Ich habe dann diese wie folgt implementiert:
Eigentlich genügen 2 Parameter.
Java:
public static void printMatch(CharacterPosition pOpen, CharacterPosition pClose) {
        System.out.println( "Matching brackets: '" + pOpen.character + "' at line " + pOpen.row + ", column " + pOpen.col
                + " and '" + pClose.character + "' at line " + pClose.row + ", column " + pClose.col );
    }
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
berserkerdq2 IJVM, ich tue auf meinen Stack 100 und 120 rein, danach subtrahiere ich, macht die Maschine 100-120 oder 120-100? Allgemeine Java-Themen 8
berserkerdq2 Kann man in IJVM maximal 3 Werte im Stack haben? Allgemeine Java-Themen 3
M Stack umdrehen Allgemeine Java-Themen 2
L Stack overflow bei einer endrekursiven Funktion (Anwendung: Spezialform des Package Merge) Allgemeine Java-Themen 4
S Collections Stack-Kapazität begrenzen Allgemeine Java-Themen 6
C Method Area, Stack, Heap Allgemeine Java-Themen 7
F Mehrere Threads - ein Stack Allgemeine Java-Themen 6
M Baum nach Stack plus Objektkonvertierung Allgemeine Java-Themen 5
V Performancefrage int-Vector/Stack Allgemeine Java-Themen 10
X Wie 'teuer' ist die Verwendung des Stack Trace ? Allgemeine Java-Themen 8
H Alternative zu Stack Allgemeine Java-Themen 3
G Java Logger ohne Stack Trace ausgaben. Allgemeine Java-Themen 2
V Unable to pop operand off an empty stack Allgemeine Java-Themen 2
P Funktionsweise von Stack- und Snakedatentypen? Code? Allgemeine Java-Themen 7
M Stack vergrößern? Allgemeine Java-Themen 7
R Entsprechung von Stack() im Collections Framework...? Allgemeine Java-Themen 4
izoards Bestimmter Text aus PDF extrahieren Allgemeine Java-Themen 3
C Koordinaten LONG/LAT eines neuen Punktes in bestimmter Entfernen und Winkel berechnen Allgemeine Java-Themen 3
J Message Box soll bei bestimmter Zeit angezeigt werden Allgemeine Java-Themen 19
N Java Robot Printscreen in bestimmter Konstellation Allgemeine Java-Themen 2
Bananabert Java mit bestimmter GPU ausführen Allgemeine Java-Themen 7
H Bestimmte Aufgaben zur bestimmter Zeit/ in bestimmten Intervallen Allgemeine Java-Themen 3
N Zahl mit bestimmter Länge und nur bestimmten Zahlen generieren lassen Allgemeine Java-Themen 7
J Bestimmter Buchstabe = bestimmte Zahl Allgemeine Java-Themen 10
S HTML-Quelltext nach bestimmter Stelle durchsuchen Allgemeine Java-Themen 2
M Klassen Array aus Klassen bestimmter Klassen ? Allgemeine Java-Themen 11
A Programm an bestimmter Stelle ausführen Allgemeine Java-Themen 5
M Nach bestimmter Namenskonvention filtern Allgemeine Java-Themen 2
C Problem beim einlesen bestimmter Seiten Allgemeine Java-Themen 5
T indexOf => bestimmter Bereich Allgemeine Java-Themen 26
G In Datei an bestimmter Stelle schreiben! Allgemeine Java-Themen 12
L 8 bytes von bestimmter position weg lesen? Allgemeine Java-Themen 11
T Objekt Array Aufgabe mit Busdatenbank Allgemeine Java-Themen 2
O Test schreiben mit Äquivalenzklassen (Aufgabe Prüfung) Allgemeine Java-Themen 9
OnDemand Erstellen von Quartz Jobs pro Aufgabe oder zusammenfassen Allgemeine Java-Themen 7
M Bräuchte Hilfe bei der Aufgabe Allgemeine Java-Themen 1
parrot Array Aufgabe Allgemeine Java-Themen 3
parrot Rekursion Aufgabe Allgemeine Java-Themen 12
S Aufgabe erwünscht Allgemeine Java-Themen 7
R Statistische Methoden (Mathematik) Aufgabe Allgemeine Java-Themen 9
M Polymorphie Aufgabe Allgemeine Java-Themen 15
E Java Aufgabe WaWi01 Allgemeine Java-Themen 7
D Methoden Java-Aufgabe Allgemeine Java-Themen 2
R Java-Code für folgene Aufgabe? Allgemeine Java-Themen 8
G Methoden BMI -Wert Aufgabe(Methoden) Allgemeine Java-Themen 4
G Erste Schritte Aufgabe - Geht das auch schneller ? Allgemeine Java-Themen 7
R Was los mit dieser Aufgabe? Arrays mit Schachbrettmustern? Allgemeine Java-Themen 10
vandread Kleine Generics Aufgabe aus einer Prüfung... wie ist das gemeint? Allgemeine Java-Themen 6
D Aufgabe: Schnittstelle und Proxy implementieren Allgemeine Java-Themen 2
D BlueJ - Aufgabe 12 namens Traktor Allgemeine Java-Themen 7
D OOP Mustererkennungs Aufgabe Allgemeine Java-Themen 9
pg1337 Firmen-aufgabe Allgemeine Java-Themen 10
B Konkrete Aufgabe Allgemeine Java-Themen 9
S Textverständnis einer Aufgabe Allgemeine Java-Themen 2
F Frage zu Aufgabe Allgemeine Java-Themen 5
P Java-Security-Aufgabe gesucht Allgemeine Java-Themen 2
M Brauche einen Tipp, bei einer Aufgabe ! Allgemeine Java-Themen 3
I Aufgabe: Aufwandsabschätzung Allgemeine Java-Themen 7

Ähnliche Java Themen

Neue Themen


Oben