Strings

Im Zeichen der Zeichenketten

Stell dir das mal nur vor: Du entwirfst einen eigenen Internetübersetzer, programmierst ein Schreibprogramm und veröffentlichst ganz nebenbei noch ein Text-Adventure-Spiel. Klingt nach dem aufregenden Leben eines IT-Rockstars, nicht? Und sei dir gewiss: Nach diesem Kapitel bist du bestens ausgerüstet, um diese ambitionierten Projekte gleich in Angriff zu nehmen. 


Na gut, vielleicht gestaltet sich der Weg bis dahin wohl doch etwas schwieriger als gedacht... Aber immerhin wirst du nach der Lektüre dieses Kapitels den ersten kleinen Schritt in eine aufregende Programmierwelt getan haben. Und wer weiß – wenn du auf diesem Fundament aufbaust, werden wir vielleicht in naher Zukunft mal alle deinen Internetübersetzer benutzen. 


Aber genug der Träumerei, starten wir in das Kapitel „Strings“. Ein merkwürdiges Wort – man kann es mit „Fäden“ oder „Schnur“ übersetzen und einige mögen da sogar an obszöne Dinge denken. Tatsächlich tun aber Strings nichts anderes, als die Palette an bisher bekannten Datentypen zu erweitern. Womit konnte dein Computer nämlich bisher arbeiten? Mit Zahlen (int, float, double), mit Zeichen (char) und Wahrheitswerten (bool). Aber irgendwie fehlt da noch ein wichtiges Objekt, mit dem man in der Informatik-Welt tagtäglich hantiert: Wörter und Texte. Und genau das ermöglichen dir Strings: Die Arbeit mit längeren Texteinheiten, oder besser gesagt: Zeichenketten


Könnte man so einfach Variablen vom Datentyp „string“ benutzen, hätten wir es sicherlich schon im ersten Kapitel erwähnt. An sich kennt der Compiler diesen Datentyp nämlich nicht. Intern ist dieser Datentyp ein Array vom Typ char. Darin werden buchstabenweise die Texte gespeichert, das Zeichen, mit dem das Ende des Strings gekennzeichnet wird, ist "\0". Das klingt zunächst sehr umstnädlich, aber für das Speichern und Verarbeiten von Strings sind eine Menge nützlicher Methoden vordefiniert. Für die Benutzung von Strings und von Methoden zur Verabrietung von Strings musst du eine spezielle Bibliothek benutzen:


    #include <string>


Wenn du nun also vorhast, Strings in deinem Code zu verwenden, darfst du nicht vergessen, die Bibliothek am Anfang deines Programms einzubinden.


In erster Linie kann mit Strings wie mit anderen Datentypen umgegangen werden. Das Deklarieren und die Wertezuweisung an Variablen funktionieren bei Strings haargenau so wie auch bei Integern oder float-Werten:


    string wohnort;

    string studienort;


    wohnort=“Hamburg“;

    studienort=“Rostock“;


Bei der Wertzuweisung musst du jedoch auf die Anführungszeichen (" ") Acht geben.


Da es ziemlich sinnlos ist, mit Wörtern arithmetische Operationen durchzuführen, sind diese auf Strings gar nicht erst definiert. Einzige Ausnahme bildet da der Vergleichsoperator, wie das folgende Programm zeigt:


    if (wohnort==studienort) {

        cout << "Wohn- und Studienort stimmen überein.“ << endl;

    }


Auch die Ausgabe eines Strings lässt sich problemlos umsetzen. Aufpassen musst du nur bei der Eingabe von Strings. Hier stehen dir nämlich zwei Varianten zur Verfügung. Bei der ersten wird die Eingabe wie gewohnt mit dem Befehl „cin“ realisiert. Diese Möglichkeit eignet sich aber nur, wenn du einzelne Wörter eingeben willst! Bei der Eingabe eines Leerzeichens wird die Ausführung des Befehls beendet und das Programm fortgesetzt. Möchtest du hingegen ganze Texte eingeben, eignet sich da der Befehl „getline“. Mache dir seine Anwendung im folgenden Programmbeispiel klar:


    string text;

    getline(cin, text);


Die Eingabe wird bei diesem Befehl erst mit dem Drücken der Enter-Taste beendet. 


Die String-Bibliothek erlaubt dir nicht allein die Verwendung von Strings, sondern kommt mit einer Reihe von vordefinierten Funktionen daher, die das Programmieren mit Strings erst spannend machen. Im Folgenden sind die wichtigsten und am häufigsten verwendeten Funktionen aufgelistet:


