Programmieren mit c++, Kapitel 1

Ursprünglich wurde dieses für die Benutzung des c++-Compilers auf der VAX mit VMS geschrieben. Jetzt ist es abgeändert um die Verwendung auf Linux (oder andern unix-Varianten) und Macintosh zu unterstützen. Dies sollte sich aber nur auf die "erste Schritte" und technische Hinweise zum Compilieren (Übersetzen) und Linken (Binden) auswirken.

erste Schritte

Die C++-Quelldateien sollten die Endung .cc haben (C-Quelldateien .c).
Ein Programm name.cc wird übersetzt und man erhält dann die Objektdatei name.o.
Um ein lauffähiges Programm zu erhalten werden dann eine oder mehrere Objektdateien gelinkt.
(Untere VMS hatten die Objektdateien die Endung .obj und lauffähige Programme mussten eine Endung .exe haben. Heutzutage sind in allen guten Betriebssystemen beliebige Namen für ausführbare Programme erlaubt)

Unter unix (Linux) erstellt man eine Datei namens "makefile", die alle benötigten Informationen zum compilieren und linken enthält. Das Hilfsprogramm make liest diese Datei und handelt entsprechend. Ein typisches makefile sieht etwa so aus:

-------------------- makefile ------------------
#typisches makefile, Zeilen die mit # beginnen sind Kommentare
C=gcc -c -I$h -Dunix
L=c++ -lm -lX11 -L/usr/X11R6/lib

all: hello

hello.o: hello.cc
	$C hello.cc
hello: hello.o
	$L hello.o -o hello

clean:
	rm -f *.o
-------------------- makefile ------------------
Dabei ist besonders zu beachten dass die eingerückten Zeilen jeweils mit einem Tabulator beginnen (Writing Makefiles).
Der c++ Compiler ist unter Linux mit dabei und heisst gcc. Er kann sowohl c-Programme wie auch c++-Programme übersetzen und linken.

Auf dem Macintosh (bis MacOS 9.2) unter Codewarrior erstellt man sich nicht ein "makefile" sondern ein "Projekt". Dies ist ziemlich selbsterklärend realisiert, es gibt aber auch ein Handbuch dazu.
Auf MacOSX ist dann auch der gcc mit dabei. Somit funktionierts dann wieder gleich wie unter Linux.

Zum Schreiben der Programme sollte ein einfacher Texteditor benutzt werden. Unter Linux wird emacs empfohlen. Hier am PCI ist auf pcihenri der emacs bereits so eingerichtet dass aus dem Editor heraus kompiliert und direkt zu allfälligen Fehlern gesprungen werden kann.
Das auf dem eigenen Computer selbst einrichten geht inzwischen auch problemlos. Einfach in der Datei .emacs folgende zwei Zeilen einfügen:

