Präprozessors Befehl

include ist kein direkter Bestandteil der Sprache C, sondern ein Befehl des Präprozessors. Präprozessor ist ein Teil des Compilers. Präprozessorbefehle erkennen Sie am vorangestellten #-Zeichen. include-Dateien nennt man auch Headerdateien.

#include <stdio> // Standard-Input/Output. 

Header nach Kategorie

Category Header
Algorithmen <algorithm>, <cstdlib>, <numeric>
Atomvorgänge <atomic>11
C-Bibliotheksumbruch <cassert>, <ccomplex> 11a b,<ciso646><climits><csignal><cmath><cfenv><cerrno><clocale><csetjmp><cinttypes><cfloat><cctype><cstdalign> 11, 11, b, 11<cstdarg><cstdbool> a b, 11 a b, 11 b<cstddef><cuchar><cstdint><cstdlib><cwchar><cstdio><cstring><ctgmath><ctime>, , 11, 11 a, , 11,<cwctype>
Konzepte <concepts>20
Container
Sequenzcontainer <array>11, , 11, <list><deque>, <forward_list><vector>
Bestellte assoziative Container <map>, <set>
Nicht sortierte zuordnende Container <unordered_map>11, <unordered_set>11
Containeradapter <queue>, <stack>
Containeransichten <span>20
Fehler und Ausnahmebehandlung <cassert>, <exception><stdexcept><system_error>11
Allgemeine Dienstprogramme <any>17<bit>, 20,<cstdlib><bitset><execution>17, <memory_resource><functional><memory>17, <optional> 17, <tuple><scoped_allocator><ratio><typeindex><utility><type_traits><variant> 11, 11, 11, 11, 11, 11, , 17
I/O und Formatierung <cinttypes>11, , <filesystem>17, <fstream><ios><streambuf><iosfwd><cstdio><ostream><sstream><strstream><istream><iomanip><iostream>c,<syncstream>20
Iterators <iterator>
Sprachunterstützung <cfloat><climits>, , <codecvt>11 a, <compare>20,<contract>20, <coroutine>20, 11, <cstdlib><initializer_list><exception>11, <limits><new><version><typeinfo>11 , 20<csetjmp><csignal><cstdarg><cstddef><cstdint>
Lokalisierung <clocale>, <codecvt>11 a, , <cvt/wbuffer>, <cvt/wstring><locale>
Mathematik und Numerische <bit>20, <cfenv>11, <cmath>, <limits><cstdlib><numeric><complex><random> 11, <ratio> 11,<valarray>
Speicherverwaltung <allocators><memory>, <memory_resource>17, , <new><scoped_allocator>11
Multithreading <atomic>11,<condition_variable> 11, <mutex><future>11, 11, 14, <thread><shared_mutex>11
Bereiche <ranges>20
Reguläre Ausdrücke <regex>11
Zeichenfolgen und Zeichendaten <charconv>17, , <cstdlib><cuchar><cstring>11, <cctype>, 11<regex><cwctype><cwchar>, <string>,<string_view> 17
Time <chrono>11, <ctime>

int main()

Hier beginnt das Hauptprogramm. Eine main-Funktion wird immer benötigt, damit der Compiler weiss, wo er beginnen muss, das Programm zu übersetzen. (Hauptfunktion). int steht für eine Ganzzahl. (Für Funktionen mit Rückgabewert)

Das void in der main()-Funktion steht für einen »leeren« Datentyp.

return 0;

Das bedeutet: Das Programm wurde ordnungsgemäss beendet

{ printf("….."); }

Zwischen den geschweiften Klammern steht unser Anweisungsblock. Geschweifte Klammern fassen Anweisungen zu einem Block zusammen.

Semikolon (;)

Es wird hauptsächlich dazu verwendet, das Ende einer Anweisung anzuzeigen. Der Compiler weiss dann, dass hier das Ende der Anweisung ist Fährt dann nach der Abarbeitung der Anweisung mit der nächsten Zeile fort.

Vergleichsoperationen

Operator Bedeutung
a < b ist Wahr, wenn a kleiner b ist
a > b ist Wahr, wenn a grösser b ist
a <= b ist Wahr, wenn a kleiner oder gleich b ist
a >= b ist Wahr, wenn a grösser oder gleich b ist
a == b ist wahr, wenn a gleich b ist

Umlaute

Wenn Sie in C oder C++ Umlaute schreiben, kommen meistens irgendwelche komischen Zeichen heraus, aber nicht die Umlaute. Sie haben schon mal von der hexadezimalen Darstellung gehört. Hier werden die Umlaute einfach hexadezimal ausgegeben.

Umlaute Hexadezimal:

Umlaute Hex
ä x84 ist nur die Schreibweise für hexadezimale Zahlen
ö x94
ü x81
Ä x8E
Ü x99
ß xE1

Bei der Zeichenkodierung verwendete ASCII-Code streng genommen nur 128 Zeichen (Codes 0 bis 127). Für die obere Hälfte der ASCII-Tabelle (Codes 128 -255) gibt es verschiedene Erweiterungen. Leider befinden sich die deutschen Umlaute in der oberen Hälfte und sind somit nicht einheitlich genormt.

Bei Windows-Programmen wird im Konsolenfenster standardmässig die Erweiterung “Code Page 850” verwendet, im Programm-Editor aber eine andere. Dies bewirkt, dass im Editor eingegebene Umlaute im Konsolenfenster falsch dargestellt werden. Unter Windows besteht jedoch die Möglichkeit,die Konsole auf “Code Page 1250 oder 1252” umzustellen, was kompatibel zum Editor ist. Diese Einstellung kann man sowohl für die Eingabe als auch für die Ausgabe vornehmen. Man muss dazu die beiden folgenden Anweisungen in den Quelltext, in der Regel in die main()-Funktion, einsetzen:

SetConsoleOutputCP (1250);// Für die Umlaut-Ausgabe
SetConsoleCP (1250);// Für die Umlaut-Eingabe

Alternativ kann man auch

system("chcp 1250");

für Ein-und Ausgabe verwenden. Allerdings gibt das System dann eine unerwünschte Meldung aus.In jedem Fall muss die Datei <windows.h> eingebunden werden. Das nachfolgende Beispielprogramm zeigt die Vorgehensweise:

