C++ Programmieren mit einfachen Beispielen DIRK LOUIS
Kapitel 6 Wenn Sie jetzt noch in Gedanken alle Vorkommen von basic_string& oder const basic_string& in string und alle Vorkommen von size_type in int umwandeln, werden die Definitionen doch gleich wesentlich verständlicher. Betrachten wir zum Beispiel die erste Definition, die in Abbildung 6.11 markiert ist und sich nach den Ersetzungen wie folgt liest: string replace(int pos1, int n1, string str); Diese Methode ersetzt einen Teil des aktuellen Strings durch den String, der ihr als drittes Argument (str) übergeben wird. Der zu ersetzende Teilstring wird durch die int-werte für die beiden ersten Parameter festgelegt. pos1 übergeben Sie die Position des ersten zu ersetzenden Zeichens im String, wobei zu beachten ist, dass die Position des ersten Zeichens im String 0 lautet. n1 übergeben Sie die Anzahl der zu ersetzenden Zeichen. 6 Rufen Sie für den String ausgabe die Methode replace() auf. // Ersetzen.cpp #include <iostream> #include <string> using namespace std; int main() { string ausgabe = "Hallo Dirk, wie geht es Dir?"; string name = "Sean"; ausgabe.replace( cout << ausgabe << endl; } return 0; Die Methoden der Klasse string können nur für Variablen der Klasse string aufgerufen werden. Man gibt also zuerst die Variable an, die bearbeitet werden soll, und hängt dann mit einem Punkt den Aufruf der Methode an. Der Aufruf ausgabe.replace() bedeutet also, dass Sie einen Teil des Strings ausgabe ersetzen wollen. 116
Mit Strings arbeiten 7 Geben Sie an, ab welchem Zeichen ersetzt werden soll. // Ersetzen.cpp #include <iostream> #include <string> using namespace std; int main() { string ausgabe = "Hallo Dirk, wie geht es Dir?"; string name = "Sean"; } ausgabe.replace(6, cout << ausgabe << endl; return 0; Zählen Sie ab dem Zeichen H und beginnen Sie mit 0. Der erste zu ersetzende Buchstabe (das D) hat dann die Position 6, die Sie als erstes Argument an replace() übergeben. 8 Geben Sie an, wie viele Zeichen ersetzt werden sollen. // Ersetzen.cpp #include <iostream> #include <string> using namespace std; int main() { string ausgabe = "Hallo Dirk, wie geht es Dir?"; string name = "Sean"; } ausgabe.replace(6, 4 cout << ausgabe << endl; return 0;»Dirk«hat vier Zeichen, weswegen wir als zweites Argument 4 übergeben. 117
Kapitel 6 9 Geben Sie den String an, der eingefügt werden soll, und schließen Sie den Methodenaufruf mit einer runden Klammer und dem Semikolon ab. // Ersetzen.cpp #include <iostream> #include <string> using namespace std; int main() { string ausgabe = "Hallo Dirk, wie geht es Dir?"; string name = "Sean"; } ausgabe.replace(6,4, name); cout << ausgabe << endl; return 0; Der String, der eingefügt werden soll, steht in der string-variablen name, die wir folglich als letztes Argument übergeben. 10 Kompilieren Sie das Programm und führen Sie es aus. Abbildung 6.12: Ausgabe des Strings nach Ersetzung des Namens In ähnlicher Weise verwendet man die weiteren Methoden der Klasse string hier eine kleine Auswahl: string insert(int pos, string str) Fügt den String str vor der Position pos in den aktuellen String ein. 118
Mit Strings arbeiten string ausgabe = "Hallo Dirk, wie geht es?"; ausgabe.insert(10, " und Sean"); cout << ausgabe << endl; Ausgabe: Hallo Dirk und Sean, wie geht es? string erase(int pos, int n) Entfernt ab der Position pos n Zeichen aus dem String. string ausgabe = "Hallo Dirk, wie geht es?"; ausgabe.erase(5, 5); cout << ausgabe << endl; Ausgabe: Hallo, wie geht es? int find(string str, int pos) Sucht im aktuellen String ab der Position pos nach dem ersten Vorkommen des Teilstrings str und liefert die Anfangsposition des Teilstrings zurück. string ausgabe = "Hallo Dirk, wie geht es?"; int pos; pos = ausgabe.find("dirk", 0); cout << pos << endl; Ausgabe: 6 string substr(int pos, int n) Liefert eine Kopie eines Teilstrings zurück. Der Teilstring beginnt bei Position pos und umfasst n Zeichen. string ausgabe = "Hallo Dirk, wie geht es?"; string str; str = ausgabe.substr(6, 4); cout << str << endl; Ausgabe: Dirk 119
Kapitel 6 Vertiefung: Speicherverwaltung für Strings Wenn Sie in Kapitel 5 den Abschnitt zur Speicherbelegung für die elementaren Datentypen gelesen haben (»Die Bedeutung des Datentyps«), werden Sie sich vielleicht fragen, wie denn die Speicherbelegung für Strings aussieht. Abbildung 6.13: Ein String im Arbeitsspeicher (jedes Zeichen belegt eine bestimmte Bitzahl, üblicherweise 8 Bit = 1 Byte 4 ) Strings werden einfach Zeichen für Zeichen hintereinander im Speicher abgelegt. Damit der Compiler weiß, wo der String endet, muss man am Ende des Strings das Terminierungszeichen \0 anhängen. Hinweis Müssten wir dann nicht alle unsere Strings mit dem Terminierungszeichen \0 abschließen? Nein! String-Konstanten werden automatisch vom Compiler mit einem Terminierungszeichen abgeschlossen, und bei der Manipulation von string-variablen sorgt die Implementierung der Klasse string dafür, dass die Strings immer korrekt mit dem Terminierungszeichen abgeschlossen werden. Problematisch wird es, wenn in einer string-variablen ein String wie»hallo«gespeichert ist, der Variablen dann aber ein String»Herzlich willkommen«zugewiesen oder ein String» Dirk«angehängt wird. string str = "Hallo"; str = "Herzlich willkommen"; oder str += " Dirk"; Das Problem hierbei besteht natürlich darin, dass sich der String, der in der Variablen gespeichert werden soll, vergrößert. Nun wissen wir aber aus Kapitel 5, dass es nicht möglich ist, den für eine Variable reservierten Speicher nachträglich zu vergrößern. Trotzdem haben Sie gesehen, dass man string- Variablen neue Strings zuweisen, andere Strings anhängen oder einfügen, und Teilstrings entfernen kann. Wie ist dies möglich? 4 Mittlerweile werden die Zeichen nach dem allgemeinen UNICODE-Standard codiert (der auch arabische und asiatische Zeichen umfasst). Dann benötigt man zur Codierung eines Zeichens mindestens 24 Bit (manche Systeme reservieren gleich 32 Bit). 120
Rätselhaftes C++ Die Lösung dieses Rätsels liegt in der Implementierung der Klasse string verborgen. Wenn Sie beispielsweise einer string-variablen einen neuen String zuweisen, reserviert die Klasse zur Laufzeit einen komplett neuen Speicherbereich für den String. Der alte Speicherbereich wird freigegeben und die string-variable wird mit dem neuen Speicherbereich verbunden. Als Fazit können wir feststellen, dass uns die Klasse string nicht nur eine Reihe von leistungsfähigen Methoden zur Bearbeitung von Strings zur Verfügung stellt, sondern uns auch von lästigen Aufgaben, wie der Speicherverwaltung oder dem Anhängen des Terminierungszeichen, befreit. Rätselhaftes C++ C++ kennt viele leistungsfähige Operatoren, ja man könnte sagen, C++-Entwickler haben ein Faible für die Programmierung mit Operatoren. Dies hält sie jedoch nicht davon ab, es gelegentlich zu übertreiben. Dann entstehen Stilblüten wie die Folgende: int m = 10; int n = 5; int erg; erg = (++m)+++(++n+1); Können Sie voraussagen, welchen Wert erg nach Ausführung der Zuweisung hat? Lösung: 18. Zuerst wird der Inhalt der ersten Klammer berechnet, d.h. m wird um 1 auf 11 erhöht. m wird dann noch ein weiteres Mal erhöht (nachgestellte Version von ++), im aktuellen Ausdruck lautet das Zwischenergebnis aber weiter 11. Zu diesem wird der Wert der zweiten Klammern (++n+1 gleich 7) hinzuaddiert. Als Ergebnis wird erg der Wert 18 zugewiesen. Gute Programmierer hätten aus obiger Zeile zumindest einen Zweizeiler gemacht: erg = ++m + (++n+1); m++; 121
Kapitel 7 Daten einlesen und ausgeben Die meisten Programme sind darauf angewiesen, dass sie Daten mit den Anwendern austauschen. Das heißt, sie nehmen die zu verarbeitenden Daten über die Tastatur entgegen und geben ihre Ergebnisse auf die Konsole aus. Wie das geht, sehen wir uns in diesem Kapitel an.
Kapitel 7 Daten einlesen In Kapitel 4 haben wir gelernt, dass man Daten auf die Konsole ausgibt, indem man sie mithilfe des <<-Operators an cout schickt. Analog kann man Daten einlesen, indem man sie von cin entgegennimmt und mithilfe des >>-Operators in Variablen schreibt. Was ist das? cout und cin sind Elemente aus der C++-Laufzeitbibliothek und repräsentieren die Standardausgabe (cout) beziehungsweise die Standardeingabe (cin). Beide Elemente sind in der Headerdatei iostream deklariert. int zahl; cin >> zahl; oder string str; cin >> str; Sie sehen, Daten einzulesen ist gar nicht schwer. Man sollte aber darauf achten, dass man vor jedem Einlesen eine Meldung an den Anwender ausgibt, die ihn darauf hinweist, was für Daten er eingeben soll. Hinweis Denken Sie daran, dass Sie zur Arbeit mit der Klasse string die Headerdatei string einbinden müssen. Als Beispiel greifen wir das Programm fahrenheit.cpp aus Kapitel 6, Abschnitt»Mathematische Formeln ausrechnen«auf. 1 Beginnen Sie ein neues Programm (siehe Kapitel 3) und tippen Sie den Code des Fahrenheitprogramms aus Kapitel 6, Abschnitt»Mathematische Formeln ausrechnen«, ein. // Fahrenheit.cpp #include <iostream> using namespace std; int main() { 124
Daten einlesen double fahrenheit; double celsius; } fahrenheit = 20; celsius = (fahrenheit - 32) * 5.0 / 9.0; cout << fahrenheit << " Grad Fahrenheit entsprechen " << celsius << " Grad Celsius" << endl; return 0; Mit diesem Programm kann man sich eine Temperaturangabe in Fahrenheit in Grad Celsius umrechnen lassen. Das Programm ist insofern aber unpraktisch, als man für jeden Fahrenheit-Wert, den man umrechnen lassen möchte, den Quelltext laden, der Variablen fahrenheit einen anderen Wert zuweisen und das Programm neu kompilieren und ausführen muss. Ein solches Programm kann man nicht mal seinen Freunden zur Verfügung stellen, da diese ohne C++-Compiler praktisch nichts damit anfangen können (außer sich 20 Grad Fahrenheit hundert Mal in Grad Celsius umrechnen zu lassen). Wenn wir das Programm allerdings dahingehend erweitern, dass der Fahrenheit-Wert vom Anwender abgefragt wird, erhalten wir ein sinnvolles Programm, mit dem man sich jeden beliebigen Fahrenheit-Wert in Celsius umrechnen kann. 2 Fordern Sie den Anwender auf, den Fahrenheit-Wert einzugeben: // Fahrenheit.cpp #include <iostream> using namespace std; int main() { double fahrenheit; double celsius; cout << "Temperatur in Fahrenheit: "; 125
Copyright Daten, Texte, Design und Grafiken dieses ebooks, sowie die eventuell angebotenen ebook-zusatzdaten sind urheberrechtlich geschützt. Dieses ebook stellen wir lediglich als persönliche Einzelplatz-Lizenz zur Verfügung! Jede andere Verwendung dieses ebooks oder zugehöriger Materialien und Informationen, einschließlich der Reproduktion, der Weitergabe, des Weitervertriebs, der Platzierung im Internet, in Intranets, in Extranets, der Veränderung, des Weiterverkaufs und der Veröffentlichung bedarf der schriftlichen Genehmigung des Verlags. Insbesondere ist die Entfernung oder Änderung des vom Verlag vergebenen Passwortschutzes ausdrücklich untersagt! Bei Fragen zu diesem Thema wenden Sie sich bitte an: info@pearson.de Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfügungstellung dieser Daten auf unseren Websites ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen. Hinweis Dieses und viele weitere ebooks können Sie rund um die Uhr und legal auf unserer Website herunterladen: http://ebooks.pearson.de