[Home]
für Einsteiger!
Seite:  [1] - Drucken

Inhalt:


Durchatmen - Zusammenfassung des ersten Teils


[drucken]

C++ Allgemein

  • C++ ist eine Programmiersprache (Hochsprache)
  • Ein Programm wird als Quelltext in einen Texteditor geschrieben und dann mit einem Compiler übersetzt:
    • Präprozessor (Fügt Code aus Headern etc. ein)
    • Compiler (Übersetzt den Quellcode in Maschinensprache)
    • Linker (Bindet zusätzliche Funktionen, wie Bibliotheken, ein!
    • Da Linker und Präprozessor nahezu immer beim Compiler dabei sind, kann man vereinfacht folgende Darstellung verwenden:
      Funktionsweise des Compilers
    • Richtiger:
      Diagramm zum Kompilieren
    • Und:
      Funktionsweise des Linkers
  • Ein Programm bekommt vom Linker einen Betriebssystemabhängigen Startcode!
  • Als Syntax bezeichnet man die Struktur eines Kommandos
  • Um die Arbeit einfacher zu gestalten nutzen einige Leute lieber IDE's, also graphische Entwicklungsumgebungen. Eine solche IDE bringt meist selber einen Compiler mit, der Compiler kann allerdings oft ausgetauscht werden.
  • Ein kompiliertes C++-Programm kann nicht wieder in Quellcode umgewandelt werden, allerdings können Werte und Zeichenketten trotzdem "wiederhergestellt" werden!

Programmaufbau

  • Ein C++-Programm braucht eine "main()"-Funktion!
    • muss einen "int" zurückgeben! ("int main" und "return #;")
    • muss keinen, 1, 2 oder 3 Parameter haben
      Quelltext
      1. int main();
      2. int main(int argc); //Selten, aber möglich
      3. int main(int argc, char *argv[]);
      4. int main(int argc, char *argv[], char *env[]);
      5. //Sehr selten, nur auf einigen Systemen sinnvoll
      6.  
      7. /*
      8. argc ist die Anzahl der Parameter.
      9. argv[0] ist das, was der Nutzer getippt hat,
      10.   um das Programm zu starten.
      11. argv[1 bis argc-1] speichert die Parameter.
      12. env[] speichert die Environment-Variablen.
      13. */
      14.  
    • ist der Startpunkt des Programms, hier beginnt die Ausführung.
  • Innerhalb der "main()"- oder einer anderen Funktion können Funktionen aufgerufen werden, die vor diesem Punkt in der Quellcodedatei stehen. Ein Prototyp reicht aus (s. Funktionen)
  • Fehler werden entweder beim Compilieren gefunden (Compiletime error) oder bei der Ausführung (Runtime error)
  • Anweisungen stehen immer in Blöcken, die mit geschweiften Klammern ("{}") definiert werden. Es kann auch innerhalb eines Blockes ein weiterer Block stehen!
  • Es wird zwischen Groß- und Kleinschreibung unterschieden, einrücken oder Zeilenumbrüche haben allerdings keine Einflüsse, wenn man von einzeiligen Kommentaren und dem Präprozessor absieht!

Werte in Variablen speichern

  • In Variablen können Werte und Daten gespeichert und mit diesen gearbeitet werden. Variablen haben immer eine Bezeichnung, unter der sie angesprochen werden, und einen Wert!
  • In C++ haben Variablen auch einen Typ, der die Art von enthaltenen Daten bezeichnet:
    (Die Größen können von System zu System variieren! 1 Byte=8 Bit)
    16-Bit-Systeme
    Name Deutsch Werte Größe
    (Byte)
    Beispiel
    bool Ja/Nein
    false/true
    bzw. 0/1
    1 bool b_test=false;
    signed char Zeichen mit Vorzeichen -128/127 1 signed char sch_test=-34;
    unsigned char Zeichen ohne Vorzeichen 0/255 1 unsigned char uch_test=240;
    enum Auflistung von Konstanten -32.768/
    32.767
    2 s.u.
    (signed) int Ganzzahl mit Vorzeichen -32.768/
    32.767
    2 signed int si_test=-1234;
    unsigned int Ganzzahl ohne Vorzeichen 0/65.535 2 unsigned int ui_test=12;
    short (int) kurze Ganzzahl -32.768 2 short int shi_test=345;
    (signed) long (int) lange Ganzzahl mit Vorzeichen   4 signed long int sli_test=-2345;
    unsigned long (int) lange Ganzzahl ohne Vorzeichen 4 unsigned long int uli_test=5678;
    float Gleitkommazahl, z.B.: 3.14   4 float f_test=1.618;
    double Gleitkommazahl mit
    doppelter Genauigkeit
      8 double d_test=1.6180339887;
    long double lange Gleitkommazahl mit
    doppelter Genauigkeit
      10 long double ld_test=4.896542;
    32-Bit-Systeme
    Nur Änderungen gegenüber 16-Bit
    enum      4  Auf die gesamte Tabelle
    (signed) int      4  keine Garantie!!!
    unsigned int      4  
    Dazu kommen noch enum etc. und eigene Typen (OOP)!
    Die genaue Größekann mit dem "sizeof()"-Operator ermittelt werden: "sizeof(int)" gibt die Größe eines Integers zurück, z.B.: "4". Die Größe eines "char" ist allerdings auf JEDEM System "1"!
  • Die Namen der Variablen unterliegen einigen Regeln:
    • Variablennamen müssen mit einem Buchstaben oder Unterstrich beginnen
    • Leerzeichen im Namen sind nicht erlaubt, man darf aber Buchstaben, Zahlen und Unterstriche benutzen.
    • Die maximale Länge variirt je nach Compiler, ist aber meist bei ca. 247
    • Reservierte Wörter dürfen nicht genutzt werden, siehe Anhang!
    • Es wird zwischen Groß- und Kleinschreibung unterschieden!
  • Um mit Variablen zu rechnen oder Operationen auszuführen, gibt es Operatoren und Funktionen. Weiterhin gibt es Methoden, also zum Typ gehöhrende Funktionen (s. OOP)
  • Variablen können lokal oder global sein, d.h. entweder nur innerhalb des Blockes, in dem sie deklariert worden sind, oder im ganzen Programm sichtbar sind. Globale Variablen bestehen also das gesamte Programm über und beanspruchen Speicher! Lokale werde aus dem Speicher entfernt, sobald ihr Gültigkeitsbereich überschritten wird.
  • Variablen können mit einem "=" Werte und andere Variablen zugewiesen werden!

Sprachelemente

  • Kommentare
    • gehen von "//" bis zum Ende der Zeile
    • oder von "/*" bis "*/"
    • Werden vom Compiler einfach ausgelassen
  • Blöcke
    • gehen von "{" bis "}" und dienen zu Strukturierung und zum definieren von Gültigkeitsbereichen
    • Bei einzeiligen Anweisungen in einem Block nach z.B. einer "if"-Abfrage können die Klammern auch wegfallen, ausgeführt wird dann nur das folgende Kommando!
  • Bedingungen
    • Bedingungen braucht man bei Schleifen und Bedingter Ausführung
    • Es gibt solche Bedingungen:
      Zeichen Bedeutung Beispiel
      == Wert1 gleich Wert2? 1==1
      1==3
      true
      false
      != Wert1 nicht gleich Wert2? 1!=2
      1!=1
      true
      false
      < Wert1 kleiner Wert2? 1<2
      2<2
      true
      false
      > Wert1 größer Wert2? 2>1
      5>5
      true
      false
      <= Wert1 kleiner oder gleich Wert2? 1<=1
      3<=2
      true
      false
      >= Wert1 größer oder gleich Wert2? 3>=3
      4>=5
      true
      false
      ! Nicht Wert !(false)
      !(true)
      true
      false
      Falls man mehrere Bedingungen verknüpfen möchte,
      gibt es die beiden folgenden Möglichkeiten:
      && Bedingung1 und Bedingung2 (1==1) && (2>0)
      (1<=1) && (2==3)
      true
      false
      || Bedingung1 oder Bedingung2 (1!=1) || (2==2)
      (1==3) || (2==6)
      true
      false
      ! Nicht diese Bedingung! !(1<0)
      !(1==1)
      true
      false
  • Inkrementierung/Dekrementierung
    Quelltext
    1. //Erst um eins erhöhen, dann weiterrechnen:
    2. ++i;
    3.  
    4. //Erst weiterrechnen, dann erhöhen:
    5. i++;
    6. //Hier wird zuerst eine Kopie angelegt,
    7. // daher ist dies Variante leicht langsamer!
    8.  
  • Schleifen
    • for
      Quelltext
      1. for (int i=5; i<12; i++)
      2. {
      3. //Mach was!
      4. }
      5.  
    • while
      Quelltext
      1. while(Fehler==0)//!SOLANGE! (Fehler gleich Null ist)
      2. // {wird das Kommando ausgeführt.}
      3. //(Mit zwei "="!!!)
      4. {
      5. //Kommando
      6. }
      7.  
    • do while
      Quelltext
      1. do
      2. {
      3. //Anweisungen...
      4. } while(/*Bedingung*/);
      5.  
  • Bedingte Ausführung
    • if
      Quelltext
      1. if (/*bedingung*/)
      2. {
      3. //Wenn Bedingung erfüllt...
      4. }
      5. else
      6. {
      7. //Ansonsten: (optional)
      8. }
      9.  
    • switch case
      Quelltext
      1. switch(/*Variable*/)
      2. {
      3. case /*==*/:
      4. /*Anweisungen*/;
      5. break; //Die anderen wollen wir nicht überprüfen...
      6. case /*==(2)*/:
      7. /*Anweisungen*/;
      8. //[...]
      9. default: //optional
      10. /*Anweisungen, falls nicht anderes wahr war...*/
      11. }
      12.  
      13. //Beispiel:
      14. switch (integer_val)
      15. {
      16. case 0:
      17. case 1:
      18. //MachDochWas! (Bei 0 oder 1)
      19. break;
      20. case 2:
      21. //vllt. beenden?
      22. break;
      23. default:
      24. std::cout << "Fehler!" << std::endl;
      25. }
      26.  
    • ?:
      Quelltext
      1. bool test=(x>5)?true:false;
      2. //Bedingte Wertzuweisung...
      3.  

Funktionen

  • Strukturieren das Programm
  • Wiederkehrende Abläufe zusammenfassen
  • haben einen Rückgabetyp, einen Namen und ggf. Parameter
  • Der Rückgabetyp kann ein beliebiger Datentyp oder "void" sein, bei void wird nichts zurückgegeben
  • Die Parameter bringen beliebige Daten in die Funktion, damit diese dort verarbeitet werden können, zurückgegeben werden kann nur einer, dies geschieht mit "return"!
  • Die Parameter haben ebenfalls einen Namen und Typ, wie "normale" variablen auch
  • Ein Prototyp ist ein Funktionsrohling, der Rückgabetyp, Parameteranzahl und Typ, sowie den Funktionsnamen beinhaltet. Dadurch können Funktionen aus anderen Dateien/von weiter unten "angemeldet" werden, damit der Compiler sie kennt. Dies muss _vor_ dem ersten Aufruf erfolgen! Prototypen schrebt man über die main-Funktion!
    Quelltext
    1. int quadrat(int); //Prototyp
    2.  
    3. //Noch ein Prototyp:
    4. int quadrat(int i); //Name des Parameters
    5. //kann angegeben werden, muss aber nicht...
    6.  
  • Funktionen müssen immer außerhalb einer anderen, wie der main() Funktion definiert werden!
  • Sie sollten, wie auch Variablen, einen sinnvollen Namen bekommen
  • Man kann mehrere Funktionen mit dem gleichen Namen schreiben, solange ihre Parameter sich voneinander durch Anzahl oder Typ unterscheiden. Dies nennt man "Überladen", oder "Polymorphie" ("Vielgestaltigkeit"). Der Rückgabewert ist beim Überladen übrigens egal! Nur sich unterscheidende Rückgabetypen können nicht zur Unterscheidung genutzt werden!
    Quelltext
    1. bool saghallo()
    2. void saghallo(int i)
    3. int saghallo(float f)
    4.  
    5. //aber nicht:
    6. int test()
    7. void test()
    8. float test()
    9.  
  • Rekursion: Rekursive Funktionen sind Funktionen, die sich immer wieder mit veränderter Parameteranzahl aufrufen. Gleich mehr... (nächster Abschnitt!)
  • Default-Parameter: Wenn du einem Parameter innerhalb des Prototypen/des Funktionskopfes einen Wert zuweist, kann dieser beim Funktionsaufruf weggelassen werden. Geschieht dies, so wird der Standardwert genommen, den du festgelegt hast. Wichtig: Solche default-Parameter dürfen nur am Ende stehen, normale Parameter dürfen dann nicht mehr folgen, damit die Reihenfolge nicht durcheinander gebracht wird. Weitere default-Parameter dürfen folgen, allerdings kann nicht der vorletzte Parameter weggelassen werden, der letzte aber nicht...!
    Quelltext
    1. int test1 (int i=0); //Geht
    2. int test2 (int i=0, int k); //Geht nicht
    3. int test3 (int i, int k=5); //Geht
    4. int test4 (int i=0, int k=9); //Geht
    5.  
    6. // [...]
    7.  
    8. test1(); //Geht: i=0
    9. test1(3); //Geht: i=3
    10.  
    11. test3(2); //Geht: i=2, k=5
    12. test3(2,-19); //Geht: i=2, k=-19
    13.  
    14. test4(); //Geht: i=0, k=9
    15. test4(1); //Geht: i=1, k=9
    16. test4(-19,8); //Geht: i=-19, k=8
    17.  
    18. test4(/*nur k angeben woll*/); //Geht nicht
    19.  
  • static: Lokale Variablen, die ihren Wert nach Verlassen einer Funktion bis zum nächsten Aufruf behalten, nennt man "static": "static int beispiel;"
  • Es gibt auch "inline"-Funktionen: Inline Funktionen werden automatisch an alle Stellen kopiert, wo sie vorkommen. Dadurch wird Speicher (RAM) gespart (Der Computer muss sich nicht merken, von wo er die Funktion aufgerufen hat!) und die binäre, ausführbare Datei größer. Daher nutzt man sie meist bei kleinen, kurzen Funktionen, da sie "inline" schneller sind, aber die Übersichtlichkeit von Funktionen bleibt! Inlinefunktionen werden mit dem Wort "inline" gekennzeichnet, aber ganz normal aufgerufen:
    Quelltext
    1. inline int saghallo() {/*...*/};
    2.  
  • Funktionen, die sich immer mit verschiedenen Parametern selbst aufrufen, arbeiten rekursiv, die alternative Schreibweise (mit Schleifen) nennt man iterativ!

[drucken]

Ein paar Beispielprogramme

Hier stehen ein paar Programme, die zeigen, was wir schon gelernt haben:

pq-Formel

Die pq-Formel wird in der Mathematik genutzt, um Nullstellen von Funktionen ausrechnen zu können. Das Programm ist recht einfach, es werden p und q eingelesen und dann die Beiden Antwortmöglichkeiten x1 und x2 ausgegeben. Die Formel lautet:
PQ-Formel
 
In C++ sieht das so aus: (Eine Möglichkeit, "double")
Quelltext
  1. x1 = -(p/2) + std::sqrt( (p/2)*(p/2)-q );
  2. x2 = -(p/2) - std::sqrt( (p/2)*(p/2)-q );
  3.  

Das ganze noch hübsch verpacken und fertig:
Quelltext[1kB]Download
  1. #include <iostream>
  2. #include <limits> //für: std::numeric_limits<>::max()
  3. #include <cmath>
  4.  
  5. double x1(double p, double q);
  6. double x2(double p, double q);
  7. std::istream& puffer_weg(std::istream& in);
  8.  
  9. int main()
  10. {
  11. //"Einleitung":
  12. std::cout << "PQ-Formelrechner" << std::endl;
  13. int weiter=0;
  14.  
  15. //Haupt-Schleife
  16. do
  17. {
  18. double var_p, var_q=0;
  19.  
  20. //Werte einlesen:
  21. std::cout << "Gib bitte die Werte für P und Q ein:\nP> ";
  22. while (!(std::cin >> var_p))
  23. {
  24. std::cerr << "FEHLER: Falsche Eingabe!" << std::endl << ">";
  25. puffer_weg(std::cin);
  26. }
  27. std::cout << "Q> ";
  28. while (!(std::cin >> var_q))
  29. {
  30. std::cerr << "FEHLER: Falsche Eingabe!" << std::endl << ">";
  31. puffer_weg(std::cin);
  32. }
  33.  
  34. //Rechnen und ausgeben: (Zeile ohne Semikolon,
  35. // da sie nur umgebrochen ist!)
  36. std::cout << "x1= " << x1(var_p, var_q) << std::endl
  37. << "x2= " << x2(var_p, var_q) << std::endl;
  38.  
  39. //Weiter?
  40. std::cout << "\nNoch eine Rechnung? (1=Ja)\n>";
  41. while (!(std::cin >> weiter))
  42. {
  43. std::cerr << "FEHLER: Falsche Eingabe!" << std::endl << ">";
  44. puffer_weg(std::cin);
  45. }
  46.  
  47. } while(weiter==1);
  48.  
  49. return 0;
  50. }
  51.  
  52. //Puffer zurücksetzen/löschen (Nach Fehleingabe aufrufen!)
  53. std::istream& puffer_weg(std::istream& in)
  54. {
  55. return in.clear(), in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  56. }
  57.  
  58. //Berechnen:
  59. double x1(double p, double q)
  60. {
  61. return( -(p/2) + std::sqrt( (p/2)*(p/2)-q ) );
  62. }
  63. double x2(double p, double q)
  64. {
  65. return( -(p/2) - std::sqrt( (p/2)*(p/2)-q ) );
  66. }
  67.  
  68.  

 
Das Programm funktioniert zwar gut, aber zwei Funktionen schreiben, um x1 und x2 zu errechnen? Schöner wäre es, direkt 2 Werte zurückzugeben... Und dazu müssen wir uns ein wenig mit dem Speicher beschäftigen, was wir im nächsten Kapitel auch machen werden. Außerdem wollen wir lieber mit "y/n" anstatt mit Zahlen antworten... ;)
Aber damit erstmal genug Beispiele, wir wollen es ja nicht direkt übertreiben! ;)

Ein paar "Aufgaben" (wirklich winzig)

Wenn du die Aufgaben lösen kannst, solltest du dieses Kapitel verstanden haben... ;)
  1. Schreibe ein Programm, das dein Alter einliest und ausrechnet, in wie vielen Jahren du wieder einen "runden" Geburtstag hast!
  2. Schreibe ein Programm, welches entweder eine Zahl auf "gerade/ungerade" prüft oder beendet wird!
  3. Schreibe ein Programm, welches zwei Zahlen (m&n) einliest, und dann " mn " ausgibt. Benutze dazu _nicht_ die Funktion "pow", sondern schreibe diese selber! (etwas komplizierter! Tipp: Schleifen)

Wie geht's weiter?

Glückwunsch! Du hast Kapitel 1 absolviert! Die Einleitung in C++ ist hier zu Ende! Das zweite Kapitel handelt von Speicher und Variablen im Speicher. Danach können wir uns mit Texteingaben beschäftigen, damit du Namen etc. einlesen kannst! ;)
Seite:  [1] - Drucken