Aus Lesson 3 sind uns Zeichenketten (in Processing mit String betitelt) bekannt. Sie beinhalten Informationen über Schriftzeichen die wir mit text() abbilden können. Anders als bei int und float handelt es sich bei String um einen komplexen Datentyp. Dies erkennen wir an der Großschreibung und dem nicht orange eingefärbt werden im Processing Texteditor. Komplexe Datentypen besitzen einen erweiterten Umfang von Speicher- und/oder Funktionsmöglichkeiten. Beispielsweise erlauben uns Variablen vom Typ PImage mittels der Punktschreibweise und des Befehls width (myPImage.width) die Breite von Bilddokumenten auszulesen. Primitive Datentypen hingegen haben nur die Funktion einen Wert zu speichern.
Zeichenketten (String Variablen) sind ähnlich wie Arrays aufgebaut. Alle Schriftzeichen sind in einer Art Liste abgelegt die durchnummeriert bei 0 beginnt und bei der Anzahl der Zeichen minus 1 endet. Da wir nicht davon ausgehen können den abzubildenden Text in gewünschte Form vorliegen zu haben, bzw. der Text nur analysiert und die Ergebnisse visualisiert werden sollen, bietet Processing ein Set an Werkzeugen.
Zum Auslesen von Texten sind drei Funktionen essentiell.
String s = "abc123ABC"; println (s.charAt (1)); // b println (s.charAt (7)); // B
true oder false zurück. siehe Referenz
String s1 = "abc";
String s2 = "ABC";
if (s1.equals (s2) == true) {
println ("s1 ist gleich s2");
}else{
println ("s1 ist nicht gleich s2"); // <-- wird ausgeführt
}
String s = "abc123ABC"; println (s.length ()); // 9
-1, eine unmögliche Position im Text. siehe Referenz
String s = "abc123ABC";
println (s.indexOf ("1")); // 3
Bei der Länge handelt es sich immer um die Gesamtanzahl aller Schriftzeichen. Das beinhaltet neben Buchstaben, Zahlen und Sonderzeichen ebenfalls Leerzeichen, Tabs und weitere unsichtbare Zeichen und Symbole. Die Funktion length(), angewandt auf eine Variable vom Typ String, zählt alle und teilt uns ihr Ergebnis mit. Dabei handelt es sich immer um eine Ganzzahl (int).
String s1 = " -$- "; String s2 = "3 Mark"; println (s1.length ()); // 5 println (s2.length ()); // 6 String s3 = s1 + " " + s2; println (s3.length ()); // 12
In diesem Beispiel lesen wir mittels der for-Schleife jedes zweite Zeichen aus unserem satz aus. Bei Index 0, dem ersten Zeichen, befindet sich das L. Wir erhöhen den Wert von i nach jedem Durchlauf um zwei und sind im zweiten Schritt bei dem Buchstaben r. Unsere Schleife läft solange i kleiner ist als unser Satz Zeichen hat – in diesem Fall 27.
String satz = "Lorem ipsum dolor sit amet."; for (int i=0; i < satz.length (); i += 2) { print (satz.charAt (i)); // Lrmismdlrstae }
Basierend auf dem vorherigen Beispiel suchen wir nun in unserem Textschnippsel nach dem Ausdruck “ipsum”. Wir erhalten von dem Aufruf s.indexOf (“ipsum”) die Zahl (int) 6. Das Resultat beschreibt die Position der ersten Zeichenkombination “ipsum” in unserem Text. Es kann sich bei der Suche auch um einzelne Zeichen, Zahlen, Sonderzeichen oder Kombinationen dieser handeln.
Ausgehend von dieser Position starten wir mit unserer for-Schleife und lesen den Text Zeichen für Zeichen aus. Dabei wird unsere Zählvariable i immer um 1 erhöht, wir lassen kein Zeichen aus.
String s = "Lorem ipsum dolor sit amet."; // Die Startposition wird durch das Suchergebnis // nach "ipsum" definiert. Das erste Vorkommen zählt! int start = s.indexOf ("ipsum"); // Ausgabe aller Zeichen ab der durch "start" // beschriebenen Position im Text. for (int i=start; i < s.length (); i++) { print (s.charAt (i)); }
Wie beim Auslesen bietet uns Processing ein Set an Tools Texte zu verändern. Angefangen bei der Funktionalität Inhalte von überschüssigen Leerzeichen am Anfang & Ende zu bereinigen bis hin zu komplexen Extrahiermethoden. Die Vorgehensweisen teilen sich in die Gruppe der Exakten, mit Regelanwendungen anhand genauer Positionsangaben, und die Unexakten. Meist ist die Struktur bzw. der Aufbau des Textes unbekannt. In diesem Fall kommt es zur Anwendung der unexakten Methoden. Beispielsweise benötigt man immer die ersten drei Sätze, ohne deren Länge zu berücksichtigen. Als Lösung teilen wir unseren Text in Textschnippsel, getrennt wird immer am Satzende – der Position im Text wo ein Punkt gesetzt ist. Exakte Funktionen erfordern qualitativ hochwertige Daten/Texte. Das Resultat des Programms hängt von der Struktur des Texten, der genauen Einhaltung der Zeichenabfolge, ab.
String names = "Ursula,Uwe Kowalski,Beate,Peggy Schmidt,Max"; String[] arr = split (names, ","); println (arr[1]); // Uwe Kowalski println (arr[2]); // Peggy
String[] arr = new String[3]; arr[0] = "Ursula"; arr[1] = "Uwe Kowalski"; arr[2] = "Beate"; String names = join (arr, ","); println (names); // Ursula,Uwe Kowalski,Beate
String s = "abc123ABC"; println (s.substring (2)); // c123ABC println (s.substring (3, 6)); // 123
String s = " My tiny Text ";
println ("|" + s + "|"); // | My tiny Text |
s = trim (s);
println ("|" + s + "|"); // |My tiny Text|
Vom Großen ins Kleinteilige. Das Beispiel zerlegt den zu Beginn erstellten Text snippet in einzelne Sätze bzw. im zweiten Schritt diese in einzelne Wörter. Die Anzahl der Sätze und die Satzlänge sind dabei nicht von Bedeutung. Die Trennung erfolgt dabei:
In beiden Fällen erhalten wir ein Array aus Strings zurück, welches wir mit zwei Zählschleifen auslesen.
String snippet; snippet += "Dort! sagte der Bieber zum Esel."; snippet += " In diesem Augenblick ging das Feuer aus."; snippet += " Die Tankstelle hatte schon zu."; // den Text "snippet" in einzelne Sätze zerlegen String[] satz = split (snippet, "."); // für jeden Satz for (int s = 0; s < satz.length; s++) { // Leerzeichen am Anfang entfernen satz[s] = satz[s].trim (); // kompletten Satz ausgeben println (satz[s]); // wenn der Satz mehr als null Zeichen hat if (satz[s].length () > 0) { // den Satz in Worte zerlegen String[] wort = split (satz[s], " "); // für jedes Wort im Satz for (int w = 0; w < wort.length; w++) { // Wort inklusive Position im Satz ausgeben println (" (" + w + ") " + wort[w]); } } }
Mit diesem Beispiel bedienen wir den Bereich des exakten Arbeitens mit Strings. Exakt, weil wir mit genauen Positionsangaben arbeiten. Mit einer for-Schleife durchlaufen wir unser Array das mit Namen gefüllt ist. Jedem Namen ist eine einstellige Ziffer, gefolgt von Punkt und Leerzeichen, vorangestellt. Diese drei Zeichen sind uns in unserem Programm unpassend – wir bevorzugen die freigestellten Namen. Um dies zu Realisieren nutzen wir die Funktion substring() mit einem Parameter. Die übergebene drei gibt das erste Zeichen an, welches unser Ergebnis enthalten soll. Da wir kein Ende zur Begrenzung angegeben haben, gibt uns Processing den Rest der Zeichenkette ab dem vierten Element zurück. Das Programm ist in dieser Form strikt an den Aufbau der Zeichenketten gebunden. Mehrstellige Zahlen zu Beginn würden das Leerzeichen, den Punkt bzw. möglicherweise Ziffern in das Ergebnis rutschen lassen.
String[] name = new String[3]; name[0] = "1. Peggy Meier"; name[1] = "2. Rudolf Schmidt"; name[2] = "3. Eckhard Karsten"; for (int i=0; i < name.length; i++) { println (name[i].substring (3)); }
Um die Anfälligkeit zu verringern kann eine Kombination aus exakten und unexakten Funktionen benutzt werden. Wenn wir davon aus gehen, dass hinter jeder Zahl ein Punkt folgt, erlaubt uns die unexakte Funktion split() im ersten Schritt Zahl und Name zu trennen. Im zweiten Schritt entfernen wir das überschüssige Leerzeichen mittels der exakten Funktion substring().
String[] name = new String[3]; name[0] = "1. Peggy Meier"; name[1] = "98. Rudolf Schmidt"; name[2] = "11124. Eckhard Karsten"; for (int i=0; i < name.length; i++) { String[] arr = split (name[i], "."); println (arr[1].substring (1)); }
Processing gibt uns eine Funktion an die Hand, mit der wir Textdokument auf einfache Art und Weise auslesen können. Die einzige Vorraussetzung ist die Ablage der Datei im Ordner SketchOrdner/data. Eine Textdatei wird von Processing Zeile für Zeile analysiert. Hat Processing eine Zeile eines Textes gelesen, speichert es diese in einem String-Objekt ab. All diese String-Objekte werden am Ende in einem String-Array zusammengeführt und uns zur Verfügung gestellt.
String[] myText = loadStrings ("source.txt"); for (int i=0; i < myText.length; i++) { println (myText[i]); }
Wenn alle Textschnippsel, die jeweil in einem Feld des Text-Arrays liegen, zusammengeführt werden, verliert man die Zeilenumbrüche. Im unteren Beispiel geben wir die Zeilen innerhalb der for-Schleife nicht aus, sondern hängen sie an unseren Text “s” an. Um einen Zeilenumbruch nach jeder Zeile (wie im Dokument) zu erhalten, wird der Inhalt von myText[i] um den Ausdruck \n erweitert. Dies steht für new line.
String[] myText = loadStrings ("source.txt"); String s = ""; for (int i=0; i < myText.length; i++) { s += myText[i] + "\n"; } println (s);