- size(): Dieser Befehl liefert dir die Länge eines gespeicherten Strings als Integer zurück. 


    string ort=“Berlin“;

    ort.size();  // gibt den integer-Wert 6 zurück


- at(index): Mit dieser Funktion kannst du dir den Buchstaben eines Strings an der Position index zurückgeben lassen. Wichtig: Der Compiler beginnt das Zählen bei 0 (genauso wie wir das schon bei Arrays gesehen haben.)!


    string ort=“Berlin“;

    ort.at(3);  // liefert "l“


- find(searchstring, startposition): Möchtest du die Stelle ermitteln, an der ein searchstring in einem größeren Text zum ersten Mal auftaucht, solltest du diesen Befehl benutzen. Soll die Suche an einer bestimmten Stelle beginnen, kannst du eine startposition angeben. Ansonsten kann dieser Parameter weggelassen werden. Zurückgegeben wird ein Integer (die Position des searchstring), ist die gesuchte Zeichenkette nicht vorhanden, wird  der Wert -1 geliefert.


    string firma=“Universität Rostock“;

    firma.find(„Rostock“); // gibt 13 aus;


- rfind(searchstring): Oft ist es hilfreich, die Position des letzten Auftretens eines Wortes zu ermitteln. Dies gelingt dir mit diesem Befehl, der dir eben jene Position des letzten Auftretens des searchstrings zurückgibt.


    string lustigerSatz=“Informatik ist toll. Alle lieben Informatik.“;

    lustigerSatz.rfind("Informatik“);  // liefert den Wert 33


- append(substring): Mit diesem Befehl wird an einen vorhandenen String ein substring angehängt.


    string ort=“Hansestadt Rostock“;

    ort.append(„ ,Mecklenburg-Vorpommern“);


- replace(position, laenge, substring): In einem größeren String wird ein Ausschnitt an einer bestimmten position mit seiner bestimmten laenge durch einen substring ersetzt.


    string ort=“Hansestadt Rostock“;
    ort.replace(5, 0, "- und Universitaetsstadt“);


-insert(position, substring): Dieser Befehl bewirkt, dass in einem String ein neuer substring direkt vor der angegebenen position eingefügt wird.


    string ort=“Hansestadt Rostock“;

    ort.insert(5, "- und Universitaets“); // Die Variable "ort“ enthält nun den String "Hanse- und Universitaetsstadt Rostock

(Diese Umbenennung erfolgte in unserer Stadt kürzlich, elektronisch in allen Dokumenten ist diese viel einfacher umsetzbar als auf den Ortsschildern. )

-substr(startposition, laenge): Anwendung findet dieser Befehl, wenn aus einem größeren String ein Teilstring herauskopiert werden soll. startposition gibt an, an welcher Stelle der Kopierprozess beginnen soll, laenge beschreibt, wie lang der kopierte Teilstring werden soll. Soll der gesamte String kopiert werden, kann laenge weggelassen werden.


    string ort=“Hansestadt Rostock“;

    string ausschnitt;

    ausschnitt=ort.substr(0,10); // im String "ausschnitt“ befindet sich nun die Zeichenkette                                                             "Hansestadt“


Besonderes Augenmerk wollen wir noch dem Befehl „compare“ schenken. Wer dem Englischen mächtig ist, wird ahnen, dass man mit dieser Funktion zwei Strings vergleichen kann. compare liefert dabei verschiedene Werte zurück. Sind die zu vergleichenden Strings gleich, spuckt compare eine 0 aus. Ist dem nicht so, wird compare eine Zahl kleiner oder größer 0 ausgeben, je nachdem, welcher String im Alphabet vor dem anderen steht. Ein kleines Programm soll die Verwendung veranschaulichen:


    string abschlussTina=“Bachelor Informatik“;

    string abschlussBenedikt=“Bachelor Mathematik“;


    if (abschlussTina.compare(abschlussBenedikt)==0){

        cout << "Beide haben den gleichen Abschluss in demselben Studiengang.“ << endl;

    }


Diese if-Anweisung wird nicht bearbeitet, da die zwei deklarierten Strings sich unterscheiden und der Befehl „compare“ dementsprechend keine 0 zurückgibt. „compare“ kann jedoch durch die zusätzliche Angabe einer Position und einer Länge Gleichheit auf einen Teilstring überprüfen:


    if (abschlussTina.compare(8, 10, "Informatik“)==0){

        cout << "Tina hat Informatik studiert.“ << endl;

    }


An Indexposition 8 werden die nachfolgenden zehn Zeichen mit dem Teilstring "Informatik“ verglichen.


Soweit unser Einblick in die Welt der Strings. Da wir das Kapitel ungern mit einer schlechten Kalauer à la „Mit Strings hast du die Fäden in der Hand“ schließen wollen, sagen wir einfach: Ab ans Üben!

Aufgaben: Strings

A1: Quiz dich schlau!

Created with Sketch.

Nachfolgend sind einige Fragen aufgeführt, die du nach diesem Abschnitt beantworten können solltest:

(1) Definiere bitte eine Variable zur Speicherung einer Zeichenkette!

(2) Wie erkennt ein Compiler das Ende einer Zeichenkette?

(3) Welche Methoden der Klasse string kennst du, die den Zugriff auf Zeichenketten unterstützen?

A2: Esperanto traduki!

Created with Sketch.

Sie wurde entwickelt, um die Kommunikation verschiedener Nationalitäten zu vereinfachen: die Plansprache Esperanto. Ein Wörterbuchverlag möchte das große Potential dieser Sprache aufgreifen. Der Verlag hat dich engagiert, damit du ein Übersetzungsprogramm in C++ schreibst.
Ein paar Beispiele in dieser Sprache sind:

birdo - Vogel
traduki - uebersetzen
flava - gelb
suno - Sonne
kaj - und


Schreibe bitte ein kleines Übersetzungsprogramm, das diese 5 Wörter in einem Text in Esperanto übersetzt. Das Programm soll einen Text auf deutsch einlesen und die entsprechenden Übersetzungen in Esperanto ausgeben.

A3: Caesar Chiffre

Created with Sketch.

Um geheime Nachrichten übermitteln zu können werden seither kniffelige Verschlüsselungstechniken verwendet. Ein einfaches Beispiel ist die Caesar-Chiffre. Mit ihr werden die Zeichen eines Textes um eine verabredete Länge gemäß des Alphabets verschoben. So wird ein um 2 Positionen verschobenes 'a' ein 'c'.
Schreibe bitte ein Chiffre-Programm, dass einen Text einliest und dessen Symbole um eine definierte Position innerhalb der ASCII-Tabelle verschiebt.

A4: IBAN entschlüsseln

Created with Sketch.

Die IBAN-Angaben werden von allen Banken und Finanzinstituten verwendet und sind europaweit einheitlich aufgebaut. Sie enthalten 22 Stellen, die ersten beiden geben das Land an, bei Geldinstituten in Deutschland steht hier 'D' gefolgt von 'E' in der IBAN. Dann folgen 2 Prüfzeichen, anschließend 8 Zeichen der Bankleitzahl und  danach die 10 Zeichen der Kontonummer. Hilf deiner Bank und schreibe bitte ein Programm, das eine IBAN einlist, ausgibt, ob es sich um eine Inlandsueberweisung oder Auslandsueberweisung handelt und anschließend die BLZ und die Kontonummer ausgibt. 

A5: Eiersalat

Created with Sketch.

Olaf möchte für seine Grillparty einen Eiersalat machen. Dabei fallen ihm Codes auf den Eiern auf:
0-DE-1344461
Nach einer kurzen Recherche findet er den Generierungsalgorithmus heraus:
1. Haltungsform (0 - Bio-Haltung; 1 - Freilandhaltung; 2 - Bodenhaltung)
2. Ländercode (DE - Deutschland; NL - Niederlande)
3. Bundesland (01 - Schleswig-Holstein; 12 - Brandenburg; 13 - MV)
4. Betriebsnummer

Schreibe bitte ein C++-Programm, das die Eierkennzeichnung (mit Bindestrichen) einliest und die Haltungsform, das Land sowie Bundesland ausgibt. Dabei brauchen nur die oben genannten Beispiele berücksichtigt werden.
Tipp: Nutze die ASCII-Codierung.

Zusatzaufgabe: Wo kommen die Eier her, die in deinem Kühlschrank sind?

Musterlösungen

L1: Quiz dich schlau!

Created with Sketch.

(1) string beispieltext;

(2) Das Ende einer Zeichenkette wird mit dem Symbol "\0" markiert.

(3) size(), at(index), find(searchstring), replace(pos, len, substring), insert(position, substring), compare(string2), ...

L2: Esperanto traduki!

Created with Sketch.

#include <string>
#include <string>
#include <iostream>
using namespace std;

int main() {
    string text;
    cout << "Bitte gib den zu uebersetzenden Text auf deutsch ein : ";
    getline(cin, text);

     int index, len;
     do {
         index = text.find("Vogel");
         len = size("Vogel")- 1;
         if (index != -1) {
             text.replace(index, len, "birdo");
         }
     } while (index != -1);
    do {

         index = text.find("gelb");
         len = size("gelb")- 1;
         if (index != -1) {
             text.replace(index, len, "flava");
         }
     } while (index != -1);
    do {
         index = text.find("Sonne");
         len = size("Sonne")- 1;
         if (index != -1) {
             text.replace(index, len, "suno");
         }
     } while (index != -1);
    do {

         index = text.find("und");
         len = size("und")- 1;
         if (index != -1) {
             text.replace(index, len, "kaj");
         }
     } while (index != -1);
     ...  / usw.
    cout << "Uebersetzung" << text;
    return(0);
}


// auch das ist ein Programm, auf das wir nach dem nächsten Kapitel noch einmal zurückkommen werden, Grund ist, dass wir bisher immer die gleichen Befehle im Quelltext wiederholen, wir benötigen also noch die Möglichkeit, ein Wörterbuch  zu speichern

L3: Caesar Chiffre

Created with Sketch.

#include <string>
#include <iostream>
using namespace std;

int main() {
    string text;
    int verschiebung;
    char buchstabe;
   

    cout << "Caesar‐Chiffrierung: " << endl << endl;
    cout << "Bitte einen Text eingeben: ";
    getline(cin, text);
    
    cout << endl << "Um wie viele Stellen soll der Text verschoben werden? ";
    cin >> verschiebung;
    cout << endl << endl;
    // hier wird ausgenutzt, dass man mit den ASCII-Kodierungen jedes Buchstaben auch rechnen kann, 'a'+2 ist beispielsweise die ASCII-Kodierung von 'c'

    for (int i = 0; i < text.size(); i++) {
        buchstabe = text.at(i) + verschiebung;
        cout << buchstabe;
    }
    
    return(0);
}

L4: Bankleitzahlen entschlüsseln

Created with Sketch.

#include <iostream>
#include <string>
using namespace std;

int main() {
    string iban;

    cout << "Bitte die IBAN eintippen: ";
    getline(cin, iban);
   
    string land = iban.substr(0, 2);
    if (land == "DE") {
        cout << endl << "Inlandsueberweisung " << endl;
    }
    else {
        cout << endl << "Auslandsueberweisung " << endl;
    }
   
    string blz = iban.substr(4, 8);
    cout << "Bankleitzahl: " << blz << endl;

    string knr = iban.substr(12, 10);
    cout << "Kontonummer: " << knr << endl;

    return 0;
}
   

L5: Eiersalat

Created with Sketch.

#include <iostream>
#include <string>
using namespace std;

int main() {
    string eiercode;
    cout << "Bitte den Eiercode eintippen: ";
    getline(cin, eiercode);

    cout << endl << "Bedeutung: ";
    char zeichen = eiercode.at(0);
    if (zeichen == '0') { 
        cout << "Bio-Haltung, "; 
    }
    else if (zeichen == '1') { 
        cout << "Freilandhaltung, "; 
    }
    else if (zeichen == '2') {
        cout << "Bodenhaltung, ";
    }
    else {
        cout << "Nicht in Datenbank vorhanden, ";
    }
 
    string land = eiercode.substr(2, 2);
    if (land == "DE") {
        cout << "Deutschland, ";
    }
    else if (land == "NL") {
        cout << "Niederlande, ";
    }
    else {
        cout << "Nicht in Datenbank vorhanden, ";
    }
 
    string bundesland = eiercode.substr(5, 2);
    if (bundesland == "01") {
        cout << "Schleswig-Holstein";
    }
    else if (bundesland == "12") {
        cout << "Brandenburg";
    }
    else if (bundesland == "13") {
        cout << "Mecklenburg-Vorpommern";
    }
    else {
        cout << "Nicht in Datenbank vorhanden";
    }
    return 0;
}

Fragen, Anregungen?

Ist etwas unverständlich oder du hast Fragen zu einem Thema, Aufgabe oder einfach zur C++-Welt? 
Dann schreibe uns einfach eine Mail!