#include <iostream>
#include <cstdio>
#include <windows.h>

using namespace std;

int main() {
	char input;

	// Windows code page 1250 / 1252 oder 28591 entspricht ISO-Latin-1
	SetConsoleOutputCP (1250);
	SetConsoleCP (1250);

	cout << endl << " Ausgabe von Umlauten unter C++";
	cout << endl << " Und jetzt geht es: ä ö ü Ä Ö Ü $" << endl << endl;

	do {
		cout << " Ihr Zeichen (0=Ende) >";
		cin >> input;
		cout << " " << input << endl;
	}while(input != '0');
	
	return 0;
}

Schlüsselwörter

Die Schlüsselwörter der Programmiersprache C/C++. Diese Schlüsselwörter sollten für Variablen-Namen nie verwendet werden:

  • asm
  • auto
  • break
  • case
  • char
  • const
  • continue
  • default
  • do
  • double
  • else
  • enum
  • extern
  • float
  • for
  • goto
  • if
  • int
  • long
  • register
  • return
  • short
  • signed
  • sizeof
  • static
  • struct
  • switch
  • typedef
  • union
  • unsigned
  • void
  • volatile
  • while

Logische Operatoren

Mit der Negation wird ein Wert invertiert, also umgekehrt. D.h. aus wahr wird falsch und aus falsch wird wahr. Die Negation erreichen wir mit einem einfachen Ausführungszeichen “!”.

int a=5;  
if(!0) cout << "aus falsch wird wahr, 0 -> 1\n";  
if(!a) cout << "aus wahr wird falsch, 5 -> 0\n";

&&

Mit dem logischen UND && prüfen wir ob mehrere Bedingungen erfüllt sind.

||

Muss nur eine von mehreren Bedingungen erfüllt sein

Zeichensatz

