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 (Fortsetzung) 20. Januar 2005 Übungen zu Einführung in die Informatik I (Vorversion) Aufgabe 31 Zeileneditor (Lösungsvorschlag) d) Das Editormodell unter Einbeziehung eines Befehlsstacks könnte wie folgt aussehen: java.io.BufferedReader java.util.Vector * java.lang.StringBuffer lines stdin Document Ed document line, column: int showDocument() showLine() showCursor() userInputLoop() getCommand() getArgument() main() getLine() getNumberOfLines() getNumberOfColumns() deleteLine() insertLine() insertTextInLine() deleteCharacter() store() undo_stack java.util.Stack Command * + undo() InsertLineCommand ........ + undo() DeleteLineCommand ........ + undo() InsertTextInLineCommand ........ + undo() e) In der Klasse Ed muss nur die Befehlseingabe erweitert werden: case ’u’: if (document.undo()) showDocument(); else System.out.println("No more undo."); break; Die erweiterte Klasse Document (mit internen Klassen): import import import import java.io.BufferedReader; java.io.BufferedWriter; java.io.FileReader; java.io.FileWriter; ......... Lösung 11 (Fortsetzung)/ Seite 2 import java.io.IOException; import java.util.Stack; import java.util.Vector; public class DocumentPlus { private Vector lines; private Stack undo_stack; private String fileName; public DocumentPlus(String file) throws IOException { // init lines = new Vector(); undo_stack = new Stack(); // 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; } 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; } } // getter public String getLine(int line) { try { return lines.get(line - 1).toString(); } catch (ArrayIndexOutOfBoundsException e) { return ""; } } public int getNumberOfLines() { return lines.size(); } public int getNumberOfColumns(int line) { try { Lösung 11 (Fortsetzung)/ Seite 3 return ((StringBuffer) lines.get(line - 1)).length(); } catch (ArrayIndexOutOfBoundsException e) { return 0; } } // public editing methods public boolean deleteLine(int line) { try { undo_stack.push(new DeleteLineCommand(this, line)); } catch (Exception e) { return false; } return true; } public boolean insertLine(int line, String text) { try { if (getNumberOfLines() == 0) line = 1; undo_stack.push(new InsertLineCommand(this, line, text)); } catch (Exception e) { return false; } return true; } public boolean insertTextInLine(int line, int column, String text) { try { undo_stack.push(new InsertTextInLineCommand(this, line, column, text)); } catch (Exception e) { return false; } return true; } public boolean deleteCharacter(int line, int column) { try { undo_stack.push(new DeleteCharacterCommand(this, line, column)); } catch (Exception e) { return false; } return true; } // private editing methods private void deleteLineInternal(int line) { lines.remove(line - 1); } private void insertLineInternal(int line, String text) { lines.add(line - 1, new StringBuffer(text)); } Lösung 11 (Fortsetzung)/ Seite 4 private void insertTextInLineInternal(int line, int column, String text) { ((StringBuffer) lines.get(line - 1)).insert(column - 1, text); } private void deleteCharacterInternal(int line, int column) { ((StringBuffer) lines.get(line - 1)).deleteCharAt(column - 1); } // undo public boolean undo() { if (undo_stack.empty()) return false; ((Command) undo_stack.pop()).undo(); return true; } // internal command classes abstract class Command { DocumentPlus document; Command(DocumentPlus document) { this.document = document; } abstract void undo(); } class InsertLineCommand extends Command { int line; InsertLineCommand(DocumentPlus document, int line, String text) { super(document); this.line = line; document.insertLineInternal(line, text); } void undo() { document.deleteLineInternal(line); } } class DeleteLineCommand extends Command { String text; int line; public DeleteLineCommand(DocumentPlus document, int line) { super(document); this.line = line; this.text = document.getLine(line); document.deleteLineInternal(line); } void undo() { document.insertLineInternal(line, text); Lösung 11 (Fortsetzung)/ Seite 5 } } class InsertTextInLineCommand extends Command { int line, column, length; InsertTextInLineCommand(DocumentPlus document, int line, int column, String text) { super(document); this.line = line; this.column = column; this.length = text.length(); document.insertTextInLineInternal(line, column, text); } void undo() { for (int i = 0; i < length; i++) document.deleteCharacterInternal(line, column); } } class DeleteCharacterCommand extends Command { int line, column; char character; DeleteCharacterCommand(DocumentPlus document, int line, int column) { super(document); this.line = line; this.column = column; this.character = document.getLine(line).charAt(column - 1); document.deleteCharacterInternal(line, column); } void undo() { document.insertTextInLineInternal(line, column, "" + character); } } }