hier ist mein kleines und erstes Tut für C++.
WICHTIG: Es ist nicht von mir, ich habe es nur etwas des Orginals hier reinkopiert, so habt ihr alles auf einen Blick. Trotzdem viel Spaß beim Lesen.
Quelle:

Grundlagen:
1) Unser erstes Programm
Folgendes ist das wohl kürzeste Programm das es gibt:
Quote:
int main()
{
}
Dieses Programm sollte jeder C++ Compiler fehlerfrei kompilieren. Allerdings werden sich die meisten Compiler darüber aufregen, dass main() einen Wert zurück geben muss (ein return erwartet). Da haben die Compiler aber unrecht, denn im C++ Standard ist beschrieben, dass man bei main() kein return schreiben muss.
Das klingt jetzt alles kompliziert und ist viel auf einmal, aber das war nur eine Erklärung warum du u.U. eine Warnung von deinem Compiler bekommen hast.
Schauen wir uns nun das Programm an:
int main() - diese Zeilen muss in jedem Programm enthalten sein (uU auch leicht abgewandelt). Das ist der Beginn des Programms. Man nennt main() deswegen auch den Einstiegspunkt, denn genau da steigen wir in das Programm ein.
Die schönen Klammern { und } (auch 'französische Klammern' oder 'geschweifte/geschwungene Klammern' genannt) schließen immer einen Anweisungsblock ein, d.h. alles was nach main() steht muss in diese Klammern eingeschlossen werden.
2) Variablen
Um Daten kurzzeitig (oder auch längerfristig) speichern zu können muss zuerst Platz geschaffen werden und dann muss es noch einen Weg geben auf diesen Platz zuzugreifen. Hierfür gibt es Variablen. Sie stehen für den Inhalt eines Speicherplatzes (bzw. sind ein anderer Name für ihren Wert). Zuerst muss eine Variable definiert werden. Danach wird dieser ein Wert zugewiesen. Welcher Wert zugewiesen werden darf ist von ihrem Typ abhängig.
Bisher haben wir nur int als Variablentyp kennengelernt. Es gibt aber viel mehr Variablentypen: Neben den eingebauten Typen gibt es auch Userdefined Typen, die behandeln wir aber viel später.
Die Variablentypen
Variablentyp:
1-int
2-float
3-double
4-char
5-bool
beinhaltet:
1-Ganzzahl
2-Gleitkommazahl
3-genauere Gleitkommazahl
4-Buchstabe
5-enthält den Wert true oder false
Um einem char einen Buchstaben zuzuweisen darf man nicht char c="a"; schreiben, sondern man muss 'a' schreiben. Denn "a" ist ein String (Zeichenkette) und 'a' ein zeichen
Warum das so ist, behandeln wir später. Wichtig für uns ist: wenn wir einen String (Zeichenkette) verwenden wollen, dann verwenden wir string als Variablentyp:
Quote:
#include<string> //für string
#include<iostream>
using namespace std;
int main()
{
string str="Hallo Welt";
cout<<str<<"\n";
}
In C ist jede Zeichenkette ("Hallo") ein char-Array welches mit einer 0 terminiert wird. Später dazu mehr.
Es gibt (außer bei bool und natürlich string) die Modifizierungen: signed bzw. unsigned. signed bedeutet dass die Variable auch negativ sein kann, unsigned bedeutet, dass sie nur positiv sein kann. Der Vorteil von unsigned ist, dass man dann natürlich höhere Werte speichern kann.
Bei int gibt es die Einteilung in short, int und long. short ist ein 'kleiner' int, während long ein 'großer' int ist.
Variablen haben auch einen Sichtbarkeitsbereich (zu englisch: Scope). Eine Variable existiert nur in ihrem Sichtbarkeitsbereich. Wie sieht so ein 'Scope' jetzt aber aus?
Quote:
#include<iostream>
using namespace std;
int main()
{
int a; //hier wird a erzeugt
{
int b; //hier wird b erzeugt
//irgend ein wichtiger code
int c; //hier wird c erzeugt
} //hier werden b und c geloescht
int d; //hier wird d erzeugt
} //hier werden a und d geloescht
Wenn wir eine Variable definieren
Quote:
int var;
dann sagen wir dem Compiler: hey du! Ich will eine Variable mit Namen var vom Typ int haben.
Wenn wir eine Variable initialisieren (dies impliziert eine Definition)
Quote:
int var=7;
//oder auch
int var(7);
//beide sind identisch!
dann sagen wir dem Compiler: ey, alter! Ich will dass diese Variable mit Namen var vom Typ int (bis hierher ist es eine Definition) mit dem Wert 7 vorbelegt werden soll.
Eine Zuweisung würde so aussehen:
Quote:
var=7;
damit sagen wir dem Compiler, dass wir der bereits definierten (aber möglicherweise noch nicht initialisierten) Variablen var den Wert 5 zuweisen wollen.
Merksatz: Variablen sollten so spät wie möglich definiert werden - am Besten erst dann, wenn wir sie wirklich brauchen.
Es gibt zusätzlich auch noch eine Deklaration
Quote:
extern int var;
mit dieser sagen wir: es gibt irgendwo eine Variable mit Namen var vom Typ int. Aber wo verrate ich dir noch nicht. Hier wird kein Speicher angelegt, sondern nur lediglich bekanntgegeben, dass es diese Variable gibt. Eine Definition und eine Initialisierung implizieren somit auch eine Deklaration.
Mittels extern kann man eine Variable nur deklarieren, denn ohne extern wäre es ja eine Definition. Wo das Sinn macht erfahren wir aber erst später.
Mit Variablen lässt sich auch Rechnen:
Rechenoperatoren
Operator:
1) =
2) +
3) -
4) *
5) /
6) %
Wirkung:
1) Zuweisung
2) Addition
3) Subtraktion
4) Multiplikation
5) Division
6) Modulo (Rest einer Division)
Beispiel:
1) a=7;
2) a+3 == 10
3) a-3 == 4
4) a*3 == 21
5) a/3 == 2
6) a%3 == 1
3) If/Else
Um den Kontrollfluss eines Programmes zu kontrollieren (wir wollen ja nicht immer das selbe machen, je nachdem was der User eingibt soll das Programm darauf reagieren können (interaktiv) sein) braucht man Bedingungen die entweder wahr (true) oder falsch (false) sein können. Je nachdem ob eine Bedingung true oder false ist, wird eine andere Aktion (oder mehrere) ausgeführt.
Quote:
if(Bedingung)
{
wenn Bedingung wahr ist,
dann wird das hier gemacht.
wenn sie nicht wahr ist,
wird das hier nicht ausgeführt.
}
hier geht es weiter, egal ob die Bedingung wahr oder falsch war.
Hier kommt wieder ein Anweisungsblock vor. Wie wir schon wissen fasst ein Anweisungsblock Anweisungen zusammen. In unserem Fall zeigen wir durch den Anweisungsblock dem Compiler welchen Coder er ausführen muss, wenn die Bedingung war ist. Dieser Anweisungsblock kann natürlich auch wieder ein if (bzw. andere Anweisungsblöcke) beinhalten (alles beginnt von vorne).
Das verwenden wir gleich in einem Beispiel:
Quote:
#include <iostream>
using namespace std;
int main()
{
cout<<"Bitte geben Sie eine Zahl ein\n";
int a;
cin>>a;
cout<<"Bitte geben Sie noch eine Zahl ein\n";
int b;
cin>>b;
if(a==b)
{
cout<<"Beide Zahlen sind gleich";
}
if(a<b)
{
cout<<a<<" ist kleiner als "<<b;
}
if(a>b)
{
cout<<a<<" ist größer als "<<b;
}
cout<<"\n";
}
Tip!!Alle Werte ungleich 0 sind in C++ true(wahr). dh ein if(1) oder if(-200) ist immer wahr!
Wichtig ist, dass man die { und } nicht vergisst. Denn man muss dem Compiler ja sagen was er alles machen soll, wenn die Bedingung wahr ist. Sollte nur eine Anweisung ausgeführt werden (so wie in unserem Beispiel), dann kann man die Klammern weglassen. Ich empfehle aber, sie trotzdem immer zu schreiben.
Interessant dürfte sein, dass es ergänzend zu dem Wenn (if) auch ein Andernfalls (else) gibt:
Quote:
#include <iostream>
using namespace std;
int main()
{
cout<<"Bitte geben Sie eine Zahl ein\n";
int a;
cin>>a;
cout<<"Bitte geben Sie noch eine Zahl ein\n";
int b;
cin>>b;
if(a==b)
{
cout<<"Beide Zahlen sind gleich";
}
else if(a<b)
{
cout<<a<<" ist kleiner als "<<b;
}
else
{
cout<<a<<" ist größer als "<<b;
}
cout<<"\n";
}
Statt
Quote:
if(bla)
{
//...
}
else
{
if(blu)
{
//...
}
}
kann man auch
Quote:
if(bla)
{
//...
}
else if(blu)
{
//...
}
schreiben. Die 2. Variante ist die Üblichere! Folgende Vergleichsoperatoren gibt es:
Vergleichsoperatoren
Operator: Wirkung:
> größer als
>= größergleich
== gleich
!= ungleich
< kleiner als
<= kleinergleich
Weiters gibt es auch logische Verknüpfungen -> if(a>b && b>c), das liest sich wie: "Wenn a größer b und b größer c".
&& bedeutet UND während || ODER bedeutet. Man sollte diese Verknüpfungen aber nicht zu exzessiv verwenden, da der Code dadurch viel zu leicht unleserlich werden kann.
In C++ gibt es 'Lazy Evaluation' - das bedeutet dass ein Ausdruck nur soweit ausgewertet wird, bis das Ergebnis feststeht: if(true || false) - hier wird nur true ausgewertet und false nicht mehr beachtet. Denn es ist ja egal ob der zweite Wert true oder false ist, denn true || false ist genauso wahr wie true || true. Dito bei &&: if(false && true) - hier wird true nicht mehr beachtet denn false && true ergibt genauso false wie false && false.
4) Schleifen
Schleifen - Iteration. Was zum Geier geht denn hier ab?
Klingt verrückt, ist es aber nicht. Schleifen sind dafür da, wenn wir etwas ziemlich oft machen wollen. zB wenn wir eine Zahl potenzieren wollen, dann müssen wir ziemlich oft multiplizieren...
Quote:
#include<iostream>
using namespace std;
int main()
{
int a;
int b;
int erg=1;
cout<<"Geben sie eine Zahl ein: ";
cin>>a;
cout<<"Und jetzt eine andere: ";
cin>>b;
for(int i=0;i<b;i=i+1)
{
erg=erg*a;
}
cout<<a<<" hoch "<<b<<" ist "<<erg<<"\n";
cin.get();
}
Merksatz: Ein C++ Programmierer zählt nicht von 1-10 sondern von 0 bis 9. Gewöhne dich daran, denn ein C++ Programmierer der nicht bei 0 zu zählen beginnt, der hat ein Problem.
Wir sehen hier etwas neues: for. for besteht aus 3 Teilen: for(a;b;c)
a -> hier stehen Initialisierungen. Meistens eine Laufvariable die mitzählt wie oft die Schleife schon durchgelaufen ist.
b -> hier steht die Bedingung die erfüllt werden muss, damit die Schleife weiterläuft, diese Bedingung ist dieselbe wie bei einem if()
c -> hier steht ein Statement das bei jedem Schleifendurchlauf ausgeführt wird. Meistens wird die Laufvariable erhöht.
Tip!!Meistens verwendet man i als Laufvariable. Wenn man mehrere braucht verwendet man i,j,k. Durch diese Namenskonvention erkennt man recht schnell was diese Variable macht.
Hier haben wir wieder einen Anweisungsblock. Solange die Bedingung true ist, wird alles ausgeführt was im dazugehörigen Anweisungsblock steht.
Neben for() gibt es auch noch while() und do {}while(). Die Schleifen sind etwas anders.
Bei while() gibt es kein a und c, sondern nur b. Bei do {} while() ist es exakt wie bei while(), nur dass die Bedingung immer erst NACH dem Schleifendurchlauf geprüft wird (dh die Schleife läuft mindestens einmal durch)
#include<iostream>
using namespace std;
Quote:
int main()
{
int a;
int b;
int erg=1;
cout<<"Geben sie eine Zahl ein: ";
cin>>a;
cout<<"Und jetzt eine andere: ";
cin>>b;
int i=0;
while(i<b)
{
i=i+1;
erg=erg*a;
}
cout<<a<<" hoch "<<b<<" ist "<<erg<<"\n";
cin.get();
}
Tip: Statt i=i+1; kann man auch i+=1; oder ++i; schreiben. ++ bedeutet um 1 erhöhen.
Normalerweise verwendet man for() immer dann, wenn man eine 'Zählschleife' haben will, dh, wenn man die Schleife exakt x-mal durchlaufen lassen will.
Es gibt zwei wichtige Schlüsselwörter bei Schleifen: break und continue
break bricht die Schleife einfach ab.
Quote:
#include <iostream>
using namespace std;
int main()
{
for(int i=0;i<10;++i)
{
cout<<"bla\n";
}
//ist aequivalent zu
for(;//ja, man muss nich ueberall was hinschreiben
//wenn der mittelteil (die bedingung) leer bleibt
//dann laeuft die schleife ewig
{
cout<<"bla\n";
++i;
if(i>=10) break;
}
}
In diesem Beispiel ist die untere Schleife einfach nur hässlich und kaum zu lesen. Selten kommt es vor, dass es auf diese Art besser geht als mit Variante 1. Also im Zweifelsfall immer Variante 1 nehmen!! Der Hauptgrund für break ist so etwas:
Quote:
#include <iostream>
using namespace std;
int main()
{
for(int i=0;i<10;++i)
{
mach_was_wichtiges;
if(mach_was_wichtiges_hat_nicht_funktioniert)
{
break;
}
}
}
continue ist das gegenteil zu break. Denn bei continue wird zwar der aktuelle Schleifendurchlauf abgebrochen, aber nicht die Schleife verlassen, sondern es wird nur der Rest der Durchlaufs übersprungen.
Quote:
#include <iostream>
using namespace std;
int main()
{
for(int i=0;i<10;++i)
{
if(etwas_ist_passiert)
continue;
tu_was_wichtiges;
}
}
Ähnlich zu break und continue ist goto. Mittels goto kann man zu bestimmten Stellen springen. Diese Stellen werden durch ein Label (Sprungmarke) markiert:
Quote:
#include <iostream>
using namespace std;
int main()
{
int i=0;
Schleife: //dies ist ein Label
if(i<10)
{
cout<<i<<'\n';
goto Schleife;
}
}
Mittels goto Schleife; springen wir zum Label Schleife:. Diese Konstruktion wird öfters 'if Schleife' genannt - allerdings ist dieser Ausdruck falsch. Es müsste 'goto Schleife' heißen. Allerdings ist goto sehr verpöhnt - denn mit goto kann man recht einfach schwer leserliche Programme schreiben. Oft gibt es bessere Lösungen als goto - allerdings nicht immer. Dennoch sollte man sehr gut überlegen ob goto wirklich nötig ist.
Schleifen können auch verschachtelt werden:
Quote:
#include <iostream>
using namespace std;
int main()
{
for(int i=3; i<30; ++i)
{
bool isprim=true;
for(int j=2; j<i; ++j)
{
if(i%j == 0) { isprim=false; break; }
}
if(isprim) cout<<i<<" ist eine Primzahl\n";
}
}
Hier werden alle Primzahlen unter 30 berechnet. Eine Primzahl definiert sich dadurch, dass sie nur durch sich selbst und 1 Teilbar ist. Wir brauchen daher 2 Schleifen: eine, in der alle Zahlen bis 30 durchgegangen werden und die Innere um die Zahlen zu testen.
5) Switch
Statt
Quote:
if(a==1)
{
//irgendwas
}
else if(a==2)
{
//irgendwas
}
else if(a==3)
{
//irgendwas
}
else if(a==4)
{
//irgendwas
}
else if(a==5)
{
//irgendwas
}
else if(a==6)
{
//irgendwas
}
else if(a==7)
{
//irgendwas
}
else if(a==8)
{
//irgendwas
}
else if(a==9)
{
//irgendwas
}
else if(a==10)
{
//irgendwas
}
kann man vereinfach aucht
Quote:
switch(a)
{
case 1:
//irgendwas
break;
case 2:
//irgendwas
break;
case 3:
//irgendwas
break;
case 4:
//irgendwas
break;
case 5:
//irgendwas
break;
case 6:
//irgendwas
break;
case 7:
//irgendwas
break;
case 8:
//irgendwas
break;
case 9:
//irgendwas
break;
case 10:
//irgendwas
break;
}
schreiben. Wie man sieht wird der Code dadurch nicht unbedingt viel kürzer, dafür aber viel klarer.
Ein switch verwendet man dann wenn man eine Variable mit vielen Werten vergleichen will - der Vorteil ist: der Compiler macht nicht mehr 10 Vergleiche sondern erstellt eine Sprungtabelle. Das bedeutet, dass der Compiler nur eine kleine Rechnung macht und dann sofort weiß welchen Code er ausführen muss. Das kann signifikanten Geschwindigkeitsvorteil bringen.
Der Nebeneffekt ist, dass der Code viel klarer wird um einen Trick anwenden kann um Code Redundanz zu vermeiden/verringern:
Quote:
if(zahl<20)
{
cout<<zahl<<" ist kleiner 20";
switch(zahl)
{
case 2:
case 3:
case 5:
case 7:
case 11:
case 13:
case 17:
case 19:
cout<<" und eine Primzahl";
break;
}
}
else
{
cout<<zahl<<" ist größer 20";
}
Man kann durch ein case 'durchfallen' und somit können sich mehrere cases den selben Code teilen. Ein case verläßt man mit einem break;.
Ein else gibt es natürlich auch beim switch - hier nennt es sich allerdings default und wird genau wie ein case behandelt.
Die cases müssen nicht in einer bestimmten Reihenfolge stehen, case 3: kann durchaus auch vor case 1: kommen.
switch hat nur einen Nachteil: da eine Sprungtabelle berechnet wird, kann man nur int Typen sowie char bei einem switch verwenden.
6) Kommentare
Angenommen wir haben einen neuen Algorithmus entwickelt der genauso genial wie unleserlich ist. Wie soll der arme Programmierer, der diesen lesen muss, wissen, was er machen soll? Sicher, wir könnten eine Text-Datei mitliefern in der wir das erklären, aber es geht auch einfacher! Jede Programmiersprache bietet die Möglichkeit den Code zu kommentieren.
In C++ sehen Kommentare so aus:
Quote:
// Hallo, ich bin ein einzeiliger Kommentar
kein Kommentar
/* Hihi, ich dagegen bin
mehr
zeil
ig
*/
Tip: Generell sollte man die einzeiligen Kommentare bevorzugen -> denn dann kann man ganze Codeblöcke mit /* und */ Auskommentieren. Denn /* */ kann man leider nicht schachteln. Ein /* Hallo /* Frosch */ Welt */ ist also nicht erlaubt!
Kommentieren ist wichtig, sollte aber nicht übertrieben werden. Man sollte immer nur unleserliche Stellen oder ungewöhnliche Sachen kommentieren. Nie zuviel, aber auch nie zuwenig.
Man sollte darauf achten zu kommentieren was der Code macht, und nicht wie. (Die Semantik beschreiben, nicht die Syntax). Denn ein cout<<"Hello Worl"; //gibt "Hello World" aus ist sinnlos. Dass hier "Hello World" ausgegeben wird, erkennt man ja auf den ersten Blick.
Später werde ich auf die Wichtigkeit des Kommentierens eingehen, aber momentan ignorieren wir diese Wichtigkeit noch.
7) Eingabe
Das Wetter-Programm ist ja schon mal schön. Aber irgendwie fad, findest du nicht auch? Wäre doch toll, wenn wir uns mit dem Programm auch verständigen könnten. Schreiben wir deshalb ein Programm, welches 2 Zahlen einliest und in umgekehrter Reihenfolge ausgibt.
Quote:
#include<iostream>
using namespace std;
int main()
{
int zahl1;
int zahl2;
cout<<"Bitte eine Zahl eingeben\n";
cin>>zahl1;
elitepvpers - Neues Thema erstellen
cout<<"Bitte noch eine Zahl eingeben\n";
cin>>zahl2;
cout<<"Zahl 2: "<<zahl2<<"\n";
cout<<"Zahl 1: "<<zahl1<<"\n";
}
cin kennen wir ja schon von cin.get(). Und wie wir auch schon wissen kann man mit >> aus cin in eine Variable einlesen. Ein bisschen verwirrend, aber stell dir das so vor als wäre cin>>zahl; eine Zuweisung an zahl.
Die zweite Neuerung ist das komische int. int steht für integer - Ganzzahl. mit "int zahl1;" sagen wir dem Compiler dass wir eine Variable mit Namen zahl1 wollen, die eine Ganzzahl speichert. Das nennt sich 'Deklaration'. Mehr dazu gibts im nächsten Abschnitt.
Mit cin werden dann die 2 eingelesen Werte in Variablen gespeichert und dann wieder ausgegeben (mit cout).
Deine Aufgabe besteht jetzt darin dieses Programm so zu verändern, dass 3 Zahlen eingelesen werden und diese in der Reihenfolge: 1 3 2 ausgegeben werden. Also die erste eingegebene Zahl wird zuerst ausgegeben, danach wird die zuletzt eingegebene Zahl ausgegeben und zum Schluss die mittlere.
Ich hoffe es hat Euch gefallen und vllt. auch ein bisschen weitergeholfen. Wenn Ihr i-welche Tipps, oder Verbesserungsvorschläge habt, dann sag mit einfach bescheid.
MfG
WeezyF940






