010
18.09.2003, 16:04 Uhr
virtual
Sexiest Bit alive (Operator)
|
Also mit reinem C++ sind solche Aufgaben zwar prinzipiell lösbar, aber das ist ziemlich unangenehm, weil wenn man es ganz sauber machen will ("{}" könnte ja auch mal in einem String vorkommen oder in Kommentaren; allerdings ist das nicht das einzige Problem), dann muß man den Quelltext richtiggehend parsen. Hierfür kann man den Umweg über flex gehen, welches Dir eine parserklasse generiert, mit deren Hilfe Du das lösen könntest. Oder eben, wie bereits erwähnt, direkt ein indent über den Source jagen. Und natürlich perl: Perl ist wie geschaffen wür solche Problemchen, wobei auch hier ein wenig handarbeit notwendig wäre.
Aber wenn es unbedingt C++ sein sollte: Ich würde es ungefähr so angehen: Der Source besteht aus "Teilen". Ein "Teil" ist sowas ähnliches wie ein Block, allerdings eben nicht das gleiche. In Deinem prgramm wäre das erste "Teil" alles bis zur ersten geschweiften Klammer. Der zweite Teil wäre alles beginnend mit der geschweiften Klammer bis zur korrespondierenden Klammern zu. Danach folgen weitere Teile. Ein Teil kann selbst wieder aus teilen bestehen. Daraus regibt sich im Groben folgendes Klassendiagramm:
C++: |
class Teil { bool hatKlammern; // Flag, das angibt, ob klammern da sind .... };
class AtomicTeil: public Teil // Ein Teil ohne unterteile { std::string inhalt; // Inhalt des Teils .... };
class ComposedTeil: public Teil { std::list<Teil*> teile; // Liste der untergeordneten Teile };
|
Die eigentliche Kunst besteht in erster Line darin, den Text nun so zu parsen, daß man den gesamten Quelltext als ein ComposedTeil auffassen kann. Dies kann man unterschiedlich komliziert anstellen. Die naive methode wäre, einen String nach folgendem Schema zu bearbeiten: 1. Man erstellt ein ComposedTeil 2. Man sucht die { 3. Wenn vor dem { TExt ist, erzeugt man ein AtomicTeil und fügt dieses ans Ende der Liste des ComposedTeils an. 4. Man sucht das zu dem { passende }. 5. Mit diesem teilstring ruft man rekursiv unsere Routine auf, die das ganze für den teilstring wiedr holt. Das so gewonnene ComposedTeil fügt man an die Liste am ende an. 6. Man betrachtet nun nur noch den String nach dem }. Wenn der String nicht leer ist, gehts weiter mit Schritt 2 7. Man ist fertig. So oder so ähnlich sähe der Algo aus, beliebig verfeinerbar, wenn man { } in Kommentaren überspringen will
Dann kann man hingehen und den Teil Klassen entsprechende Ausgaberoutinen verpassen, wobei dem AtomicTeil aufgabe zufallen würde, bei allen Newlines die dem Newline folgenden Spaces (wenn welche da sind) durch eine Anzahl von Spaces zu ersetzen, die der Methode übergeben werden muß. Oder eben ein Newline zu löschen, wenn der Text von Atomic Teil nur aus Leerzeichen oder Newlines besteht). Das Composed Teil muß sich rekursiv durch die Liste der unterteile hangeln und entsprechend die Anzahl der Spaces erhöhen oder verringern. -- Gruß, virtual Quote of the Month Ich eß' nur was ein Gesicht hat (Creme 21) |