Technische Universität München Fakultät für Informatik A. Berlea, M. Petter, Dr. M. Schneider, P. Ziewer WS 2004/2005 Lösungsvorschläge zu Blatt 11 (erster Teil 20. Januar 2005 Übungen zu Einführung in die Informatik I Aufgabe 31 Zeileneditor (Lösungsvorschlag) a) • Zeilen: Zeilen sind Texte, können also durch String repräsentiert werden. Besser geeignet ist die Klasse StringBuffer für veränderbare Zeichenketten. Diese bietet nützliche Methoden wie insert(), delete() und append(). • Menge von Zeilen: z.B. Feld oder Liste von StringBuffer. Sinnvoll ist ein dynamisches Feld. Dies wird von der Klasse java.util.Vector geboten, die Methoden zum direkten Zugriff auf einzelne Elemente, sowie zum Einfügen und Löschen bietet (get(), add(), remove()). • Dokument: Eine neu zu implementierende Klasse Document übernimmt das Einlesen einer Textdatei und legt die einzelnen Zeilen in einem Zeilenvektor ab. Außerdem sollte die Klasse die notwendigen Editiermethoden zur Verfügung stellen. • Befehle: Eine Befehlszeile besteht aus einem String, der von der Standardeingabe gelesen wird. Ein Befehl ist das erste Zeichen einer solchen Befehlszeile und kann als char repräsentiert werden. Der Rest der Befehlszeile beinhaltet das zugehörige Argument (falls notwendig). Hilfsmethoden könnten zum Extrahieren von Befehl und Argument nützlich sein. • Hauptklasse des Editors: Die Klasse Ed übernimmt die Darstellung, sowie das Einlesen der Befehlszeilen und die entsprechenden Aufrufe der Editierfunktionen für das Dokument. Dies geschieht bis zum Abbruch seitens des Benutzers. Hilfsmethoden zur Darstellung einer Zeile (mit Zeilennummer), des gesamten Dokuments oder des Cursors sind hier hilfreich. Das gesuchte Klassenmodell könnte folgendermaßen aussehen: java.io.BufferedReader java.util.Vector lines stdin Document Ed line, column: int showDocument() showLine() showCursor() userInputLoop() getCommand() getArgument() main() document getLine() getNumberOfLines() getNumberOfColumns() deleteLine() insertLine() insertTextInLine() deleteCharacter() store() java.lang.StringBuffer Lösung 11 (erster Teil/ Seite 2 b), c), f) • Die Klasse Document (mit javadoc-Kommentaren): import import import import import import java.io.BufferedReader; java.io.BufferedWriter; java.io.FileReader; java.io.FileWriter; java.io.IOException; java.util.Vector; /** * The <code>document</code> class represents a ordered set of text lines * with corresponding editing methods. */ public class Document { private Vector lines; private String fileName; /** * Constructs a new document initialized with text read from a specified file. * * @param file name of the initial text file * @throws IOException can’t read initial text file */ public Document(String file) throws IOException { // init lines = new Vector(); // read text from file BufferedReader buffer = new BufferedReader(new FileReader(file)); String line; while ((line = buffer.readLine()) != null) { lines.add(new StringBuffer(line)); } buffer.close(); fileName = file; } /** * Writes modified document content back to file. * * @return <code>true</code> if write ok, else <code>false</code> */ public boolean store() { try { BufferedWriter buffer = new BufferedWriter(new FileWriter(fileName)); for (int i = 0; i < lines.size(); i++) { buffer.write(lines.get(i).toString()); buffer.newLine(); } buffer.close(); return true; } catch (IOException e) { return false; } Lösung 11 (erster Teil/ Seite 3 } /** * Delivers the textual content of a specified line. * * @param line number of line * @return text in line if line exists, empty <code>String</code> else */ public String getLine(int line) { try { return lines.get(line - 1).toString(); } catch (ArrayIndexOutOfBoundsException e) { return ""; } } /** * Delivers how many lines the document contains. * * @return number of lines */ public int getNumberOfLines() { return lines.size(); } /** * Delivers how many columns a specified line contains. * * @param line number of line * @return number of colums if line exists, 0 else */ public int getNumberOfColumns(int line) { try { return ((StringBuffer) lines.get(line - 1)).length(); } catch (ArrayIndexOutOfBoundsException e) { return 0; } } /** * Removes the specified line from the document. Following lines are shifted by on * * @param line number of line * @return <code>true</code> if operation succeeded, <code>false</code> else */ public boolean deleteLine(int line) { try { lines.remove(line - 1); return true; } catch (Exception e) { return false; } } Lösung 11 (erster Teil/ Seite 4 /** * Adds a new line containing the specified text at a specified position in the do * Following lines are shifted by one line each. * * @param line number of line * @param text contents of the new line * @return <code>true</code> if operation succeeded, <code>false</code> else */ public boolean insertLine(int line, String text) { try { if (getNumberOfLines() == 0) line = 1; lines.add(line - 1, new StringBuffer(text)); return true; } catch (Exception e) { return false; } } /** * Adds the specified text at a specified position in the document. * * @param line number of line * @param column number of column * @param text * @return <code>true</code> if operation succeeded, <code>false</code> else */ public boolean insertTextInLine(int line, int column, String text) { try { ((StringBuffer) lines.get(line - 1)).insert(column - 1, text); return true; } catch (Exception e) { return false; } } /** * Removes one character at a specified position from the document. * * @param line number of line * @param column number of column * @return <code>true</code> if operation succeeded, <code>false</code> else */ public boolean deleteCharacter(int line, int column) { try { ((StringBuffer) lines.get(line - 1)).deleteCharAt(column - 1); return true; } catch (Exception e) { return false; } } } • Die Klasse Ed: Lösung 11 (erster Teil/ Seite 5 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Ed { Document document; int line, column; BufferedReader stdin; public Ed(String filename) throws IOException { document = new Document(filename); line = column = 1; showDocument(); stdin = new BufferedReader(new InputStreamReader(System.in)); } public void userInputLoop() throws IOException { char command; while ((command = getCommand()) != ’q’) { switch (command) { case ’ ’: break; case ’a’: showDocument(); break; case ’6’: column++; break; case ’4’: column--; break; case ’8’: line--; break; case ’2’: line++; break; case ’l’: try { line = Integer.parseInt(getArgument()); } catch (NumberFormatException e) { System.out.println("Syntax Error."); } break; case ’c’: try { column = Integer.parseInt(getArgument()); } catch (NumberFormatException e) { System.out.println("Syntax Error."); } break; case ’r’: Lösung 11 (erster Teil/ Seite 6 document.deleteLine(line); break; case ’n’: if (document.insertLine(line + 1, getArgument())) line++; break; case ’d’: document.deleteCharacter(line, column); break; case ’i’: if (document.insertTextInLine(line, column, getArgument())) column += getArgument().length(); break; case ’s’: document.store(); break; default: System.out.println("Unknown command."); break; } } } private String argument = ""; private String getArgument() { return argument; } private char getCommand() { char command = ’ ’; argument = ""; try { valiadtePosition(); showLine(); showCursor(); System.out.print("> "); String commandLine = stdin.readLine(); command = commandLine.charAt(0); argument = commandLine.substring(2); } catch (Exception e) { } return command; } private void if (line line if (line line valiadtePosition() { > document.getNumberOfLines()) = document.getNumberOfLines(); < 1) = 1; if (column > document.getNumberOfColumns(line)) column = document.getNumberOfColumns(line); if (column < 1) Lösung 11 (erster Teil/ Seite 7 column = 1; } private void showDocument() { System.out.println("---------------------------------------------------------for (int i = 1; i <= document.getNumberOfLines(); i++) { showLine(i); } System.out.println("---------------------------------------------------------} private void showLine() { showLine(line); } private void showLine(int lineNumber) { System.out.print(lineNumber + ": "); try { System.out.println(document.getLine(lineNumber)); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(); } } private void showCursor() { int k = (line + ": ").length() + column; for (int i = 1; i < k; System.out.print(" "), i++) ; System.out.println("^" + " " + column); } public static void main(String[] argv) throws IOException { Ed ed = new Ed(argv[0]); ed.userInputLoop(); } }