Basic-Zeichensatz:

  • Der Basic-Zeichensatz beinhaltet Zeichen für den Quellcode. (Dezimalzahlen, Alphabet, einige Sonderzeichen -> ! " % & / ( ) [ ] { } \ ? =’ # + * ~ – _ . : ; , | < > ^)

Ausführungszeichensatz:

  • Der Ausführungszeichensatz enthält Zeichen, die erst bei der Ausführung des Programms interpretiert werden. (Steuerzeichen, Umlaute, usw.)

Beim Ausführungszeichensatz kommen zu den oben aufgeführten Zeichen noch weitere hinzu.

Steuerzeichen (Escape-Sequenzen) in Zeichenkonstanten

Steuerzeichen sind nicht druckbare Zeichen. Sie können damit die Ausgabe auf dem Bildschirm beeinflussen. Steuerzeichen beginnen also immer mit einem Backslash ( \ ), auf den eine Konstante folgt.

Value Escape sequence
newline \n
backslash \\
horizontal tab
question mark ? or \?
vertical tab \v
single quote \'
backspace \b
double quote \"
carriage return \r
the null character \0
form feed \f
octal \ooo
alert (bell) \a
hexadecimal \xhhh

ASCII-Tabelle

Character Character Name ASCII code
! Exclamation point 33
Double quotation 34
# Number sign 35
$ Dollar sign 36
% Percent sign 37
& ampersand 38
apostrophe 39
( Left parenthesis 40
) Right parenthesis 41
* asterisk 42
+ Plus sign 43
, comma 44
hyphen 45
. period 46
/ slash 47
0 zero 48
1 one 49
2 two 50
3 three 51
4 four 52
5 five 53
6 six 54
7 seven 55
8 eight 56
9 nine 57
: colon 58
; semi-colon 59
< Less-than sign 60
= Equals sign 61
> Greater-than sign 62
? Question mark 63
@ At sign 64
A Uppercase a 65
B Uppercase b 66
C Uppercase c 67
D Uppercase d 68
E Uppercase e 69
F Uppercase f 70
G Uppercase g 71
H Uppercase h 72
I Uppercase i 73
J Uppercase j 74
K Uppercase k 75
L Uppercase l 76
M Uppercase m 77
N Uppercase n 78
O Uppercase o 79
P Uppercase p 80
Q Uppercase q 81
R Uppercase r 82
S uppercases 83
T Uppercase t 84
U Uppercase u 85
V Uppercase v 86
W Uppercase w 87
X Uppercase x 88
Y Uppercase y 89
Z Uppercase z 90
[ Left square bracket 91
\ backslash 92
] Right square bracket 93
^ caret 94
_ underscore 95
` Grave accent 96
a Lowercase a 97
b Lowercase b 98
c Lowercase c 99
d Lowercase d 100
e Lowercase e 101
f Lowercase f 102
g Lowercase g 103
h Lowercase h 104
i Lowercase i 105
j Lowercase j 106
k Lowercase k 107
l Lowercase l 108
m Lowercase m 109
n Lowercase n 110
o Lowercase o 111
p Lowercase p 112
q Lowercase q 113
r Lowercase r 114
s Lowercase s 115
t Lowercase t 116
u Lowercase u 117
v Lowercase v 118
w Lowercase w 119
x Lowercase x 120
y Lowercase y 121
z Lowercase z 122
{ Left curly brace 123
| Vertical bar 124
} Right curly brace 125
~ tilde 126

Rechenoperatoren

Variablen und Konstanten können durch Rechenoperatoren miteinander verknüpft und einer neuen Variablen zugeordnet werden.

Als Klammern sind in Ausdrücken nur runde Klammern erlaubt. Sie bewirken, dass der darin enthaltene Ausdruck zuerst berechnet wird. Nach Ausführung der Klammerausdrücke führt der Compiler die Operationen von links nach rechts aus.

Operator Math. ausdruck
+ Addition
- Subtraktion
* Multiplikation
/ Division
% Restdivion (Modulo)
double x = 6(4 + 7.4)2;				//falsch
double y = 5 * (4 + 7.4) * 2;		// ok

Ein- und Ausgaberoutinen

Ein- und Ausgaberoutinen geben Ihnen die Möglichkeit, mit einem Programm zu interagieren.

Um die C++ Ein- und Ausgabe nutzen zu können, müssen Sie die Bibliothek “iostream” einbinden.

Um diese “Ein- und Ausgaberoutinen” im Programm nutzen zu können, geben Sie dem Compiler bekannt: using namespace std.

Das Teilt dem Compiler mit das dieser Befehl in einem speziellen Namensraum befindet.

Der Namensraum „std“ heisst so viel wie Standard. Wenn etwas in diesem Namensraum steht, dann gehört es zur C++-Standardbibliothek und die sollten

Sie (in der Regel) wann immer möglich einsetzen.

Formatierte Ausgabe mit Manipulatoren

Um Informationen besser formatieren zu können, stellt C++ eine Reihe von Manipulatorenzur Verfügung. Viele Dieser Manipulatoren werden durch die Headerdatei “iomanip” eingebunden.

Manipulator Bedeutung
setw(int n) Festlegung der Feldbreite
setfill(char) Festlegung des Füllzeichens
left Linksbündig
right rechtsbündig
scientific Exponentendarstellung
fixed Gleitpunktdarstellung
showpos Anzeige des positiven Vorzeichens
uppercase Grossbuchstaben
setprecision(int n) Anzahl der Nachkommastellen
dec, hex, oct Umwandlung in andere Zahlensysteme

Inkrement & Dekrement

Wollen wir den Wert einer Variablen um eins erhöhen oder erniedrigen, empfiehlt es sich die Inkrement- und Dekrement-Operatoren zu nutzen.

Zeichen: ++ oder –

bsp.

// mit Inkrement-Operator  
int a=0, b=0;  
a++;  
b--;  

// ohne Inkrement-Operator  
a = a + 1;  
b = b  1;

Achtung bei der Zuweisung

Bei der Zuweisung gibt es mit ++ und – noch eine Besonderheit:

int a, b=0;  
// Erst Zuweisung, dann Inkrement  
a = b++;  
// Erst Inkrement, dann Zuweisung  
a = ++b;

Präfix und Postfix

Der Inkrementoperator und der Dekrementoperator existieren in zwei Spielarten:

Präfix und Postfix.

Präfix ++counter –counter Inkrementiere den Wert zuerst und übertrage in dann.

Postfix counter– counter++ Übertrage den Wert zuerstund inkrementiere dann.

Deklaration von Variablen

Mit der Deklaration benennen wir eine Variable. Unter der Definition versteht man, dass einer Variablen ein Speicherbereich zugeteilt wird. Haben wir eine Variable deklariert und definiert, so hat sie einen beliebigen Wert - je nach dem was gerade im zugewiesenen Speicherbereich steht.

Bsp. int zahl; oder int a, b, c;

Variablen

Variablen einführen

Wenn eine Variable das erste Mal verwendet wird, muss ihr Name und der Datentyp dem Compiler bekannt gegeben werden. Diesen Vorgang nennt man Variablenvereinbarung.

Werte zuweisen

Unter dem Namen einer eingeführten Variablen können bestimmte Werte abgespeichert werden.

Wertzuweisungen bestehen normalerweise aus der Variablen selbst (sie muss immer links stehen) einer Zahl oder einem Ausdruck (rechts von der Variablen).

Regeln

Ein Name darf Buchstaben, Zahlen und das Zeichen _ (englisch: «underline») enthalten, jedoch keine Zwischenräume und keine Sonderzeichen. Das erste Zeichen muss ein Buchstabe oder ein Underline sein.

Variablen sind Case sensitiv (Es wird zwischen Gross- und Kleinschreibung unterschieden. Eine Variable sollte also immer richtig geschrieben werden sonst gibt es Probleme.)

Variable_1			//ok
Heute Morgen		//nicht erlaubt: Zwichenraum
vater&söhne			//nicht erlaubt: Sonderzeichen
3_laender			//nicht erlaubt: Zahl am anfang
int					//nicht erlaubt: bereits für Datentyp besetzt
_int				//erlaubt, aber nicht empfohlen (wird normalerweise für Systemfunktionen verwenden)
double z;				//z als Flieskommazahl vereinbart
int zahl;				//zahl als Ganzkommazahl
char zeichen;			//Zeichenvariable
bool zustand;			//Zustandsvariable
float z;				//korrekt, z als float vereinbart,
z = 46.3;				//dann eine Wertzuweisung
int x = 347;			//ok. Vereinbarung der Variablen. x und Wertzuweisung kombiniert
220.7= double z;		//falsch. Zahl muss rechts stehen
int x = 2;				//ok.
int z = 25*x + 5;		//Wertzuweisungen können auch Ausdrücke (Formeln) sein

Variablen ausgeben

Bildschirmausgaben

printf("Hello World");

Ausgabe von Variablen

Wollen wir in den auszugebenden Text Variablenwerte einfügen, geht dies mit der Formatierungsanweisung %. Für jeden Datentyp gibt es einen eigenen Formatierungstyp. Die Formatierungsanweisung wird in den Text geschrieben, also zwischen die “ “. Danach folgen die Variablennamen nach dem Komma.

Ausgabe von Zeichen

Für die Ausgabe eines einzelnen Zeichens verwenden wir den Formatierungstyp %c.

bsp.:

char vari = Z';  
printf("Das Alphabet endet mit: %c", vari);

Der Formatierungstyp für ganze Zahlen ist %d. (Merke: Dezimalwerte)

bsp.:

int laenge=312500, breite=50;  
printf("\nLaenge: %d cm\nBreite: %d cm\n", laenge, breite);  
printf("\nLaenge: %10d cm\nBreite: %10d cm\n", laenge, breite);

Zur Ausgabe von Kommazahlen verwenden wir den Formatierungstyp %f.

So wie man den Vorkommateil auf eine bestimmte Länge bringen kann, kann man dies auch mit dem Nachkommateil machen. Mit %2.3f hat man z.B. 2 Vorkomma-stellen und 3 Nachkommastellen. Was zu wenig ist, wird aufgefüllt - was zu viel ist, wird abgeschnitten.

Sollen beim Auffüllen keine Leerzeichen, sondern führende Nullen verwendet werden, erreichen wir dies mit einer Null nach %, also %0.

bsp.:

int tag=3, monat=9, jahr=2007;  
printf("Ein Datum: %02d.%02d.%4d\n", tag, monat, jahr);

Tastatureingaben

Zeichen einlesen mit getchar

char c;

printf("Mit welchem Buchstaben beginnt ihr Vorname? ");c = getchar();  
printf("\nIch weiss jetzt, dass Ihr Vorname mit %c beginnt.\n", c);  

//Oder mit C++  
cout << Dein Vorname beginnt mit :  << c << “\n;

Zahlen einlesen

int alter;  
printf("Wie alt sind sie? ");  
scanf("%d", &alter);  
printf("\nIn %d Jahren sind Sie 100!\n", 100-alter);  

//Oder mit C++  
cin >> alter;

Datentyp wechseln

Oft möchte man z. B. eine Dezimalzahl in eine Ganzzahl umformen. Man nennt dies Typumwandlung.

Umgekehrt kann aber eine Fliesskommazahl nicht einem Ganzzahltyp zugeordnet werden. Da auf diese Weise ein Teil der Zahl verloren geht.

Es muss mittels «type casting» die Umwandlung erzwungen werden.

Konstanten

Konstanten werden durch das Wort const gekennzeichnet. Üblicherweise werden bei den Namen der Konstanten Grossbuchstaben verwendet. Der Wert muss immer sofort zugewiesen werden. Bei “const” bleibt die Variable immer gleich und kann nicht durch eine Rechenoperation oder anderes verändert werden.

const int "Variable" = 25

//bsp. 

const double PI = 3.14159;				//ok
const double MEHRWERTSTEUER = 0.075;	//ok. Prozent gibt es nicht in C
const float UMRECHNUNGSKURS;			//falsch: Wert muss sofort zugewiesen werden

Schleifen, Verzweigungen, Sprünge

Verzweigungen:

Hierbei wird im Programm eine Bedingung definiert. Je nachdem, ob diese wahr oder nicht wahr ist, wird das Programm an unterschiedlichen Stellen fortgesetzt.

if(Bedingung)  
{  
	Anweisung(en);  
} else
{
	Falls Bedingung nicht zutrifft
}

bzw.

switch-Verzweigung

switch(Ausdruck) 
{ 
case Ausdruck1 : Anweisung(en); 
	break; 
	
case Ausdruck2 : Anweisung(en); 
	break; 

case Ausdruck3 : Anweisung(en); 
	break; 

default : Anweisung(en); 
}

Mit break wird die Verzweigung beendet. default gleicht der else Funktion.

Schleifen:

Sie sind dazu da, Anweisungen zu wiederholen bis die Bedingung erfüllt wird. Eine Schleife verwenden wir, um Wiederholungen im Programm zu realisieren - also um Dinge mehrmals zu machen. Jede Schleife hat eine Durchlauf-Bedingung, damit sie nicht endlos läuft.

while Schleife

while(Bedingung) 
{ 
	Anweisung(en); 
}

for Schleife Die for Schleife verwenden wir, wenn die Anzahl der Durchläufe bekannt ist. D.h. es ist eine Zähler-gesteuerte Schleife Wir benötigen also immer eine Variable, welche wir zum Zählen der Durchläufe verwenden.

int i;  
for(i=0; i<5; i++) {  
	cout << "Zahl " << i+1 << "\n";  
}
  • Bereich 1: Startwert der Zählvariablen setzen, z.B. i=0
  • Bereich 2: Durchlauf-Bedingung, z.B. i<5
  • Bereich 3: Operation auf Zählvariable ausführen, z.B. i++

for-each

Mit der for-Schleife muss immer auf die korrekte Zählweise geachtet werden. Also nicht kleiner als 0 und auch nicht die Listengrösse übersteigen

Eine Variante der for-Schleife, die Ihnen diese ganze Index-Problematik abnimmt und daher zur Vermeidung von Programmierfehlern oft die bessere Wahl ist, ist die sogenannte for-each-Schleife. For-each bedeutet »Für jedes«, also: für jedes Element der Liste mache etwas Bestimmtes.

For-each hat also eine Variable, die das jeweilige Element enthält und die nach jedem Durchgang auf das nächste Element gesetzt wird. Sie müssen also nicht mit Zahlen hantieren, sondern können direkt mit den Elementen arbeiten.

vector<int> vec={11,22,33,44,55,66};
cout<<"The elements are: ";

for(auto var : vec) {
    cout<<var<<" ";
}

Sprünge:

Die Programmausführung wird unterbrochen und an einer bestimmten Stelle, die markiert wurde, fortgesetzt.

Schleifen-Verschachtelung

Schleifen können auch beliebig verschachtelt werden. Es gibt eine äussere Schleife und eine inneren Schleife. Die Durchlauf-Bedingung der inneren Schleife ist meist an die äussere Schleife gebunden.

kopfgesteuerte Schleifen// fussgesteuerte Schleifen

while und for sind sogenannte kopfgesteuerte Schleifen. D.h., dass der Kontrollpunkt als erstes vor jedem Durchlauf ausgeführt wird. Soll zuerst der Schleifen-Block ausgeführt und dann die Bedingung für einen erneuten Durchlauf geprüft werden, verwenden wir die do while Schleife. Diese ist also eine fussgesteuerte Schleife.

int alter;  
do  
{  
cout << "\nBitte geben sie ihr Alter ein: ");  
cin >> alter;} while(alter < 18);  
cout << "Danke. Hier dein Bier. Prost!\n");
}while

break//continue

Mit dem Schlüsselwort break können wir zu jeder Zeit auch eine Schleife verlassen, ohne auf den Kontrollpunkt warten zu müssen.

bsp.:

int Zahl = 17;
	
while(Zahl >= 3)
{
	cout << "Die Zahl ist \a" << Zahl << endl;
	if(Zahl == 9)
	{
		cout << "Es gabe einen Fehler in der Matrix" << endl;
		break;
	}
		Zahl--;
	}
cout << endl;
system("PAUSE");
return 0;

Mit dem Schlüsselwort continue haben wir die Möglichkeit, direkt zum Kontrollpunkt zu springen. Somit wird der restliche Code im Schleifen-Block nicht ausgeführt.

bsp.:

int Minimum;
int Maximum;
int teiler;
	
cout << "\nBitte geben Sie die höchste Zahl ein > ";
cin >> Maximum;
cout << "\nBitte geben Sie die niedrigste Zahl ein > ";
cin >> Minimum;
cout << "\nBitte geben Sie den Teiler ein > ";
cin >> teiler;
cout << endl << "___________________________________" << endl << endl;
	
int counter;
	
for(counter = Minimum; counter <= Maximum; counter++) {
		if(counter == 42)
		{
		cout << "Die antwort die Grosse Frage. Nach dem Leben, dem Universum und allem lautet: 42" << endl;
			continue;
		}
		if (counter % teiler == 0)
		{
			cout << counter << endl;
		}
			
}

Sprünge:
Die Programmausführung wird unterbrochen und an einer bestimmten Stelle, die markiert wurde, fortgesetzt

Trigraph-Zeichen

Als Trigraph bezeichnet man in der Linguistik eine Kombination aus drei Schriftzeichen.

Bei der Entwicklung neuer Software sollten Sie, wenn möglich, auf den Einsatz von Trigraph-Zeichen komplett verzichten.

Trigraph Interpunktionszeichen
??= #
??( [
??/ \
??) ]
??' ^
??< {
??! \
??> }
??- ~

Datentypen

Bei der Wahl des richtigen Datentyps spielen folgende Überlegungen eine wichtige Rolle:

  • Was möchte ich speichern oder verarbeiten?
  • Zeichen, Text, Zahl oder Kommazahl
  • Char, String, Int, float etc.
Typname Byte Andere Namen Wertebereich
int 4 signed -2,147,483,648 bis 2,147,483,647
unsigned int 4 unsigned 0 bis 4.294.967.295
__int8 1 char –128 bis 127
unsigned __int8 1 unsigned char 0 bis 255
__int16 2 short, short int, signed short int –32.768 bis 32.767
unsigned __int16 2 unsigned short, unsigned short int 0 bis 65.535
__int32 4 signed, signed int, int -2,147,483,648 bis 2,147,483,647
unsigned __int32 4 unsigned, unsigned int 0 bis 4.294.967.295
__int64 8 long long, signed long long -9,223,372,036,854,775,808 bis 9,223,372,036,854,775,807
unsigned __int64 8 unsigned long long 0 bis 18.446.744.073.709.551.615
bool 1 none false oder true
char 1 none -128 bis 127 standardmäßig 0 bis 255, wenn sie mithilfe kompiliert werden /J
signed char 1 none –128 bis 127
unsigned char 1 none 0 bis 255
short 2 short int, signed short int –32.768 bis 32.767
unsigned short 2 unsigned short int 0 bis 65.535
long 4 long int, signed long int -2,147,483,648 bis 2,147,483,647
unsigned long 4 unsigned long int 0 bis 4.294.967.295
long long 8 keine (aber gleichwertig mit __int64) -9,223,372,036,854,775,808 bis 9,223,372,036,854,775,807
unsigned long long 8 keine (aber gleichwertig mit unsigned __int64) 0 bis 18.446.744.073.709.551.615
enum Variiert none
float 4 none 3.4E +/- 38 (7 Stellen)
double 8 none 1.7E +/- 308 (15 Stellen)
long double gleiches wie double none Identisch mit double
wchar_t 2 __wchar_t 0 bis 65.535

bsp. (string und char):

int main() {  
    char text[20]="Blabla";  
      
  cout << "hallo char möchte gerne etwas ausgeben " << text << endl;  
 
system("PAUSE");
return 0;
}

bsp. (bool):

using namespace std;

int main() {
   int x;
   bool Variable = (x == 2);
   if(Variable) 
   	{
   		cout << "Fehler in der Matrix :-)\n";
   	}
   	else 
   	    {
   	    	cout << "lol";
   		}

system("PAUSE")
return 0;
}

Deklaration, Definition und Initialisierung

Mit der Deklaration benennen wir eine Variable. Unter der Definition versteht man, dass einer Variablen ein Speicherbereich zugeteilt wird. Haben wir eine Variable deklariert und definiert, so hat sie einen beliebigen Wert - je nach dem was gerade im zugewiesenen Speicherbereich steht

Vector & Strings

Mit den Klassen vector und string stehen dir eine Menge nützlicher Funktionalitäten zur Verfügung, die du von einem Array bzw. String erwarten darfst. Reservieren von weiterem Speicher musst du dir keine Gedanken machen. Pufferüberläufe können ebenfalls abgefangen werden.

Vector

Für Arrays empfehlen die C++-Doktoren die Klasse vector.

Um die Klasse verwenden zu können, musst du die gleichnamige Headerdatei “vector” mit einbinden.

#include  < vector >

Ein vector ist im Wesentlichen ein dynamisches Feld, das je nach Bedarf seine Grösse dynamisch verändern kann. Auf ein beliebiges Objekt innerhalb des Feldes kann sehr effizient unter direkter Adressierung zugegriffen.

Syntax

vector< int > meinvecray(5);  

Hinweis: Alle Elemente werden gleich mit der Zahl 0 initialisiert. Den Zugriff auf die einzelnen Elemente des Arrays kannst du wieder über die eckigen Klammern [n] realisieren.

Containerklassen

Sequentielle Containerklassen

  • vector
  • deque
  • list

Container sind Behälter für Objekte. Dabei wird immer eine Kopie des Objektes in dem Container gespeichert. Das hat den Vorteil, dass sich die Speicherverwaltung vereinfacht, denn das Objekt verliert seine Gültigkeit, wenn das Containerobjekt aufgelöst wird.

Nachteile Der Nachteil liegt auf der Hand - durch das Erstellen einer Kopie geht Zeit und Speicherplatz verloren. Es gibt aber auch Wege, Zeiger in Containern zu speichern

at()

Damit auch Pufferüberläufe abgefangen werden können, brauchen wir eine neue Elementen-Funktion. Das at( ).

Die Methode at(), die den Index als Parameter erwartet und eine Grenzprüfung ausführt, gibt den Buchstaben an der jeweiligen Stelle zurück.

Im Fehlerfall löst sie eine out_of_range-Exception aus.

#include <iostream>
#include <string>

using namespace std;

int main() {
	string zeichenkette = "Ich bin ganz lang!";

	cout << zeichenkette[4] << endl;
	cout << zeichenkette.at[4] << endl;

	cout << zeichenkette[20] << endl; // ausgabe von Datenmüll (out_of_range)
	cout << zeichenkette.at[20] << endl; // Laufzeitfehler (what(): basic_string::at)
}

Grösse erfahren!

Die Anzahl Elemente zur Laufzeit kannst du bei den vector-Arrays mit der Funktion size() ermitteln.

cout << vecray.size() << endl;   ## Grösse eines Arrays
cout << vecray.length() << endl; ## Länge eines Stings

String

String-Funktionen nutzen zu können, müssen wir eine neue Bibliothek einbinden:

< string > für C++

string einString01;  
string einString02 = ’’ Voll einfach ’’;  
getline(cin, einString01);

Probleme

#include <string>

int main() {
	string zeichenkette;

	cin >> zeichenkette;
	cout << zeichenkette;
}

Diese Art der Eingabe erlaubt es lediglich, bis zum nächsten Whitespace einzulesen. Es kommt jedoch häufig vor, dass man eine Zeichenkette bis zum Zeilenende oder einem bestimmten Endzeichen einlesen möchte.

Die Funktion getline()

Did you get the line? Yeah i’ve got the line with getline()!

In diesem Fall ist die Funktion getline() hilfreich. Sie erwartet als ersten Parameter einen Eingabe stream und als zweiten ein string-Objekt.

int main() {
	string zeichenkette;
	// Liest bis zum Zeilenende
	getline(cin, Zeichenkette);
	cout << zeichenkette;	
}

Zuweisen und Verketten

Für die Verkettung von strings wird der + Operator benutzt und das Anhängen einer Zeichenkette ist mit += möglich.

int main() {
	string string1, string2 string3;

	string1 = "ich bin ";
	string2 = "ein JS-Dev";
	string3 = string1 + string2;
	cout << string3 << endl;

	string3 += " - " + string1 + "schön";
	cout << string3 << endl;
}

Methoden

Die string-Klasse stellt einige nützliche Methoden bereit. Etwa um den String mit etwas zu füllen, ihn zu leeren oder über verschiedene Eigenschaften Auskunft zu bekommen. Eine Methode wird mit folgender Syntax aufgerufen:

<stringname>.<mehtodenname> ("paramenter");
  • size() und length()
  • empty() (true or false)
  • clear()
  • resize()
  • swap() (String austauschen)
  • Und viele andere.

Das Zählen beginnt mit 0

In der Informatik beginnt das Zählen nicht mit 1, sondern mit 0. Deshalb sollte man auch bei den Zählvariablen bei 0 beginnen. Durchlauf-Bedingung anpassen. Bei der Ausgabe des Werts um eins erhöht ausgeben (i+1).

char

Wir haben gelernt, dass wir für die Verarbeitung von einzelnen Zeichen den Datentyp char verwenden. Nun lernen wir den Umgang mit Zeichenketten, auch Strings genannt. Das sind aneinandergereihte Zeichen. Also ein char-Array

String Objekt erstellen

Wie Ihnen bereits bekannt ist, werden einzelne Zeichen in einfachen Anführungszeichen geschrieben.

Dieser Zeichenliteral ist dann vom Typ char.

char titel[]={'H', 'a', 'l', 'l', 'o', ' ', 'W', 'e', 'l', 't', '!', '\0'};

Die doppelten Anführungszeichen erzeugen hingegen eine Instanz eines char-Arrays.

char titel[]="Hallo Welt!";

Nullterminiert

Ein String besteht in C/C++ aus einem char-Feld. Dieses Feld ist meist grösser als der der String selbst. Ein Beispiel:

char text[100] = "Hallo";  

Hier speichern wir in einem Feld der Grösse 100 lediglich 5 Zeichen.

ASCII-Zeichen 0 abgeschlossen

Wo ist das Ende der Zeichenkette?

Strings werden mit dem ASCII-Zeichen 0

abgeschlossen: '\0'.  

Im Hauptspeicher steht nicht nur “Hallo”,

sondern "Hallo\0".  

Bei der Initialisierung ohne die geschweiften Klammern und bei den String-Funktionen wird das Ende-Zeichen automatisch gesetzt.

Das Ende-Zeichen dient also nur zur Markierung, deshalb ist es bei der Ausgabe auch nicht zu sehen. Wir sprechen hierbei von sogenannten nullterminierten Strings. Bei der Deklaration von String-Feldern sollte also auch immer an das Ende-Zeichen gedacht werden!

Beispiel: Zeichenkette mit String/Klasse

Ein Objekt der Klasse String wird hier erzeugen. (Nach OOP gesprochen)

string satz; //Die Klasse heisst STRING!
satz = “Das ist “;
cout « satz « endl;

Typumwandlung nach C oder C++ String-Streams

Möchte man Zahlen verarbeiten, welche in einem String vorkommen, gibt es eine Reihe von Umwandlungsfunktionen dafür. Hierfür wird die Bibliothek stdlib.h oder cstdlib benötigt. Das sind die Funktions-Prototypen:

  • String zu int: atoi
  • String zu long int: atol
  • String zu double: atof

Bsp.

int main() {  

char charNumber1[] = "100";  
char charNumber2[] = "23";  

int number1 = atoi(charNumber1);  
int number2 = atoi(charNumber2);  

int sum = number1 + number2;  
cout << number1 << " + " << number2 << " = " << sum;  

cout << endl;  
system("PAUSE");  
return 0;  
}

Funktionen

Teilprobleme legen wir als “Funktion” getrennt vom Hauptprogramm ab. Eine Funktion erledigt immer eine bestimmte Aufgabe.

Eine Funktion hat folgende Eigenschaften:

  • Bezeichner, ein Name unter der sieansprechbar ist, z.B. addiere()
  • Bezeichner der Parameter, z.B. summand1, summand2
  • Datentyp der Parameter, z.B. int/double/etc.

Gibt eine Funktion nichts zurück, verwenden wir das Schlüsselwort void, welches einen nicht-existenten Wert darstellt.

Beispiel

Rekursion

Jede Funktion kann sowohl andere Funktionen als auch sich selbst aufrufen. Ein solcher Selbstaufruf wird auch rekursiver Aufruf genannt. Das dahinter stehende Konzept bezeichnet man entsprechend als Rekursion. Eine Ausnahme von dieser Regel bildet wieder einmal die Funktion main(). Sie darf ausschliesslich vom Betriebssystem aufgerufen werden, also weder von einer anderen Funktion, noch aus sich selbst heraus.

call-by-value

Bei call-by-value (Wertübergabe) wird der Wert des Arguments in einen Speicherbereich kopiert, auf den die Funktion mittels Parametername zugreifen kann.

call-by-reference

Sollen die von einer Funktion vorgenommen Änderungen auch für das Hauptprogramm sichtbar sein, müssen sogenannte Zeiger verwendet werden.

Zeiger

Zum Beispiel arbeiten wir mit grossen Datenmengen, welche von Funktionen bearbeiten werden sollen. Würden wir diese Datenmengen als Paket zu den Funktionen transportieren, geht dies sehr stark zu Lasten der Performance und des Speicherplatzes. Um dem vorzubeugen, verwenden wir Zeiger.

Die Datenmengen liegen im Speicher und haben eine Adresse. Ein Zeiger “zeigt” auf die Menge, indem er lediglich die Adresse der Menge speichert. Wenn wir dann einer Funktion unsere Datenmenge überliefern möchten, teilen wir ihr lediglich mit dem Zeiger die Adresse mit.

Die Datenmenge wird dabei nicht transportiert, stattdessen greift die Funktion über die Adresse auf die Daten zu. Datenmengen werden durch Variablen repräsentiert. Ein Zeiger speichert also nur die Adresse einer anderen Variablen und leitet somit die Anfrage auf einen Wert weiter.

Ein Zeiger repräsentiert eine Adresse und nicht wie eine Variable einen Wert. Will man auf den Wert der Adresse zugreifen, auf die ein Zeiger zeigt, muss der Stern * vor den Namen gesetzt werden.

Beispiel

int *Variable = Bei der Deklarierung einer Variable kann die Variable als Zeiger definiert werden. &Variable = Gibt die Adresse bekannt ! Die Variable muss den gleichen Datentyp haben wie den *Zeiger !

int zahl = 7;  
int *zeiger; 
zeiger = &zahl; //Zeiger verbinden Adresse  

Ausgabe:

cout<<"Zeiger-Wert: " *zeiger; //Dereferenzierung  = Wert ausgeben
cout<<"Zeiger-Wert: " zeiger;  //Adresse der Variable anzeigen

Ausgabe über Adresse (Wert) = 7.

Referenzen

Was ist das?

Referenzen sind interne Zeiger auf Variablen. Sie werden also genau so verwendet wie gewöhnliche Variablen, verweisen jedoch auf das Objekt, mit dem sie initialisiert wurden. Die Zeigerverwendung wird vor dem Programmierer verborgen.

int a = 1;		// eine Variable
int &r = a;		// Referenz auf die Variable a

Wofür Referenzen?

Vielleicht haben Sie sich bereits gefragt, wofür Referenzen nun eigentlich gut sind, schliesslich könnte man ja auch einfach die Originalvariable benutzen. Referenzen bieten in einigen Anwendungsfällen eine Beschleunigung und bessere Lesbarkeit der Quelltexte.

Wichtig: Sie müssen initialisiert werden.

Array

Der englische und gängigere Begriff für Feld ist Array. Für ein Array müssen wir lediglich eine Deklaration machen.

Um viele Variablen auf einmal zu erstellen können Sie dies mit einem Array realisieren.

Beispiel

double messwerte[1440];

Einfacher geht es mit einem Feld von Variablen. Hierfür benötigen wir lediglich eine Deklaration.

Hier haben wir 1440 Variablen auf einen Schlag angelegt.

Zugriff

Der Zugriff auf diese Variablen erfolgt mittels einer Nummer, auch Index genannt. Aufdie Elemente des Arrays wird dann über diese Indexoperator zugegriffen. Dieser Index liegt im Bereich 0 und Feldgrösse minus 1, da wir bekanntlich bei Null anfangen zu zählen.

Initalisierung

Bei der Definition sind der Typ der Elemente und die Grösse des Arrays anzugeben stehen Ihnen folgende Möglichkeiten stehen zum Anlegen eines Array zur Verfügung:

Möchte man die Werte eines Feldes Initialisieren, schreibt man die Werte einfach in geschweifte Klammern.

Ist die Anzahl der Werte bei der Initialisierung kleiner als die Feldgrösse, werden die restlichen Werte auf Null 0 gesetzt.

int punkte[5] = { 1, 3, 5 };

Alles mit Null: Dadurch lässt sich ein Feld auch einfach komplett mit Null-Werten initialisieren:

int punkte[5] = { 0 };

Lässt man bei der Initialisierung die Angabe für die Feldgrösse weg, wird automatisch die Grösse durch die Anzahl der Initialisierungswerte bestimmt.

Dieses Array wird die Grösse 3 haben:

int punkte[] = { 1, 2, 3 };
//Anlegen ohne Initialisierung
int feld [10];

//Mit Initialisierung (automatisch 10 Elemente)
int feld[] = {1,2,3,4,5,6,7,8,9,10};

//10 Elemente, mit Initialisierung
int feld[10] = {1,2,3,4,5,6,7,8,9,10};

Schlaufen und Array

Mit den Schleifen können wir die einzelnen Elemente des Arrays sehr einfach ansprechen.

int punkte[5], i;  
for(i=0; i<5; i++) 
{  
	punkte[i] = i+1;  
	cout << punkte[i] << endl;
}

Zweidimensionale Felder

Bisher haben wir eindimensionale Felder kennengelernt, die einer einfachen Liste entsprachen.

Für viele Zwecke benötigt man aber mehrdimensionale Felder. Im Folgendem wollen wir ein Schachbrett simulieren.

Schachbrett

Ein Schachbrett hat 8 x 8 Felder, die wir mit einem zweidimensionalen Array darstellen können.

int brett[Y][X];

Insgesamt haben wir hier 8 * 8 Elemente, also 64.

Koordinatensystem

Man kann sich das Brett wie ein Koordinatensystem vorstellen, wobei man mit dem ersten Index die Y-Achse und mit dem zweiten Index die X-Achse anspricht:

brett[Y][X]

Allgemein wird bei Null angefangen zu zählen und von rechts her hochgezählt. Bei unserem Beispiel mit zwei Dimensionen und 12 Initialisierungs-Werten sind dabei folgende Indexierungen betroffen:

Zeile 1:  [0][0], [0][1], [0][2], [0][3], [0][4], [0][5], [0][6], [0][7]
Zeile 2:  [1][0], [1][1], [1][2], [1][3]

Zeigerarithmetik

Ein Array besteht im Prinzip nur aus Zeigern, welche auf die zum Array gehörenden Variablen zeigen. Der Zugriff auf die Variablen erfolgt also mittels Zeiger. Dazu benötigen Sie einen Positionszeiger.

Alternative Adressoperator &

Alternativ erhalten wir die erste Adresse eines Feldes auch mit dem Adressoperator & und der Indexierung auf das erste Element, z.B.

&punkte[0].

Mit diesem Operator können Sie die Adresse des Feldes herausfinden.

Hinweis zur Speicherverwaltung

In den bisherigen Beispielen haben wir Felder deklariert, bei denen die Grösse zur Compilezeit bereits feststand. Da es nicht sehr effizient ist, immer den grösstmöglichen Speicher zu reservieren, gibt es die dynamische Speicherverwaltung.

int array1[100];  
// kein Standard:  
int size = 200;  
int array2[size];

Strukturen

Wenn du unterschiedliche Typen verwenden willst oder musst, kannst du diese in einer Struktur zusammenfassen.

struct schuhe 
{
	string marke;
	unsigned short Groesse;
	string verschluss;
	string farbe;
}

Mit dem Schlüsselwort struct und der sich öffnenden geschweiften Klammer leitest du die Zusammenfassung der unterschiedlichen Typen und des Namens schuhe ein. Jetzt folgen die einzelnen Strukturmitglieder (Members), in denen die eigentlichen Daten gespeichert werden. Hier kannst du alle bekannten Typen verwenden. Am Ende wird diese Zusammenfassung der Struktur mit einer sich schliessenden geschweiften Klammer und einem Semikolon beendet.

Eine neue Variable erstellen

Nachdem du deine Typen in der Struktur zusammengefasst hast, kannst du im Programm folgendermassen einen neuen Schuh erstellen:

schuhe einSchuh, nocheinSchuh;

Zugriff auf die Daten

Der Zugriff auf die einzelnen Strukturmitglieder erfolgt dann über den Bezeichner der Struktur, gefolgt vom Punkteoperator und dann dem Strukturmitglied:

structbezeichner.structmitglied

Prototypen

Wir müssen dem Compiler erst eine Funktion bekanntmachen, bevor wir sie aufrufen können. Dies erreichen wir, indem wir die Funktionen über unser Hauptprogramm platziert haben.

Wir wollen dies mittels den Funktions-Prototypen ändern. Diese platzieren wir über das Hauptprogramm, wobei der Funktionskörper dann an einer beliebigen Stelle im Skript sein darf.

#include<31231>
// Anmeldung von Funktions-Prototypen
double multipliziere(double zahl1, double zahl2);

// Ab hier das Hauptprogramm 
int main() {}  

// Eigentliche Funktion
double multipliziere(double zahl1, double zahl2)  
{  
return (zahl1 * zahl2);  
}

Befehle

main

“Hier beginnt das Hauptprogramm”. Eine main Funktion wird immer benötigt damit der Compiler weiss wo er beginnen muss, das Programm zu übersetzten

void

void in der main()-Funktion steht für einen “leeren” Datentyp (🕳️)

;

Es wird hauptsächlich dazu verwendet, das Ende einer Anweisunganzuzeigen. Er Fährt dann nach der Abarbeitung der Anweisung mit der nächsten Zeile fort.

{}

Zwischen den geschweiften Klammern steh Anweisungsblock.

return 0

Die main-Funktion bekommt den Rückgabewert 0. Das bedeutet das Programm wurde ordnungsgemäss beendet

stdio

stdio steht für Standard-Input/Output.

bool

Eine boolische Variable hat zwei Werte “true oder false”.Intern wird bool als Zahl abgespeichert abgespeichert

short

Kann Positivzahlen bis 32767 abspeichern. Short ist dafür Effizienter als int und benötig weniger Computerressourcen. Falls man nur positive Zahlen will, sollte man “unsigned short” benutzen. Damit verdoppelt sich die mögliche Zahlenmenge.

double

Fliesskommazahlen. Double kann Dezimalzahlen oder als Zahlen mit Zehnerexponent eingegeben werden. double ist etwas genauer wie float (64-Bit-Zahl -> doppelt so grosser Zahlenraum)

float

Fliesskommazahlen. Double kann Dezimalzahlen oder als Zahlen mit Zehnerexponent eingegeben werden. Ist etwas ungenauer wie double (32-Bit-Zahl)

string

ABC

char

symbolisch (Einzelne Buchstaben, Zahlen oder Sonderzeichen). Eingabe mit einfachen Hochkommas (A 8 %). Abgespeichert wird eine Zahl gemäss dem Zeichencode.

string und char

Eine Zeichenfolge (String) kann mit einem Feld von char abgespeichert werden. char

int

Ganzzahlen

Noch mehr “long double”

printf() Ist eine Funktion aus der Headerdatei stdio.h . Beliebige String konstante formatiert auf dem Bildschirm aus. Steht immer zwischen zwei Hochkommata ( “HALLO“ ).

getchar()

Getchar kann ein Zeichen speichern das vom Nutzer eingegeben wurde, und dies dan später ausgeben.

int main() =

Hier beginnt das Hauptprogramm. Eine main-Funktion wird immer benötigt, damit der Compiler weiss, wo er beginnen muss, das Programm zu übersetzen. (Hauptfunktion)

return 0

In diesem Programm bekommt die main-Funktion den Rückgabewert 0. Das bedeutet: Das Programm wurde ordnungsgemäss beendet.

{}

Zwischen den geschweiften Klammern steht unser Anweisungsblock. Geschweifte Klammern fassen Anweisungen zu einem Block zusammen.

static

Durch static wird der letzte Wert in der in einer Variable “lokal in einer Funktion” gespeichert. Static benötigt immer einen Anfangswert