(global-set-key "\C-b" 'compile)
(global-set-key "\C-n" 'next-error)
oder runterladen von KED.

Übung1: Bringe hello.cc zum laufen.

erstes Beispiel

// hello.cc
/* Die beiden Schrägstriche leiten einen Kommentar ein, der bis zum
   Zeilenende reicht. Kommentare über mehrere Zeilen werden mit /* eingeleitet
   und enden bei */

#include <stream.h>		// mit #include Anweisungen werden Dinge eingefügt

// in jedem C++ Programm muss irgendwo eine Funktion 'main' definiert sein.
main()
{				//Jede Funktion hat einen Block der in
 cout << "Hello World\n";
}				//Geschweiften Klammern steht.

/* Ein- Aus-gaben sind nicht in der Sprache selbst definiert (wie auch in C
   oder Pascal).
   (cout ist ein Benutzerdefiniertes Objekt und << ein Benutzerdefinierter
    Operator. (in stream.h definiert)
    Es gibt auch noch ein cin das so verwendet wird: cin >> variable;
   )
*/
Mit dem neuen GCC (ab Version 3.x) ist die Syntax beim Einfügen der Standardbibliotheken (z.B. stream) etwas anders. Hier ein Beispiel um automatisch zu entscheiden welche Variante benutzt werden soll: hello2.cc

Grundtypen

Fundamentale Typen sind: char short int long float double

Die ersten 4 dienen zum Darstellen von ganzen Zahlen, die beiden andern werden für Gleitkommazahlen gebraucht.

Eine Variable des Typs char hat die Länge von einem Byte (könnte auf andern Maschinen anders sein). Die meisten Compiler verwenden für short 2 Byte, für long 4 Byte, und für int 2 oder 4 Byte. Mit der eingebauten Funktion sizeof(Typ) kann die verwendete Grösse ermittelt werden.

Beim Rechnen mit Gleitkommazahlen wird immer double verwendet, float hat nur eine Bedeutung beim Speichern von grossen Feldern, oder bei Parameterübergaben von andern Programmiersprachen.

Übung2: Schreibe ein Programm das die Grössen aller Grundtypen ermittelt.

Die Deklaration eines Objekts erfolgt mit 'Typ Objekt;', mehrere Objekte werden durch Kommas getrennt. Beispiele:

	int zahl;
	long Zahl,_gueltigevariable_1;
	double x,y,
	       pi=3.14;
Gross-klein-Schreibung ist wichtig. ('zahl' ist verschieden von 'Zahl') Ausser Buchstaben und Ziffern ist auch _ (underline) in Variablennamen erlaubt (Umlaute aber nicht). Bei der Deklaration darf man die Variablen auch initialisieren (pi=3.14). Mit dem Strichpunkt wird jeweils eine Anweisung abgeschlossen. Zeilentrenner und Tabulatoren hingegen werden gleich wie Leerstellen behandelt.

Durch Voranstellen von 'unsigned' lassen sich aus den ganzzahligen Typen auch Vorzeichenlose Typen machen. Zum Beispiel:

	unsigned int n;
Voranstellen von 'const' definiert eine Konstante. In diesem Fall muss auch gleichzeitig eine Initialisierung stattfinden. Beispiel:
	const double pi=3.14159;
Um einen Zeiger zu definieren wird der Variablen bei der Deklaration ein * vorangestellt. "char * s;" zum Beispiel heisst dass s ein Zeiger auf ein Objekt des Typs char ist. (Die Leerstellen vor und nach * können auch weggelassen werden)

Operatoren

In C gibt es viele Operatoren:

Arithmetische Operatoren:
 Binäre:
	+  plus
	-  minus (binär und unär)
	*  Multiplikation
	/  Division
	%  Rest bei ganzzahliger Division
	&  und
	|  oder
	^  exklusives oder
	<< Bitschieben nach links
	>> Bitschieben nach rechts
 unäre:
	~  Complement
	++ Increment
	-- Decrement
	&  Adresse
	*  Dereferenzierung (Gegenteil von Adresse ermitteln)
Vergleichsoperatoren:
	== gleich
	!= nicht gleich
	<  kleiner
	>  grösser
	<= kleiner gleich
	>= grösser gleich
	!  nicht  (die einzige unäre logische Operation)
	&& und
	|| oder

Zuweisungsoperatoren:
	=  normale Zuweisung
	+= dazuaddieren

In der gleichen Art wie += sind auch die andern arithmetischen Operatorzeichen an stelle von + einsetzbar. Allgemein gesagt bedeutet x*=y das gleiche wie x=x*(y).

Die Zuweisungsoperatoren verhalten sich gleich wie die andern binären Operatoren. Das zugewiesene Ergebnis ist gleichzeitig auch das Ergebnis der Operation. Somit ist ein Ausdruck wie a=b=c genauso erlaubt wie zum Beispiel a+b+c. Das Ergebnis einer Vergleichsoperation ist 0 (wenn die Antwort nein lautet) oder ungleich 0 (Antwort ja). Der Type ist dabei int.

Ausdrücke und Anweisungen

Beispiele für Ausdrücke:
	a+b*c
	y+sin(x)
	z=(x>(y-1)) /* gleiche Bedeutung wie ohne Klammern */
	(z=x)>(y-1) /* andere Bedeutung ohne Klammern */

Beispiele für Anweisungen:
	ergebnis=x+sin(alfa);
	z = x > y-1;
	unterprogramm(zahl,x+y);
	; /* leere Anweisung, vergleichbar mit CONTINUE in Fortran oder
	     NOOP in Assembler */

Unterprogramme und Funktionen

In C++ ist beides dasselbe, ein Unterprogramm ist einfach eine Funktion vom Typ void. Allgemeine Syntax:
Typ Name(Parameterliste)
{
 Anweisungen
}

Beispiele:
double quadrat(double x)
{
 return x*x;
}

void zeichne_n_eck(int n,double x0,double y0,double dicke)
{
 /*....*/
 return; //kann in einer void-Funktion auch weggelassen werden
}

Verzweigungen und Schlaufen

Überall wo im folgenden {Anweisungen} steht ist auch eine einzelne Anweisung ohne geschweifte Klammern erlaubt.
----------------------------------------------------------
 Syntax				Beispiele
----------------------------------------------------------
Verzweigung:

 if(Ausdruck)			if(x==y)	cout << "beide gleich\n";
	{Anweisungen}		else if(x<y)	cout << "x ist kleiner\n";
 else				else		cout << "x ist grösser\n";
	{Anweisungen}	
----------------------------------------------------------
Mehrfachverzweigung:

 switch(ganze_zahl)		switch(nummer)
  {case Konstante:		 {case 1: eins();
	 Anweisungen			  break;
	 break;			  case 7: sieben();
   case Konstante:			  break;
	 Anweisungen		  default:cout<<"unbekannte Nummer";
   ....				 }
   default: Anweisungen
  }
----------------------------------------------------------
while(Ausdruck)			while(!isdigit(c))  //erste Ziffer suchen
	{Anweisungen}			c=getc(fp);
----------------------------------------------------------
do {Anweisungen}		do {c=getc(fp);}
while(Ausdruck);		while(isspace(c)); //Leerstellen überlesen
----------------------------------------------------------
for(Ausdr1;Ausdr2;Ausdr3)	for(i=0;i<10;i++)
	{Anweisungen}			cout << " i=" << i;
Ausdr1 bis 3 können auch weggelassen werden, wenn Ausdr2 fehlt wird die
Schlaufe unendlich oft ausgeführt.
----------------------------------------------------------
Schlaufen können auch an beliebiger Stelle mit der Anweisung break; vorzeitig verlassen werden. Mit der Anweisung continue; kann man auch an den Schlaufenanfang springen. (break und continue sollten aber nur sparsam verwendet werden)

Die if-else-Konstruktion ist als gesamtes eine Anweisung und kann somit auch überall wo eine Anweisung erwartet wird vorkommen. Dasselbe gilt auch für Schlaufen-Konstrukte. Somit ist auch folgendes Beispiel eine gültige Anweisung:

 if(x<=y)
	if(x==y) cout << "beide gleich\n";
	else while(x<y)
		if(++x<y) cout << "x immer noch kleiner";
Solche Konstruktionen sollte man aber vermeiden. (unübersichtlich)

Übung3: Schreibe ein Programm das eine Multiplikationstabelle der folgenden Art erstellt:

	1 2 3 ... n
	2 4 6 ... 2*n
	3 6 9 ... 3*n
	...
	n 2n  ... n*n

Präprozessor

Zeilen die mit # beginnen, werden durch den Präprozessor substituiert und erreichen somit den eigentlichen Compiler gar nicht. (Kommentare werden ebenfalls schon vom Präprozessor entfernt)
Eine ausführliche Beschreibung des Präprozessors ist in 3) zu finden.
Beispiele:
#include <stdlib.h>	// die Systemdatei stdlib.h einfügen
#include "teilxy.cc"	// ein eigner Programmteil einfügen
Bei Benutzung von spitzen Klammern wir die Datei in verschiedenen
Verzeichnissen gesucht. Mit Anführungszeichen wird nur im aktuellen gesucht.

#ifdef __cplusplus
// dies geht nur mit C++
#else
/* dies geht auch mit C */
#endif

#define VAX 1
#ifdef VAX
// etwas das nur auf der VAX gebraucht wird
#endif
#ifndef VAX
// etwas das auf allen andern Systemen gebraucht wird
#endif

Literaturhinweise:

1) Bjarne Stroustrup, Die C++ Programmiersprache, Addison-Wesley-Verlag (1987), (2000)
2) Kernighan & Ritchie, Programmieren in C, Hanser Verlag (1983)
3) VAX: gnu_cc:[docs]cpp.dvi, im Aminet:
gccdoc.lha, im Internet: onlinedocs
Last update: 30-März-2007