1. Zeichenkettenverarbeitung
Zum Speichern von Zeichen und Zeichenfolgen stehen in Java die Typen char
, Character
, String
und StringBuilder
bereit. Der Einsatz der Datentypen muss geübt werden, denn jeder Typ hat seine Berechtigung. Die Aufgaben bringen den Lesern die Vor- und Nachteile der einzelnen Datentypen nahe.
Voraussetzungen
API von
String
undStringBuilder
sicher nutzen könnenAPI von
String
undStringBuilder
sicher nutzen könnenerkennen, wann
String
undStringBuilder
besser geeignet ist
Verwendete Datentypen in diesem Kapitel:
Noch mehr Aufgaben findest du im Buch: ›Captain CiaoCiao erobert Java: Das Trainingsbuch für besseres Java. 300 Java-Workshops, Aufgaben und Übungen mit kommentierten Lösungen‹
1.1. Die Klasse String und ihre Eigenschaften
String
ist nicht nur ein Datentyp, der für immutable Zeichenfolgen steht, sondern die Klasse bietet auch eine große Anzahl von Methoden. Wer die Methoden kennt und zu nutzen weiß, kann sich viel Arbeit sparen.
1.1.1. HTML-Elemente aufbauen mit einfacher Konkatenation ⭐
Zur Erinnerung: In HTML werden für Auszeichnungen Tags eingesetzt, ein Beispiel ist <strong><em>Emphasized and Italics</em></strong>
.
Aufgabe:
Schreibe eine neue Methode
htmlElement(String tag, String body)
, die einen Stringbody
mit einem Start- und End-Tagtag
einrahmt und als neuenString
zurückgibt. Es gibt folgende Sonderbehandlung:Ist
tag
gleichnull
oder leer (""
) so wird nur derbody
betrachtet und keine Start-End-Tags geschrieben.Ist
body
gleichnull
, so gilt das wie ein übergebener Leer-String.
Schreibe zwei neue Methoden
strong(String)
undemphasized(String)
, die im Hintergrund mithtmlElement(…)
arbeiten und ein<strong>
respektive<em>
erzeugen.
Beispiel:
htmlElement( "strong", "strong is bold" )
→"<strong>strong is bold</strong>"
strong( emphasized( "strong + emphasized" ) )
→"<strong><em>strong + emphasized</em></strong>"
htmlElement( "span", null )
→"<span></span>"
htmlElement( "", "no" )
→"no"
htmlElement( null, "not strong" )
→"not strong"
htmlElement( null, null )
→""
Hinweis: Es gibt durchaus einige Anforderungen an Tag-Namen, die ein richtiges Programm prüfen könnte. So dürfen Tag-Namen nur die Ziffern 0 bis 9 sowie Groß- und Kleinbuchstaben enthalten. Diese Fälle können ignoriert werden.
1.1.2. Sichere Übermittlung durch Verdoppelung der Zeichen prüfen ⭐
Bamboo Blobfish nutzt einen Typendrucktelegraf, um Bonny Brain wichtige Nachrichten mitzuteilen. Da es auf jedes Zeichen ankommt, sendet Bamboo alle Zeichen zur Sicherheit zweimal hintereinander.
Aufgabe:
Schreibe eine Methode
int isEveryCharacterTwice(String)
, die prüft, ob jedes Zeichen im String zweimal hintereinander vorkommt.Ist die Anzahl der Symbole ungerade, ist die Nachricht falsch und die Rückgabe der Methode
0
.Kommt jedes Zeichen zweimal vor, ist die Antwort eine beliebige positive Zahl. ˗ Wenn ein Zeichen nicht zweimal hintereinander vorkommt, gibt die Methode die Position mit der ersten falschen Stelle zurück, allerdings negiert.
Beispiele:
isEveryCharacterTwice("eehhrrwwüürrddiiggeerr$$ccaappttaaiinn")
→1
isEveryCharacterTwice("ccapptttaaiinn")
→-3
isEveryCharacterTwice("222")
→0
isEveryCharacterTwice(null)
→NullPointerException
Dass ein negativer Index gewisse Stellen markiert, ist auch in der Java-Bibliothek zu finden. Die |
1.1.3. Y und Z vertauschen ⭐
Captain CiaoCiao tippt auf seiner Tastatur einen längeren Text, und spät fällt ihm auf, dass statt des deutschen Tastaturlayouts das englische aktiviert ist. Jetzt sind »y« und »z«, bzw. »Y« und »Z« vertauscht. Der Text muss korrigiert werden.
Aufgabe:
Lege eine neue Klasse
YZswapper
an.Setze in die Klasse eine neue Klassenmethode
void printSwappedYZ(String string)
, die einen übergebenenString
auf den Bildschirm bringt, aber den Buchstaben »y« als »z«, »z« als »y«, »Y« als »Z« und »Z« als »Y« ausgibt. Es geht nicht darum, einen String aus der Methode zurückzuliefern!Schreibe nicht nur eine Variante, sondern versuche, mindestens zwei Varianten zu programmieren. Es gibt zum Beispiel, die Möglichkeit die Zeichen mit
if
-else
zu prüfen oder mitswitch
-case
.
Beispiele:
printSwappedYZ("yootaxz")
ergibt auf dem Bildschirm die Ausgabezootaxy
undprintSwappedYZ("Yanthoxzl")
die AusgabeZanthoxyl
.
1.1.4. Trotzige Antworten geben ⭐
Tony der Trotzige ist für die Aktivitäten auf dem Schwarzmarkt von Captain CiaoCiao zuständig, doch er wird geschnappt und von der Polizei verhört. Um die Polizisten zu nerven, wiederholt er alles, was sie sagen, und setzt ein »No idea!« hintendran. Fragt der Polizist: »Where is the illegal whiskey distillery?«, sagt Tony: »Where is the illegal whiskey distillery? No idea!«
Aufgabe:
Lege eine neue Klasse an, und frage von der Kommandozeile eine Eingabe ab.
Abhängig von der Eingabe sollen drei Fälle unterschieden werden:
Wenn die Eingabe mit einem ? endet, dann gib auf dem Bildschirm aus, was von der Eingabe kommt, und hänge aber
" No idea!"
hinten an.Wenn von der Polizei keine Frage gestellt wird — die Eingabe endet nicht mit
?
— hält Tony der Trotzige ganz seinen Mund.Kommt von der Eingabe die spezielle Eingabe
"No idea?"
, und das unabhängig von der Groß-/Kleinschreibung, erwidert Tony trotzig:"Aye!"
1.1.5. Zeichenfolgen auf Palindrom-Eigenschaft testen ⭐
Ein Palindrom ist ein Wort, das sich von vorne wie von hinten gleich liest, etwa »Otto« oder auch »121«.
Dass es überhaupt solche Wörter und sogar Sätze gibt, amüsiert Captain CiaoCiao, kann er damit doch die Gesellschaft unterhalten. Allerdings legt man ihm immer wieder Zeichenfolgen vor, die keine Palindrome sind. Daher müssen alle Wörter vorher getestet werden.
Aufgabe:
Schreibe ein Java-Programm, das untersucht, ob eine Zeichenkette ein Palindrom ist.
Lege eine neue Klasse
PalindromeTester
an.Implementiere eine statische Methode
boolean isPalindrome(String s)
.Erweitere das Programm um eine Klassenmethode
boolean isPalindromeIgnoringCase(String s)
, sodass der Test unabhängig von der Groß-/Kleinschreibung wird.Jetzt sollen auch alle Zeichen ignoriert werden, die keine Buchstaben oder Ziffern sind. Bei der Feststellung hilft
Character.isLetterOrDigit(char)
. Damit kann man auch Sätze wie »A man a plan a canal Panama« oder »Pepe in Tahiti hat nie Pep« oder »Sei fies – stets sei fies!« prüfen. Nennen wir die MethodeisPalindromeIgnoringNonLettersAndDigits(String)
.
1.1.6. Prüfen, ob Captain CiaoCiao in der Mitte steht ⭐
Captain CiaoCiao ist der Mittelpunkt der Welt, also erwartet er, dass er in allen Texten auch im Zentrum steht.
Aufgabe:
Schreibe eine Methode
boolean isCiaoCiaoInMiddle(String)
, dietrue
liefert, wenn die Zeichenfolge"CiaoCiao"
in der Mitte steht.
Beispiele:
isCiaoCiaoInMiddle("CiaoCiao")
→true
isCiaoCiaoInMiddle("!CiaoCiao!")
→true
isCiaoCiaoInMiddle("SupaCiaoCiaoCute")
→true
isCiaoCiaoInMiddle("x!_CiaoCiaoabc")
→true
isCiaoCiaoInMiddle("\tCiaoCiao ")
→true
isCiaoCiaoInMiddle("BambooCiaoCiaoBlop")
→false
isCiaoCiaoInMiddle("Bernie und Ert")
→false
1.1.7. Den kürzesten Namen im Array finden ⭐
Bonny Brain nutzt nur den kürzesten Rufnamen einer Person.
Aufgabe:
Schreibe eine Methode
String shortestName(String... names)
, die von allen vollständigen Namen den kürzesten Teil-String zurückgibt. Der String kann auch genau ein Leerzeichen enthalten, wenn der Name zusammengesetzt ist. Anders gesagt: Es gibt Strings mit einem Namen oder Strings mit zwei Namen.Wenn es keine Namen gibt, ist die Antwort ein leerer String.
Das Vararg-Array darf nicht
null
sein, und kein String im Array darfnull
sein.
Beispiel:
shortestName("Albert Tross", "Blowfish", "Nick Olaus", "Jo Ker")
→"Jo"
1.1.8. String-Vorkommen zählen ⭐
Captain CiaoCiao hat in einer unbedachten Aktion den Entwickler Dev David ausgeschaltet. Der war gerade dabei, eine Methode zu schreiben; die Javadoc ist fertig, aber die Implementierung fehlt.
/**
* Counts how many times the substring appears in the larger string.
*
* A {@code null} or empty ("") String input returns {@code 0}.
*
* <pre>
* StringUtils.countMatches(null, *) = 0
* StringUtils.countMatches("", *) = 0
* StringUtils.countMatches("abba", null) = 0
* StringUtils.countMatches("abba", "") = 0
* StringUtils.countMatches("abba", "a") = 2
* StringUtils.countMatches("aaaa", "aa") = 2
* StringUtils.countMatches("abba", "ab") = 1
* StringUtils.countMatches("abba", "xxx") = 0
* </pre>
*
* @param string the String to check, may be null
* @param other the substring to count, may be null
* @return the number of occurrences, 0 if either String is {@code null}
*/
public static int countMatches( String string, String other ) { return null; }
Hinweis: Das *
in der Javadoc symbolisiert eine beliebige Übergabe.
Aufgabe:
Implementiere die Methode.
1.1.9. Die größere Mannschaft ermitteln ⭐
Bonny Brain studiert alte Logbücher, in denen die Stärke ihrer Mannschaft und die der gekaperten Schiffe steht:
|-||| |-|| |||-||| |||||-||
Jedes Crew-Mitglied ist durch einen Strich symbolisiert, ein Minuszeichen trennt die Mannschaftsgröße. Links steht die Anzahl Personen auf dem eigenen Schiff, rechts die Anzahl des überfallenen Schiffs.
Aufgabe:
Die Striche sind für Bonny Brain nicht gut zu lesen. Schreibe ein Programm, das die Kodierung deutlich macht:
|-||| => Raided ship had a larger crew, difference 2 |-|| => Raided ship had a larger crew, difference 1 |||-||| => Ships had the same crew size |||||-|| => Pirate ship had a larger crew, difference 3
1.1.10. Diamanten bauen ⭐⭐
Captain CiaoCiao mag Diamanten, je größer desto besser.
Aufgabe:
Schreibe ein Programm, das folgende Ausgabe generiert:
A ABA ABCBA ABCDCBA ABCBA ABA A
Über eine Abfrage auf der Konsole soll es möglich sein, die maximale Breite des Diamanten festzulegen. In unserem Beispiel ist das die 7 — die Länge des String
ABCDCBA
. Es sollen nur Angaben für die Breite akzeptiert werden, die mit Strings aus auf- und wieder absteigenden Großbuchstaben zu erreichen sind, also maximal die Länge vonABCDEFGHIJKLMNOPQRSTUVWXYZYXWVU…BA
.
1.1.11. Auf ein gutes Passwort prüfen ⭐
Alle schmutzigen Geheimnisse verschlüsselt Captain CiaoCiao, aber zu oft war sein Passwort zu einfach und wurde erraten. Er hat gelernt, dass ein sicheres Passwort für seine Geschäfte wichtig ist, doch kann er sich die Regeln nicht so richtig merken: Ein gutes Passwort hat eine gewisse Länge, enthält Sonderzeichen usw.
Aufgabe:
Lege eine neue Klasse
PasswordTester
an.Schreibe eine Methode
isGoodPassword(String)
, die einige Kriterien testet. Die Methode sollfalse
zurückgeben, wenn das Passwort nicht gut ist, undtrue
, wenn das Passwort einen guten Aufbau hat. Schlägt ein Test fehl, so soll überSystem.err
eine Meldung erscheinen und es sollen keine weiteren Prüfungen stattfinden.
1.1.12. Erdnussbutterkekse backen ⭐⭐
Kurz vor dem Fest trifft sich die Crew bei Captain CiaoCiao, um Erdnussbutterkekse zu backen. Die Hobbybäcker bringen entweder Erdnussbutter, Zucker oder Eier mit. Als sie ankommen, setzen sie sich der Reihe nach an einen Tisch und möchten anfangen zu backen.
Gegeben ist eine Liste aller Zutaten, die die Hobbybäcker mitgebracht haben. Die Liste wird als String repräsentiert, wobei P
für Erdnussbutter steht, S
für Zucker und E
für Ei. Der String könnte lauten: PSESEPESP
oder auch PPPEEESSS
.
Gebacken werden kann nur, wenn drei Hobbybäcker mit Erdnussbutter, Zucker und Ei nebeneinander sitzen, wobei die Reihenfolge egal ist.
Aufgabe:
Ermittele, wie oft Erdnussbutterkekse gebacken werden können, also die drei Zutaten direkt nebeneinander in beliebiger Reihenfolge zusammenkommen.
Einige Hobbybäcker haben nicht richtig zugehört und bringen ganz andere Zutaten mit, wie Rum, Lakritz oder marinierten Aal. Mit ihnen lassen sich keine Erdnussbutterkekse backen.
Beispiele:
"PSESEPESP"
→ 3"PPPEEESSS"
→ 0"SEPEPLSEE"
→ 1
1.1.13. Quersumme berechnen ⭐
Da Bonny Brain oftmals Zahlungen anweist und befürchtet, jemand könnte die Beträge verändern, greift sie zu einem Trick: Neben dem Betrag übermittelt sie in einem getrennten Kanal die Quersumme.
Die Quersumme einer Zahl bildet man durch die Addition jeder Ziffer der Zahl. Wenn die Zahl etwa 10938 lautet, so ist die Quersumme 1 + 0 + 9 + 3 + 8 = 21.
Aufgabe:
Lege eine neue Klasse
SumOfTheDigits
an.Schreibe eine Klassenmethode
int digitSum(long value)
, die die Quersumme einer Zahl berechnet.Schreibe eine überladene Klassenmethode
int digitSum(String value)
dazu, die die Ziffern in einem String annimmt.
Welche Methode ist leichter zu implementieren? Welche Methode sollte die andere als Unterprogramm aufrufen?
1.1.14. Texte entspalten ⭐⭐
Captain CiaoCiao scannt alte Logbücher ein, doch die waren ursprünglich in Spalten. Nach der OCR-Texterkennung bleiben die Spalten erhalten.
Da das nicht gut zu lesen ist, sollen die zwei Spalten erkannt und in regulären Fließtext ohne Spalten übersetzt werden.
Aufgabe:
Schreibe eine Methode
decolumnize(String)
, die nach der Weißraum für die Trennung der Spalten sucht und aus einem String mit Text in zwei Spalten einen Text ohne Spalten liefert. Es ist im Vorfeld nicht bekannt, wo die Trennung der Spalten ist, das muss das Programm ermitteln.
Beispiel:
I’m dishonest, and a to watch out for, dishonest man you because you can can always trust to never predict when be dishonest. they’re going to do Honestly, it’s the something incredibly honest ones you want stupid.
→
I’m dishonest, and a dishonest man you can always trust to be dishonest. Honestly, it’s the honest ones you want to watch out for, because you can never predict when they’re going to do something incredibly stupid.
Jede Spalte ist durch mindestens ein Leerzeichen getrennt. Bedenke, dass die rechte und linke Seite »halbe« Leerzeilen haben können!
1.1.15. Eine Wiese mit Lieblingsblumen zeichnen ⭐⭐
Captain CiaoCiao möchte sein Schiff verschönern und mit Blumen verzieren. Er findet eine Grafik von Joan G. Stark als Vorlage und überlegt, wie er den Malern und Anstreichern mitteilen kann, welche Muster er in der Kabine wünscht.
_ _(_)_ wWWWw _ @@@@ (_)@(_) vVVVv _ @@@@ (___) _(_)_ @@()@@ wWWWw (_)\ (___) _(_)_ @@()@@ Y (_)@(_) @@@@ (___) `|/ Y (_)@(_) @@@@ \|/ (_)\ / Y \| \|/ /(_) \| |/ | \ | \ |/ | / \ | / \|/ |/ \| \|/ \\|// \\|// \\\|//\\\|/// \|/// \\\|// \\|// \\\|// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Aufgabe:
Kopiere die Blumen in einen String. Tipp: Lege einen String wie
String flower = "";
an, setze die Blumenreihe in die Zwischenablage, und füge sie in der IDE zwischen die Anführungszeichen ein; IntelliJ und Eclipse werden dann die Sonderzeichen wie\
und\n
selbständig kodieren. Mit den Textblöcken wird es noch einfacher.Es gibt 8 Sorten von Blumen, und wir können sie durchnummerieren von 1 bis 8. Die Reihenfolge kodieren wir als String, zum Beispiel
"12345678"
. Es soll nun möglich sein, die Reihenfolge zu ändern und Blumen mehrfach vorkommen zu lassen, etwa durch die Kodierung"8383765432"
. Ist eine Kennung falsch, soll für sie automatisch immer die erste Blume erscheinen.
Beispiele:
"838"
führt zu_ _(_)_ _ _(_)_ (_)@(_) _(_)_ (_)@(_) (_)\ (_)@(_) (_)\ `|/ (_)\ | \| | \|/ | / \|/ \\\|/ \\\|// \\\|/ ^^^^^^^^^^^^^^^^^^^^^^^
"ABC9"
führt zu@@@@ @@@@ @@@@ @@@@ @@()@@ @@()@@ @@()@@ @@()@@ @@@@ @@@@ @@@@ @@@@ / / / / \ | \ | \ | \ | \\|// \\|// \\|// \\|// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Halte in einem Array die Stellen für den Übergang zwischen den Blumen fest. |
1.1.16. Wiederholungen erkennen ⭐⭐⭐
Captain CiaoCiao blättert in einem Buch und findet Muster der Art 🌼🌻🌼🌻🌸🌼🌻🌼🌻🌸🌼🌻🌼🌻🌸. Wie beruhigend für ihn. Er möchte Stempel für den Druck herstellen, um sich solche Musterfolgen selbst drucken zu können. Natürlich sollen die Kosten reduziert werden, und der Stempel soll selbst keine Wiederholungen von Symbolen enthalten. Für gegebene Musterfolgen soll ein Programm entwickelt werden, das die minimale Folge von Symbolen ermittelt, die auf den Stempel müssen.
Aufgabe:
Schreibe eine Methode
String repeatingStrings(String)
, die im Fall einer Wiederholung die sich wiederholende Zeichenfolge als Rückgabe liefert, sonstnull
, falls sich keine Teilfolge wiederholt.
Beispiele:
repeatingStrings("🌼🌼🌼")
liefert"🌼"
.repeatingStrings("🌼🌻""🌼🌻""🌼🌻")
liefert"🌼🌻"
.repeatingStrings("Ciao"+"Ciao")
liefert"Ciao"
.repeatingStrings("Captain CiaoCiaoCaptain CiaoCiao")
liefert"Captain CiaoCiao"
.repeatingStrings("🌕🌔🌓🌑")
liefertnull
repeatingStrings("CaptainCiaoCiaoCaptain")
liefertnull
repeatingStrings("🌼")
liefertnull
repeatingStrings("")
liefertnull
repeatingStrings(null)
liefertnull
Hinweis: repeatingStrings(…)
soll die kürzeste sich wiederholende Zeichenfolge liefern.
1.1.17. Zeilengrenzen beschränken und Zeilen umbrechen ⭐⭐
Bonny Brain steigt in der Kommunikation auf Brieftauben um, und da kann das Papier nicht sehr groß sein. Jetzt müssen alle Texte in der Breite reduziert werden.
Aufgabe:
Schreibe eine Klasse
WordWrap
mit einer statischen MethodeString wrap(String string, int width)
, die eine Zeichenkette ohne Zeilenumbrüche in kleine Teilzeichenketten der maximalen Breitewidth
zerlegt und mit\n
getrennt wieder zurückgibt. Innerhalb von Wörtern — und Satzzeichen gehören zum Wort — soll nicht zwangsumbrochen werden!
Beispiel:
Der Aufruf von
String s = "Live now; make now always the most precious time. " + "Now will never come again."; System.out.println( wrap( s, 10 ) );
liefert bei einer maximalen Zeilenlänge von 30 folgende Ausgabe:
Live now; make now always the most precious time. Now will never come again.
1.1.18. Testen, ob die Frucht schokoladig umhüllt ist ⭐⭐
Captain CiaoCiao mag Obstspieße mit Schokolade überzogen. Sara bekommt die Aufgabe, die Früchte zu glasieren, wobei sie unterschiedliche Schichten von dunkler und heller Schokolade bildet.
Bambi prüft, ob die Schichten korrekt sind. Sieht sie dhFhd
, weiß sie, dass die Frucht F
erst eine Schicht helle, dann eine Schicht dunkle Schokolade bekommen hat. Bei dhhd
fehlt die Frucht, und das entspricht nicht der Erwartung von Captain CiaoCiao. Bei ddhFh
ist die Schicht kaputt, was auch nicht richtig ist. Und bei F
fehlt die Schokolade komplett, was für eine Enttäuschung!
Aufgabe:
Schreibe eine rekursive Methode
checkChocolate(String)
, die prüft, ob der String symmetrisch ist, also links und rechts der gleiche Typ Schokolade ist und sich in der Mitte die FruchtF
befindet.
Optional: Erweitere das Programm, für den Fall, dass der String eine Fläche ist, etwa
String fruit =
"ddddd\n" +
"dhhhd\n" +
"dhFhd\n" +
"dhhhd\n" +
"ddddd" ;
1.1.19. Von oben nach unten, von links nach rechts ⭐⭐⭐
In einer Höhle findet Bonny Brain einen Text, allerdings läuft der Text nicht von links nach rechts, sondern ist von oben nach unten geschrieben.
s u ey! ao
Vertikal geschrieben ist das die Zeichenfolge sea you!
— und das ist viel einfacher zu lesen!
Aufgabe:
Schreibe eine Methode
printVerticalToHorizontalWriting(String)
, die einen String wieder in die horizontale Lage bringt und ausgibt. Das Argument ist ein String, in dem Zeilenvorschübe die Zeilen trennen.
Beispiel:
Bleiben wir bei dem String von oben:
String s = "s u\ney!\nao "; printVerticalToHorizontalWriting( s );
Die Ausgabe auf dem Bildschirm wird sein:
sea you!
.
Drei wichtige Annahmen sollen gelten:
Zeilen werden nur mit
\n
getrenntJede Zeile ist gleich lang; die letzte Zeile hat zum Beispiel ein Leerzeichen, damit alle Zeilen 3 Zeichen (in diesem Beispiel) lang sind (Zeilenumbruch nicht eingerechnet),
Am Ende des Strings steht kein
\n
.
1.2. Dynamische Strings mit StringBuilder
Während String
-Objekte immutable sind, lassen sich Objekte vom Typ java.lang.StringBuilder
modifizieren. Das Gleiche gilt für StringBuffer
, doch dieser Typ ist API-gleich und für die Übungen nicht relevant.
1.2.1. Strings füllen ⭐
Captain CiaoCiao liebt die Freiheit, und Abstand ist ihm sehr wichtig. Auch bei Texten, findet er, könnten die Buchstaben ruhig ein wenig mehr Abstand haben.
Aufgabe:
Schreibe eine Methode
mix(String, String)
, die einen String aufspreizt und Füllzeichen zwischen alle Zeichen setzt.Die Parameter dürfen
null
sein.
Beispiele:
mix( "We’re out of rum!", "-" )
→"W-e-'-r-e- -o-u-t- -o-f- -r-u-m-!"
mix( "Blimey", "👻" )
→"B👻l👻i👻m👻e👻y"
mix( "HI", "♥" )
→"H♥I"
mix( "♥", "!!" )
→"♥"
mix( "", "👻" )
→""
1.2.2. Mit dem Papagei das Alphabet üben ⭐
Captain CiaoCiao lehrt seinen Papagei das Alphabet. Damit er sich die Mühe spart, greift er auf eine Software zurück, die ihm das Alphabet generiert.
Gegeben ist folgende Methode:
static String abcz() {
String result;
result = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return result;
}
Die Methode liefert eine Zeichenkette mit allen Zeichen im Alphabet von 'A'
bis 'Z'
. So kann Captain CiaoCiao die Zeichenkette auf https://ttsreader.com/de/ in ein Eingabefeld kopieren und vorlesen lassen. Allerdings müssen dann zwischen den Buchstaben Leerzeichen stehen, damit die Tonausgaben besser klingen.
Die Methode ist zwar performant in ihrer Aufgabe, aber nicht sonderlich flexibel, wenn es zum Beispiel darum geht, nur gewisse Bereiche zu generieren, etwa von '0'
bis '9'
. Denn der Papagei kann ABC
schon sehr gut, aber von G
bis Z
wird es eng.
Aufgabe:
Ändere die Methode
abcz()
, sodass derString
dynamisch über eine Schleife generiert wird.Ergänze eine Methode
String abcz(char start, char end)
, die einen String mit allen Symbolen generiert, die zwischen dem Anfangsbuchstabenstart
und dem Endbuchstabenend
liegen; das Endezeichen ist inklusiv und gehört mit zum String.Schreibe dann die Methode
String abcz(char start, int length)
, dielength
Zeichen abstart
liefert. Lässt sich eine der Methoden auf die andere abbilden?Überlege, wie mit fehlerhaften Parametern umzugehen ist, wenn etwa der Endindex vor dem Startindex liegt.
Der primitive Datentyp |
1.2.3. Zahl in textuelle unäre Kodierung konvertieren ⭐
Captain CiaoCiao macht sich Sorgen um die Sicherheit seiner Crew und er möchte die Beutemenge der Raubzüge verschleiern. Dabei sollen nur zwei Symbole verwendet werden.
Die unäre Kodierung stellt eine natürliche Zahl n wie folgt dar:
n | unäre Kodierung |
---|---|
0 | 0 |
1 | 10 |
2 | 110 |
3 | 1110 |
4 | 11110 |
Eine natürliche, also positive Ganzzahl n wird dargestellt durch n Einsen, gefolgt von einer Null. Ein Code dieser Art nennt sich übrigens präfixfrei, weil kein Wort das Präfix eines anderen Wortes ist. Bei der Kodierung könnten wir auch problemlos 0 und 1 vertauschen, die Präfixeigenschaft ändert sich dadurch nicht.
Durch die unäre Kodierung entstehen unterschiedlich lange Codes.
Aufgabe:
Schreibe eine Methode
String encode(int... values)
, die aus einem Vararg-Array mit Ganzzahlen einen String erzeugt, in dem alle unärkodierten Werte aus dem Array aneinandergehängt werden.Ergänze eine Methode
int[] decode(String value)
, die aus einem unärkodierten String wieder einint
-Array macht.
Beispiel:
encode( 0, 1, 2, 3, 0, 1 )
→"0101101110010"
encode( 0, 0, 0, 0 )
→"0000"
encode()
→""
Arrays.toString( decode("0101101110010") )
→[0, 1, 2, 3, 0, 1]
1.2.4. Gewicht durch Vertauschung verlieren ⭐
Bonny Brain ist aufgefallen, dass es sich bei den Frachtgebühren prima betrügen lässt. Die Verantwortlichen im Büro vergessen oft das genaue Gewicht, können sich aber die vorkommenden Ziffern perfekt merken, und es fällt nicht auf, wenn maximal zwei Ziffern vertauscht werden. Bonny Brain nutzt das zu ihrem Vorteil, indem sie die kleinste Ziffer in der Zahl nach vorne setzt, um ein kleineres Gewicht zu erzielen. 0 muss allerdings ignoriert werden, da sich sonst die Länge der Zahl ändert, und das fällt auf.
Aufgabe:
Schreibe eine Methode
int cheatedWeight(int weight)
, die genau diese Transformation macht.
Beispiele:
cheatedWeight(0)
→0
cheatedWeight(1234)
→1234
cheatedWeight(4321)
→1324
cheatedWeight(100)
→100
cheatedWeight(987654321)
→187654329
1.2.5. Vokale entfernen ⭐
Captain CiaoCiao diktiert seine Memoiren, und es sprudelt aus ihm heraus. So schnell kann Kiko Kokopu gar nicht mitschreiben! Aber kann man nicht alle Vokale weglassen und es trotzdem später noch verstehen? Ein Sprachwissenschaftler sagte mal, dass ein Text auch nach dem Entfernen der Vokalbuchstaben noch verständlich bleibt. Als Vokalbuchstaben gelten im Deutschen: A, Ä, E, I, O, Ö, U, Ü, Y. Stimmt es, was die Wissenschaftler sagen?
Aufgabe:
Lege eine neue Klasse
RemoveVowel
an.Schreibe eine Klassenmethode
String removeVowels(String string)
, die aus einem übergebenenString
die Vokalbuchstaben entfernt. Es ist in Ordnung, wenn die Umlaute fehlen.Löse die Aufgabe mit mindestens zwei verschiedenen Varianten.
Beispiele:
"Hallo Javanesen"
→"Hll Jvnsn"
"BE NICE"
→"B NC"
1.2.6. Don’t shoot the Messenger ⭐
Bonny Brain übermittelt eine geheime Nachricht und hat Angst, dass der Bote überfallen und die Nachricht dadurch offenbart wird. Also schickt sie mehrere Boten, die jeweils einen Teil der Nachricht zustellen. Das Schema ist wie folgt:
Ein Text wird in Buchstaben zerlegt
Bote 1 bekommt den 1. Buchstaben
Bote 2 bekommt den 2. Buchstaben
Bote 1 bekommt den 3. Buchstaben
Bote 2 bekommt den 4. Buchstaben
usw.
Der Empfänger der Nachricht muss nun auf die beiden Boten warten, die ursprüngliche Reihenfolge kennen und die Nachricht wieder zusammensetzen.
Aufgabe:
Schreibe eine Methode
String joinSplitMessages(String...)
, die eine beliebige Anzahl der zerlegten Botschaften entgegennimmt und den zusammengesetzten String zurückgibt.Falls Nachrichtenteile fehlen, soll das zu keinem Fehler führen.
Beispiele:
joinSplitMessages("Hoy", "ok")
→"Hooky"
joinSplitMessages("Hooky")
→"Hooky"
joinSplitMessages("Hk", "oy", "o")
→"Hooky"
joinSplitMessages( "H", "", "ooky" )
→"Hooky"
1.2.7. Wiederholte Leerzeichen komprimieren ⭐⭐
Bubbles hört für Captain CiaoCiao ein Gespräch ab und transkribiert es. Doch weil Bubbles immer so viele Erdnüsse schält, ist die Leertaste verklemmt und löst sich schlecht; so verdoppelt sich schnell ein Leerzeichen. Auf keinem Fall kann sie so den Text Captain CiaoCiao geben.
Aufgabe:
Schreibe eine statische Methode
StringBuilder compressSpace(StringBuilder string)
, die mehr als zwei Leerzeichen im übergebenenstring
zu einem Leerzeichen zusammenschmelzen lässt.Die Übergabe
string
soll mitreturn string;
zurückgegeben werden, die Veränderung soll direkt amStringBuilder
erfolgen.
Beispiel:
"Will you shut up, man! This is the way!"
→"Will you shut up, man! This is the way!"
1.2.8. Knacken und Knistern einfügen und entfernen ⭐
Meldungen über Funk haben oft ein Knistern, das stört Captain CiaoCiao.
Aufgabe:
Schreibe zwei Methoden:
String crackle(String)
soll in willkürlichen Abständen »♬CRACK♪« einbauen und den Knisterstring zurückgeben.String decrackle(String)
soll das Knistern wieder entfernen.
1.2.9. CamelCase-Strings zerlegen ⭐
Um bei der telegrafischen Übertragung von Text Volumen einzusparen, wendet Funker Frogfish einen Trick an: Er schreibt das nächste Zeichen hinter dem Leerzeichen groß und löscht dann das Leerzeichen. Aus ciao ciao
wird ciaoCiao
. Ist das nächste Zeichen schon ein Großbuchstabe, wird einfach nur das Leerzeichen entfernt, aus Ciao Ciao
wird so CiaoCiao
. Da die Großbuchstaben innerhalb der Serie von Kleinbuchstaben wie Höcker aussehen, wurde die Schreibweise CamelCase getauft.
Captain CiaoCiao empfängt die Zeichenfolgen, aber leicht zu lesen ist so ein Text nicht.
Aufgabe:
Schreibe eine neue Methode
String camelCaseSplitter(String)
, die alle CamelCase-Segmente wieder trennt.
Beispiele:
camelCaseSplitter("List")
→"List"
camelCaseSplitter("CiaoCiao")
→"Ciao Ciao"
camelCaseSplitter("numberOfElements")
→"number Of Elements"
camelCaseSplitter("CiaoCiaoCAPTAIN")
→"Ciao Ciao CAPTAIN"
Falls Wörter komplett in Großbuchstaben sind, wie im letzten Fall, gilt nur der Wechsel zwischen Klein- und Großbuchstaben.
1.2.10. Wörter unterstreichen ⭐⭐
Immer wieder muss Bonny Brain die Crew auf Regeln aufmerksam machen. Sie schreibt dazu eine Nachricht und unterstreicht die wichtigen Wörter. Bonny Brain hat im folgenden Text das Wort »treasure« unterstrichen:
There is more treasure in books than in all the pirates' loot on Treasure Island -------- --------
Aufgabe:
Lege eine neue Klasse
PrintUnderline
an.Schreibe eine neue statische Methode
printUnderline(String string, String search)
, die jede Zeichenkettesearch
instring
wie im oberen Beispiel gezeigt unterstreicht. Bedenke, dasssearch
mehrmals im String vorkommen kann oder auch keinmal.Die Groß-/Kleinschreibung des Such-Strings soll keine Rolle spielen, wie es auch das Beispiel zeigt.
1.2.11. Caesar-Verschlüsselung implementieren ⭐⭐⭐
Captain CiaoCiao hat von einer Verschlüsselung erfahren, die schon Gaius Julius Caesar verwendet haben soll. Da er den römischen Feldherrn bewundert, will auch er seine Texte so verschlüsseln.
Bei der sogenannten Caesar-Verschlüsselung verschiebt man jedes Zeichen um drei Positionen im Alphabet, das heißt, aus A
wird D
, aus B
wird E
und so weiter. Am Ende des Alphabets beginnen wir wieder von vorne, und so ergibt X
→ A
, Y
→ B
, Z
→ C
.
Aufgabe:
Lege eine neue Klasse
Caesar
an.Implementiere eine Methode
String caesar(String s, int rotation)
, die die Verschlüsselung vornimmt.rotation
ist dabei die Verschiebung, die beliebig sein sollte, nicht nur 3 wie aus dem Eingangsbeispiel.Schreibe eine Methode
String decaesar(String s, int rotation)
, die die Verschlüsselung wieder zurücknimmt.Die Caesar-Verschlüsselung fällt in die Klasse der Verschiebechiffren. Ist sie Captain CiaoCiao zu empfehlen?
Beispiel:
caesar( "abxyz. ABXYZ!", 13 )
→"noklm. NOKLM!"
decaesar( caesar( "abxyz. ABXYZ!", 13 ), 13 ) )
→"abxyz. ABXYZ!"
Noch mehr Aufgaben findest du im Buch: ›Captain CiaoCiao erobert Java: Das Trainingsbuch für besseres Java. 300 Java-Workshops, Aufgaben und Übungen mit kommentierten Lösungen‹