3 Strukturierung der C/C++

Werbung
C/C++ Programmierung
3
3.1
Strukturierung der C/C++-Programme
Die Funktion
3.1.1 Funktionsdefinition
Bei den Funktionen unterscheiden wir zwischen der Deklaration, der Definition und dem
Aufruf. Bei der Deklaration wird festgelegt, wie die Funktion aussieht: formale Argumente
und Typ des Rückgabewertes, bei der Definition wird festgelegt, was die Funktion tut
(Algorithmus), beim Aufruf wird diese verwendet.
Eine Funktion wird erst beim Aufruf aktiv. Sie kann mit den ihr übergebenen Parametern
entweder ein oder kein Ergebnis (Rückgabewert) an das aufrufende Programm
zurückliefern. Diese Ergebnisrückgabe erfolgt mittels des Schlüsselwortes return.
Funktionsdefinition
Syntaktisch wird eine Funktionsdefinition nach diesem Schema gestaltet:
[ Speicherklasse ]
[ Datentyp des
Rückgabewertes ]
Name der
Funktion
(
[ Datentyp und Name der
formalen Parameter ]
)
{
Die Parameterliste (Liste der formalen Parameter) kann leer sein, d.h. die Funktion hat
Funktionskörper;
keine Argumente.
}
[ ] bedeutet optional
Der Funktionskörper, der die eigentlichen Anweisungen enthält, kann auch lokale
Variablendefinitionen enthalten. Eine lokale Variable darf nicht den Namen eines
Parameters haben. Lokale Variable und Parameter leben nur während des Ablaufes
der Funktion.
Der Ergebnistyp (Typ des Rückgabewertes) einer Funktion kann void, ein Grundtyp
(int, float, ...) oder ein selbstdefinierter Typ sein.
Wie bei der Variablenvereinbarung kann auch bei der Funktionsvereinbarung noch
zusätzlich die Speicherklasse angegeben werden, womit die Anordnung der Funktion im
Speicher beschrieben wird. Eine Funktion kann als
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
60
C/C++ Programmierung
extern (Definition in einer anderen Textdatei, global im gesamten Programm, Standard)
oder
static (nur in eigener Textdatei sichtbar, d.h. global im eigenen Text) definiert werden.
Beispiel:
Projekt öffnen
// Deklaration (Prototyp):
int maximal(int, int);
//Definition:
int maximal(int a, int b)
{
int ergebnis;
if (a>b) { ergebnis = a; } else { ergebnis = b; }
return(ergebnis);
}
//Aufruf:
void main(void)
{
int e;
e = maximal(3,10);
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
61
C/C++ Programmierung
Beispiele für Funktionsaufrufe:
Funktion
Aufruf der Funktion
mit Namen:
int Quadrat (int Zahl )
{
return ( Zahl*Zahl ) ;
}
Quadrat (2) ;
in einer Zuweisung:
int Ergebnis = Quadrat ( 2 ) ;
in einer Ausgabe:
cout << Quadrat (2) ;
in Bedingungsausdrücken:
if ( Quadrat ( 2 ) > 10 ) Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
62
C/C++ Programmierung
Syntax einer einfachen Funktionsdefinition ohne Parameterübergabe
Funktion:
void Funktionsname (void)
{ Variablendeklariation;
Konstantendeklaration;
Anweisung 1;
Anweisung 2;
}
Aufruf:
Beispiel in C++:
Funktionsname ( );
Projekt öffnen
#include <iostream>
using namespace std;
// Funktion
void berechne ( void )
{
int Resultat;
Resultat = 36 * 6 / 3;
cout << "Das Ergebnis der Berechnung ist " << Resultat <<"."<< endl;
}
void main (void)
{
berechne (); // Aufruf
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
63
C/C++ Programmierung
Syntax von Funktionen mit Parametern und Rückgabewert
Funktion:
RückgabeDatentyp Funktionsname (Parameter1, Parameter2, … )
{ ……..
return ( RückgabeDaten);
}
Aufruf:
[void] Funktionsname (Parameter1, Parameter2, ... ); /*Aufruf ohne Rückgabewert*/
oder
Var= Funktionsname (Parameter1, Parameter2, ... ); /*Aufruf mit Rückgabewert*/
Beispiel in C++:
Projekt öffnen
//Zinsrechnung
//----------------------------------------------------------------------------#include <iostream>
using namespace std;
//
//----------------------------------------------------------------------------//Funktionsdefinition
//---------------------------------------------------------------------------float Zinsen ( int Kapital, float Zinssatz )
{
return (Kapital*Zinssatz/100 );
}
//---------------------------------------------------------------------------//Hauptfunktion
//---------------------------------------------------------------------------void main (void)
{
int Geld;
float Prozent;
cout <<
"\n Wieviel Geld wollen Sie anlegen? ";
cin
>>
Geld;
cout <<
" Wie hochprozentig ist das Angebot? ";
cin
>>
Prozent;
cout <<
"\n Und das haben Sie davon: "
<<
Zinsen (Geld, Prozent)
<< endl;
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
64
C/C++ Programmierung
3.1.2 Liste einiger häufig gebrauchter Systemfunktionen
Headerdatei
Funktion
Beschreibung
Trigometrische u. Hyperbolische Funktionen
math.h
double sin(double x)
liefert sin(x)
math.h
double sinh(double x)
liefert sinh(x)
math.h
double cos(double x)
liefert cos(x)
math.h
double cosh(double x)
liefert cosh(x)
math.h
double tanh(double x)
liefert tanh(x)
math.h
double atan2(double y, x)
liefert arctan(y/x)
Exponential- und Logarithmische Funktionen
math.h
double exp(double x)
berechnet die Exponentialfunktion zur Basis e
(2.7182..).
7.389 = exp(2.0);
math.h
double ldexp(double x, int exp)
berechnet x*2exp
math.h
double log(double x)
berechnet ln x (natürlicher Logarithmus)
math.h
double log10(double x)
berechnet log10x (dekadischer Logarithmus)
Potenzfunktionen
math.h
double pow(double x,y)
berechnet xy (Potenzieren)
math.h
double pow10(double x)
berechnet 10x (Potenzieren)
math.h
double sqrt(double x)
liefert die Quadratwurzel von x
Sonstige Funktionen
math.h
int abs(int x)
liefert den mathematischen Absolutbetrag von x
math.h
double hypot(double x, y)
berechnet die Hypothenuse eines rechtwinkligen
Dreiecks für die Katheten x und y
math.h
double floor (double x);
liefert den nächstkleineren ganzzahligen Wert
kleiner
oder gleich x
2 = floor (2.51);
2 = floor (2.41);
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
65
C/C++ Programmierung
math.h
int abs( int x)
liefert den mathematischen Absolutbetrag von x im
int Format
math.h
double ceil(double x)
rundet x auf Ganzzahl im double-Format
3 = ceil (2.41),
3 = ceil (2.51);
int getche(void)
dito – sichtbar
conio.h
int kbhit(void)
prüft, ob Taste gedrückt wurde (ob Zeichen im
Tastaturpuffer bereitsteht)
stdlib.h
char *itoa(int x,char *s, int b)
wandelt eine int-Zahl x in einen String zur
Zahlenbasis b (2,8,10,16)
stdlib.h
char *ltoa(long int x,char *s, int
b)
wandelt eine long int-Zahl x in einen String zur
stdlib.h
typ max(typ x,y)
liefert das Maximum im typ der zu vergleichenden
typ-Größen x und y
stdlib.h
typ min(typ x,y)
liefert das Minimum im typ der zu vergleichenden
typ-Größen x und y
Zahlenbasis b (2,8,10,16)
Zufallszahlen
stdlib.h
int rand(void)
liefert eine int-Zufallszahl zwischen 0 und +215-1
stdlib.h
int random(int ber)
liefert eine int-Zufallszahl zwischen 0 und +ber-1
stdlib.h
int randomize()
Initialisierung des Zufallszahlengenerators. Vor
rand()und random() einzusetzen
stdlib.h
void srand( unsigned int seed)
Erzeugung einer neuen Sequenz von
Zufallszahlen, seed gibt den Startwert an
dos.h
void nosound(void)
Abschalten des durch sound() hervorgerufenen
Tones
dos.h
void sleep(unsigned sek)
Programmablauf wird um sek Sekunden verzögert
dos.h
void sound(unsigned frq)
Eine Tonausgabe in der Frequenz frq wird bis
nosound() über Lautsprecher aktiviert.
Funktionen für Zeichenketten
string.h
strlen(ZK)
Zeichenkettenlänge (ohne Endekennzeichen)
string.h
strcpy(ZK1,ZK2)
ZK1 bekommt den Wert von ZK2 (ZK2: Variable
oder
Konstante, ZK1: Variable)
Beispiel: strcpy(ZK1, "");
(Löschen von ZK1, dh. in ZK1[0] steht '\0')
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
66
C/C++ Programmierung
string.h
strncpy (ZK1,ZK2,max )
Es werden 'max' Zeichen von ZK2 kopiert.
string.h
strcat(ZK1,ZK2)
ZK2 wird an ZK1 angehängt. Das 1. Zeichen von
ZK2
überschreibt das Endekenzeichen von ZK1. Diese
'\0'
wird am Ende der gesamten Zeichenkette
angefügt.
string.h
strncat (ZK1,ZK2,max)
An ZK1 werden 'max' Zeichen von ZK2
angehängt.
string.h
ZK1 wird mit ZK2 verglichen.
strcmp(ZK1,ZK2)
= 0: wenn ZK1<ZK2
Beispiele (sin(x), sqrt(double x), pow(double x,y) zur Verwendung der Headerdatei math.h:
Projekt hier öffnen
Beispiel C++: Zufallsgenerator
Pojekt öffnen
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
void main(void)
{
srand (time(NULL));
//Initialisierung des Zufallsgenerators
int i;
for ( i=0; i<20; i++ )
cout<<rand()<<"\t";
cout<<endl<<endl;
// Erzeugung von 20 Zahlen vom Typ int
for ( i=0; i<20; i++ )
// Erzeugung von 20 Zahlen vom Typ int im Bereich
cout<<rand()%6+1<<"\t"; // von 1 bis 6
cout<<endl<<endl;
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
67
C/C++ Programmierung
3.1.3 Funktionsdeklaration (Prototyp)
Funktionen, die man vor ihrer Definition aufruft und die keinen ganzzahligen Wert
zurückliefern, muss man durch eine Funktionsdeklaration (Prototyping) bekanntmachen.
Syntax des Prototyping
1) Rückgabedatentyp FktName ( Datentyp1 Name1, Datentyp2 Name2, ..);
2) Rückgabedatentyp FktName ( Name1, Name2, ... ) ;
Beispiel:
void Ausgabe (int Ausgabewert) ;
/* Prototyp */
void Ausgabe (int Ausgabewert )
{
cout<< "Die Summe ist " << Wert;
}
/* Definition* /
Im folgenden Programm werden die einzelnen Aufgaben des Programms auf Funktionen
verteilt. Es soll nach Eingabe eines Nettobetrages der Bruttobetrag bei einer
Mehrwertsteuer von 19% berechnet werden.
Die Funktion Eingabe liest einen Wert ein. Die Funktion Berechne führt eine Berechnung
durch und die Funktion Ausgabe ist für die Ausgabe des berechneten Wertes zuständig.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
68
C/C++ Programmierung
Beispiel in C:
Projekt öffnen
Beispiel in C++:
Projekt öffnen
float Eingabe (void);
void Ausgabe (float Brutto);
float Berechne (float Netto,
const float MwSt);
#include <iostream>
using namespace std;
float Eingabe (void);
void Ausgabe (float Brutto);
float Berechne (float Netto,
const float MwSt);
void main(void)
{
float Netto, Brutto;
const float MwSt = 0.19;
Netto = Eingabe();
Brutto = Berechne (Netto, MwSt);
Ausgabe (Brutto);
}
void main(void)
{
float Netto, Brutto;
const float MwSt = 0.19;
Netto = Eingabe();
Brutto = Berechne (Netto, MwSt);
Ausgabe (Brutto);
}
float Eingabe ()
{
float Netto;
printf ("Geben Sie den Nettobetrag ein.
");
scanf
("%f", &Netto);
fflush
(stdin);
return (Netto);
}
float Eingabe ()
{
float Netto;
cout<<"Geben Sie den Nettobetrag ein.
";
cin>>
Netto;
fflush(stdin);
return (Netto);
}
void Ausgabe (float Brutto)
{
printf ("\n\Der Bruttobetrag betraegt %8.2f
", Brutto);
}
void Ausgabe (float Brutto)
{
cout<<"\n\Der Bruttobetrag betraegt "<<
Brutto<<endl;
}
float Berechne (float Netto, const float
MwSt)
{
return (Netto * (1.0 + MwSt));
}
float Berechne (float Netto, const float
MwSt)
{
return (Netto * (1.0 + MwSt));
}
#include <stdio.h>
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
69
C/C++ Programmierung
3.1.4 Rekursiver Funktionsaufruf
Funktionen können in sich selbst - rekursiv - aufgerufen werden.
void fkt()
{
Anweisung1;
Anweisung2;
…
fkt ( );
…
}
Beispiel : Fakultät ( n! = 1*2*3* .. (n-1)*n )
Beispiel in C++:
Projekt öffnen
//Fakultät ( n! = 1*2*3*.. (n-1)*n )
#include <iostream>
using namespace std;
int fakult( int n)
{ cout << n;
// Gestaltung des Ausgabe-Bildschirms
if ( n>1 ) cout << "*"; // dito
if ( (n==1) | (n==0)) return( 1 );
else return( n * fakult( n-1 ) ); // Rekursion
}
void main(void)
{ int i;
cout << "Gib eine ganze positive Zahl ein: "; cin >> i;
cout << " = "<< i << "! = " << fakult( i )<< endl;
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
70
C/C++ Programmierung
3.2 Felder (Arrays)
Felder stellen eine Zusammenfassung von Elementen gleicher Typen dar. Jedes
dieser Elemente kann mittels eines Index identifiziert werden. Die Indizierung
beginnt immer bei 0.
3.2.1 Vereinbarung von Feldern
Vor der Verwendung einer Feldvariablen muss diese vereinbart werden:
Typ
//(Elementeanzahl: konstanter int-Ausdruck)
Name [ Elementeanzahl ] ;
Die Definition
char wort [5]
Anzahl der Feld-Elemente
Name des Feldes
Typ der Feld-Elemente
liefert einen Vektor, der fünf Zeichen aufnehmen kann.
Element
1.
2.
3.
4.
5.
1
2
3
4
Feld
Index
0
Beispiele:
int zensur[6];
//6 int-Größen: zensur[0] . . . zensur[5]
double widerstand[3];
//Feld von 3 double-Zahlen: widerstand[0] . . . widerstand[2]
char zk[50];
//Feld von 50 Zeichen: zk[0] . . . zk[49]
int datum [31] [12];
/*zweidimensionales Array mit 31 Zeilen und 12 Spalten
(31*12 = 372 int-Elemente)
datum[0] [0] . . . datum[30] [11]*/
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
71
C/C++ Programmierung
float drei [5] [4] [3];
0
1
2
//dreidimensionales Feld
3
4
5
6
7
8
9
10
11
0
1
2
.
.
.
Spalte
Zeile
29
30
Das zweidimensionale Feld
datum [31] [12]
wird zeilenweise gespeichert :
datum[0][0] ... datum[0][11] , datum[1][0] ... datum[1][11] , datum[2][0] ... datum[2][11] , usw.
3.2.2 Zugriff auf Feldelemente
Beim Zugriff auf ein Feldelement kann jeder int-Ausdruck als Index verwendet
werden:
zensur [i+3] = datum [10] [i];
Globale Felder (d.h. außerhalb von Funktionen definierte Felder) und statische, lokale
Felder (d.h. innerhalb von Funktionen erklärte, sowie Felder der Speicherklasse static)
können bei der Vereinbarung initialisiert werden.
Initialisierung der Feldelemente
Die Anfangswerte für die Feldelemente sind durch Komma ( , ) getrennt in
{
}
anzugeben. Die Angaben zur Felddimension können dabei wegfallen (der Compiler
ermittelt die Dimension aus der Anzahl der Initialwerte):
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
72
C/C++ Programmierung
static int monat [ ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
//(Feld mit 12 Elementen)
int flaeche [ ] [ ] = { {1, 2, 3}, {4, 5, 6} };
//(zweidimensional, flaeche [1] [1] = 5)
int aber[5] = { 1, 2, 3, 4, 5 };
/*(das Feld 'aber' hat 5 Elemente,
aber[0] = 1)*/
char pipapo [ ] = { 'H' , 'e' , 'u' , 't' , 'e' };
//(Feld mit 5 Zeichen)
char aber [ ] = "Heute";
//(Feld mit 6 Zeichen -Abschluss: \0 -)
Nachfolgendes Beispiel zeigt eine Addition von Feldelementen, die durch eine WhileSchleife realisiert wird.
Beispiel in C:
Beispiel in C++:
#include<stdio.h>
#include<iostream>
Projekt öffnen
using namespace std;
int main(void)
int main(void)
{int i,sum,feld[ ]={0,1,2};
{int i, sum, feld[]={0,1,2};
i=sum=0;
i=sum=0;
while(i<3)
while(i<3)
{sum=sum+feld[i];
{sum=sum+feld[i];
i=i+1;} /*SchleifenEnde*/
i=i+1;} /*SchleifenEnde*/
/*Summeausgeben*/
/*Summeausgeben*/
printf("summe=%d\n",sum);
cout<< "summe = "<<sum <<endl;
return 0;
return 0;
}
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
73
C/C++ Programmierung
3.2.3 Zeichenketten
Eine Zeichenkette ist ein Feld aus
"char", das mit einer binären Null
(Ersatzdarstellung '\0' , ASCII= 0) abgeschlossen wird.
Textkonstanten werden in " " eingeschlossen. Das Endekennzeichen wird bei
Textkonstanten "automatisch" gesetzt.
Textvariablen werden
- wie Textkonstanten-
als Felder aus "char" definiert, wobei
beachtet werden muss, dass das Endekennzeichen
'\0'
ebenfalls ein Feldelement
belegt.
Eine Zeichenkette wird mittels der Funktion
(iostream.h)
bzw.
cin
eingegeben. Als Argument wird der Name des Feldes (ohne
[ ] )
gets
(stdio.h)
angegeben, in das der Text gespeichert werden soll. Das Ende-Kennzeichen
( '\0' ) wird von dieser Funktion "automatisch" eingetragen.
Beispiel:
char text[30];
//Das Feld kann 29 Zeichen aufnehmen
cout << "\nText-Eingabe: "; cin >> text; cout <<"\nKontroll-Ausgabe: " << text;
Falls mehr als 30 Zeichen eingegeben wurden, werden die restlichen Zeichen,
einschließlich des EKZ '\0', abgeschnitten (undefinierte Ausgabe).
Sie können Zeichenkettenvariablen nicht über das Gleichheitszeichen eine Zeichenkette
zuweisen. Für diesen Fall werden folgende Funktionen (z.B. strcpy) bereitgestellt.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
74
C/C++ Programmierung
In der Header-Datei string.h sind eine Reihe Zeichenketten-Funktionen und in der
Header-Datei stdlib.h Umwandlungsfunktionen definiert.
Eine besondere Form der Zeichenketten ist mit Zeigern möglich (Folgekapitel!).
Zeichenketten zuweisen
//Das Feld Name kann 29 Zeichen aufnehmen
char Name[30];
char Name[30] =“MEIER“;
Name=“MEIER“;
//FALSCH!
strcpy (Name, “MEIER“);
//Richtig
Auf einzelne Zeichen einer Zeichenkette zugreifen
char String[11] =“ABCDEFGHIJ“;
char Zeichen;
Zeichen = String[5];
//Zeichen hat nun den Inhalt F
Zeichen = String[10];
//Zeichen hat nun den Inhalt 0x00
String[3] = Zeichen;
//Der String hat nun den Inhalt “ABC“
Funktionen zur Zeichenkettenverarbeitung
Das Kopieren von Strings erfolgt mittels der Bibliotheksfunktion strcpy (string copy),
das Anhängen von Strings an schon vorhandene ZK mittels strcat (string catenate) u.
das Vergleichen zweier ZK mittels der Funktion strcmp (string compare).
Um die Funktionen für die Zeichenkettenverarbeitung nutzen zu können, muss die
Header- Datei string eingebunden sein.
Funktion
strcpy
Beschreibung
Beispiel
Diese Funktion überträgt den Inhalt des char ziel[10];
Ausgangsfeldes in das Zielfeld.
char quelle[ ] =“Text“;
strcpy (ziel, quelle) ;
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
75
C/C++ Programmierung
strlen
Diese Funktion liefert die Länge einer int len;
Zeichenkette zurück. Das abschließende len =strlen(“HALLO“);
Nullzeichen wird nicht mit gezählt.
strcat
Über diese Funktion können Sie eine char ziel[5];
Zeichenkette an eine andere hängen.
char quelle[ ] =“XT“;
Das Nullzeichen der Zielzeichenkette strcpy (ziel,“TE“);
wird überschrieben.
strcat (ziel, quelle);
strcmp
Über diese Funktion können Sie zwei char st1[ ]=”tst”;
Zeichenketten
zeichenweise
verglei- char st2[ ]=”test2”;
chen. Ist die erste Zeichenkette
if (strcmp(st1, st2) == 0)
 kleiner als die zweite, wird eine Zahl
kleiner Null,
 sind beide gleich, wird Null und
 sonst
eine
Zahl
größer
Null
zurückgegeben.
Die von C geerbten Zeichenketten vom Typ char weisen die Nachteile, dass der
Speicher nicht dynamisch nach Anforderung belegt wird, und eines hohen
Fehlerpotenzial durch fehlenden Kontrolle der Speichergrenzen auf.
In C++ gibt es in der Standardbibliothek eine Klasse string, die diese Nachteile
beseitigt. Es muss ebenfalls der Header string eingebunden werden.
#include <string>
using namespace std;
string meinName;
Die Klasse string bietet einige Vorteile. So muss beim Anlegen eines Objekts nicht
angegeben werden, wie viele Zeichen reserviert werden sollen. Wird mehr Platz
benötigt,
sorgt
das
Objekt
selbst
dafür,
dass
es
den
erforderlichen
Speicherbereich bekommt.
Der größte Vorteil ist, dass die Strings einfach zu zuweisen und zu vergleichen
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
76
C/C++ Programmierung
sind, wie es bei Integer-Variablen der Fall ist.
//Vergleich
//Verkettung
//Strings können mit dem Operator + verkettet werden.
string s, s1, s2;
string s1, s2;
s = s1 + s2;
if (s1 == s2) //
Beispiel in C++:
s = s1 + " xxx " + s2;
Projekt öffnen
#include <iostream> #include <string> using namespace std;
int main (void)
{
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;
// copy str1 into str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// concatenates str1 and str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// total lenghth of str3 after concatenation
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
77
C/C++ Programmierung
3.3 Pointer (Zeiger)
3.3.1 Der Datentyp Pointer
Ein Zeiger (Pointer) speichert keinen Wert wie eine Variable, sondern eine Adresse, an
der ein Wert im Speicher des Computers gespeichert werden kann.
Pointer werden z.B. auf folgenden Gebieten eingesetzt:

Dynamische Speicherverwaltung,

Parameterübergabe in Funktionen,

Zeichenkettungsverarbeitung.
Mittels eines Pointers ist es möglich, auf die Speicherplatzadressen zuzugreifen:
* Zgr bedeutet: Inhalt der Speicherzelle, deren Adresse in Zgr steht.
Zeigervariablen werden durch Vorstellen des *Operators
double *za;
deklariert.
Durch die Zuweisung
za = &a;
speichert die Zeigervariable die Adresse der Variablen a.
Mit dem *Operator kann durch die Zuweisung
*za=14.7;
indirekt der Inhalt der Variablen a geändert werden.
Speicheradresse
Speicherinhalt
a
750000230
14.7
za
850700321
750000230
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
78
C/C++ Programmierung
Ein Zeiger (Pointer) ist ein Datentyp, der Adressen von Objekten eines bestimmten
Datentyps aufnehmen kann.
Dies können Speicherplatzadressen von einfachen als auch zusammengesetzten
Datenelementen sein, einschließlich Funktionen.
Auch von Zeigern selbst können wiederum die Adressen in Zeigern abgelegt werden
(zweifach indirekte Adresse).
Zeigervariable dürfen nur auf Objekte eines bestimmten Typs zeigen.
Vor ihrer Verwendung müssen Pointervariable vereinbart werden. Dabei muss der
Typ angegeben werden, auf den sie verweisen. Zeigervariable werden bei der
Vereinbarung durch * gekennzeichnet. Zeigervariable, die wiederum auf einen Zeiger
verweisen, erhalten als Präfix ** (max. 32 mal *).
int a;
Variable vom Typ int
int *z_i;
Vereinbarung eines Zeigers auf eine Integergröße
Lies: z_i zeigt auf ein Objekt vom Typ int. Der Typ dieser Variablen ist int , der Name ist z_i.
char ch, *z_ch;
Vereinbarung einer char-Variablen und eines Pointers, der auf
ein char-Objekt verweist.
int **z_z_ganz;
Vereinbarung eines Zeigers auf Zeiger, die auf int-Werte
verweisen
double *c[3];
Feld von Zeigern, die auf double zeigen
Beispiel:
Es wurde vereinbart: double a, b, *z_d;
Mit der Zuweisung z_d = &a; erhält die Pointervariable z_d die Adresse der doubleVariablen a.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
79
C/C++ Programmierung
3.3.2 Initialisierung der Zeigervariablen
Adressen von Variablen
zeig = &var;
int var, *zeig;
Anfangsadressen von Arrays
zeig = arr;
int arr[10], *zeig;
Adresse eines Arrayelementes
zeig = &arr[3];
int arr[10], *zeig;
Adressen anderer Zeiger
zeig = zeig2;
int zeig*, zeig2*;
Adressen von Zeigern auf Zeiger
zeig2 = &var; zeig = &zeig2; int var, zeig*, zeig2*;
Beispiel:
int *ptr, i;
*ptr =12;
/* Falsch, da der Inhalt des Zeigers eine zufällige Adresse ist */
ptr = &i;
*ptr = 12;
/* Richtig, der Inhalt des Zeigers ist die Adresse der Variablen i*/
3.3.3 Dynamische Speicherbereiche
Mit
Hilfe
von
Zeigern
und
den
Funktionen/
Operatoren
der
dynamischen
Speicherverwaltung kann der Speicherplatzverbrauch eines Programms flexibel an die
reale Notwendigkeit angepasst werden. Will man z.B. eine Liste aller Schüler einer
Schule sortieren, so ist der Aufbau eines Arrays sicher günstig. Bei der „normalen“
Speichernutzung muss jedoch die maximale Dimensionierung des Arrays, sprich die
maximale Schülerzahl, schon bei der Programmentwicklung festgelegt werden.
Man könnte beispielsweise ein Array für die Speicherung von maximal 3000 Schülern
anlegen. Für eine kleine Schule mit nur 200 Schülern wäre der Speicherplatz viel zu groß
und für eine große Schule mit 4000 Schülern zu klein dimensioniert. Besser wäre hier
eine dynamische Speicherzuweisung (Heap), bei der der benötigte Speicherbereich
erst während der Laufzeit „allokiert“ wird.
In C++ kann mit Hilfe des Operators new Speicherplatz im Heap reserviert werden. Mit dem
Operator delete wird diese Reservierung wieder aufgehoben.
Das folgende Beispiel stellt diese Arbeitsweise vor:
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
80
C/C++ Programmierung
Zuerst wird eine Zeigervariable
double *za;
deklariert.
Mit der Anweisung
za = new double [Anzahl];
wird der erforderliche Speicherplatz reserviert. Nach Abschluss der Berechnung muss mit
delete za;
der zuvor reservierte Speicherplatz wieder freigegeben werden.
Beispiel in C++:
Projekt öffnen
#include <iostream>
using namespace std;
void main(void)
{ int *p, size, i;
cout << "Wie groß soll das Array sein? ";
cin >> size;
p = new int[size];
//Heap-Zuweisung
if(p == NULL)
cout << "Speicherfehler\n";
else
{ for(i = 0; i < size; i++)
{
cout << "Einen Wert: ";
cin >> p[i];
}
cout << "Ihre Eingabe war: \n";
for(i = 0; i < size; i++)
cout << p[i] << endl;
delete p; // Heap-Freigabe
}
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
81
C/C++ Programmierung
3.4
Strukturen
Strukturen sind eine Möglichkeit neue Datentypen anzulegen, die mehrere vorher
definierte unterschiedliche Datentypen zu einer Verwaltungseinheit zusammenfassen
und gemeinsam nutzbar machen.
3.4.1 Strukturbeschreibung
struct [<Strukturbezeichner>]
{
<Datentyp> <Datenelemente>;
<Datentyp> <Datenelemente>;} [var1, var2];
Strukturen werden mit der Anweisung struct definiert. Sie müssen einen Namen Strukturbezeichner- erhalten, wenn die Strukturvariablen -var1, var2 - später
definiert werden sollen.
Eine Struktur kann auch mit der typedef-Anweisung beschrieben werden:
typedef struct { <Datentyp> <Datenelement>; ...} <Strukturbezeichner>;
Bei der Definition der Instanzen einer Struktur, die vom Typ einer mit Strukturbezeichner
definierten Struktur sind, wird der Strukturbezeichner wie im Normalfall der Datentyp
verwendet.
Beispiel:
struct Schueler { char Name[20]; char Vorname[20]; Zensur; }
KL12a[30], KL12b[30];
Schueler KL11a[30], KL11b[30], neu;
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
82
C/C++ Programmierung
Im Beispiel wurde eine Struktur mit Namen „Schueler“ definiert. Die Struktur fasst die
Variablen Name, Vorname und Zensur zu einer Einheit „Schueler“ zusammen. Sie wird
zur Definition von insgesamt 4 Array’s und eine Einzelvariable verwendet.
Die Array’s enthalten alle 30 Elemente. In jedem dieser Elemente könnten Name,
Vorname und Zensur eines Schülers abgelegt werden. Es wurde also Speicherplatz für 4
Klassen zu je 30 Schülern und für einen einzelnen Schüler in der Variablen „neu“
geschaffen.
3.4.2 Initialisierung und Zugriff auf Strukturen
Eine Initialisierung der inneren Variablen einer Strukturinstanz kann schon bei der
Definition erfolgen:
Schueler KL10a[] = { { "Joamei", "Jens",2 }, { "Bergner", "Susanne",3 },
{ "Stadler", "Heiko",4 } };
Während des Programmlaufs können natürlich auch Zuweisungen zu Strukturvariablen
vorgenommen werden:
strcpy( neu.Name,"Bachner");
strcpy( neu.Vorname,"Gerti");
neu.Zensur = 5;
KL12a[25]=neu;
cout << KL12a[25].Name << ", " <<KL12a[25].Vorname << " : " << KL12a[25].Zensur;
Die Schülerin erhielt in der Struktur „neu“ seine Angaben eingetragen. In der letzten Anweisung „KL12a[25]=neu;“ wird die Stärke der Arbeit mit Strukturen deutlich. Die Angaben zur Schülerin werden mit dieser kurzen Anweisung vollständig in das Element 25 des
Arrays KL12a kopiert. Der Zugriff auf Strukturelemente ist in der letzten Zeile gut erkennbar.
Auf die Elemente einer Strukturinstanz wird also nach dem Schema
Instanzname.Strukturvariablenname
zugegriffen.
Im Beispiel kann man auf den 4. Buchstaben im Namen des Schülers 14 in KL12a mit
KL12a[13].Name[3]
zugreifen.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
83
C/C++ Programmierung
Das Programm ADRESSE2 kann bis zu zehn eingegebene Adressen speichern. Die
Datenstruktur zur Speicherung der Adressen wird global definiert. Dadurch braucht beim
Anlegen von Variablen nicht das Schlüsselwort struct mit angegeben zu werden.
Beispiel in C++:
Projekt öffnen
# include <iostream>
# include <iomanip>
using namespace std;
struct Adressen
{
char Name [16];
char Ort[16];
char Tel[11];
};
//string Name;
//string Ort;
//string Tel;
void main(void)
{
int i, Index =0;
char Ende = 'n';
Adressen Adressdaten[10];
while ((Index !=10) && (Ende != 'J') && (Ende != 'j'))
{
cout<<"Bitte geben Sie den Namen ein: ";
cin>>setw(16)>>Adressdaten[Index].Name;
cout<<"Bitte geben Sie den Wohnort ein: ";
cin>> setw(16)>>Adressdaten[Index].Ort;
cout<<"Bitte geben Sie die Telefonnummer ein: ";
cin>> setw(11)>>Adressdaten[Index].Tel;
cout<<"Beenden j/n ? : ";
cin>>setw(1)>> Ende;
Index++;
}
for (i=0; i<Index; i++)
cout << setw(18) <<Adressdaten[i].Name <<setw(18) <<Adressdaten[i].Ort
<<setw(11) <<Adressdaten[i].Tel<<endl;
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
84
C/C++ Programmierung
3.4.3 unions
Die union ist die Varianten-record-Konstruktion der C++-Sprache. Es werden mehrere
Variable als Teil einer union definiert, Speicherplatz wird aber nur in der Größe der
längsten Variablen reserviert.
union Datenmix { int var1; char var2;};
Var2
Byte1
Var1
Byte2
Für die union Datenmix werden nur 2 Byte reserviert, weil der größte Datentyp (int) diese
Länge hat.
Egal, ob Sie var1 oder var2 benutzen, Sie arbeiten mit demselben Speicherbereich. Das
heißt, eine Veränderung von var1 führt zu einer Veränderung von var2. Diese
Arbeitsweise ist vor allem zur Sparsamkeit beim Speicherplatz günstig anzuwenden.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
85
C/C++ Programmierung
3.5
Zeiger als Parameter in Funktionen und auf Strukturen
3.5.1 Funktionen
3.5.1.1 Parameterübergabe
Standardfall:
call by value
Beim Aufrufen einer Funktion werden im Standardfall nur die Werte der Parameter
übergeben (call by value), d.h. die Funktion kann nur lesend, aber nicht schreibend
auf die übergebenen Parameter zugreifen.
Beispiel:
Projekt öffnen
#include <iostream>
using namespace std;
//Prototyp
int chaab (int, int);
/*Prototyp der falschen Prozedur chaab */
//Hauptfunktion
void main(void)
{
int a=10, b=5;
chaab(a, b);
cout <<"a= "<<a<<endl; cout<<"b=
"<<b<<endl;
}
/*Aufruf von chaab:
Die beiden Variablen a und b bleiben
unverändert. */
//Funktion
int chaab(int x1, int x2)
{
int temp;
temp=x1;
x1=x2;
x2=temp;
return 0;
}
/* in chaab werden nur die lokalen Variablen
x1 und x2 vertauscht. */
Beim Funktionsaufruf chaab(a,b) werden die Werte von a und b an die Funktion chaab
übergeben; innerhalb der Funktion chaab werden zwar die Werte x1 und x2 korrekt
vertauscht, davon unberührt bleiben aber die Variablen a und b in main.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
86
C/C++ Programmierung
Parameterübergabe:
call by reference
Mit Zeigern als Funktionsparametern können in C/C++ Adressen von Variablen und
damit Verweise auf die Variablen an Funktionen übergeben werden. Dies gestattet, dass
die Funktionen auch schreibend auf Variablen zugreifen und die Werte von
Argumenten auch innerhalb von Funktionen verändert werden können.
Beispiel:
Projekt öffnen
#include <iostream>
using namespace std;
//Prototyp
int chaab (int *, int *);
/*Prototyp der Prozedur chaab */
/* Die Argumente sind vom Typ "Zeiger auf int" */
//Hauptfunktion
void main(void)
{
int a=10, b=5;
cout<<"a="<<a<<" b= "<<b
<<endl;
chaab(&a,&b);
cout<<"nach Prorammaufruf\n";
cout<<"a="<<a<<" b=
"<<b<<endl;
}
//Funktion
int chaab(int *x1, int *x2)
{
int temp;
temp= *x1;
*x1= *x2;
*x2=temp;
cout<<*x1<<endl;
cout<<&x1<<endl;
return 0;
}
/*Aufruf von chaab:
Es werden die Adressen von a und b übergeben.
main und chaab greifen auf dieselben Speicherplätze
zu; Die Werte von a und b werden vertauscht. */
/* *x1, *x2 und a und b sind Werte aus den jeweils
selben Speicherplätzen (dieselben Adressen) */
Es werden die Adressen von a und b übergeben. main und chaab greifen auf dieselben
Speicherplätze zu. Die Werte von a und b werden auch in main vertauscht.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
87
C/C++ Programmierung
Beispiel :
Projekt öffnen
#include <iostream>
using namespace std;
void eingabe(float *kapital, int *laufzeit)
{
cout<<"Wieviel Geld moechten Sie anlegen? ";
cin>>*kapital;
cout<<"Wieviele Jahre moechten Sie das Geld anlegen? ";
cin>>*laufzeit;
}
//Funktion eingabe
void ausgabe(float *kapital, int *laufzeit, float *zins, float *endkapital)
{
cout<<"\nKapital:\t "<<*kapital;
cout<<"\nLaufzeit:\t "<<*laufzeit;
cout<<"\nZinssatz:\t "<<*zins;
cout<<"\nEndkapital:\t "<<*endkapital<<endl;
}
//Funktion ausgabe
void rechnen(float *kapital, int *laufzeit, float *zins, float *endkapital)
{
if ((*laufzeit > 4)||(*kapital>10000))
*zins =5.;
else *zins=3.5;
*endkapital=(*kapital)*(1+*zins/100.0 *(*laufzeit));
}
//Funktion rechnen
void main(void)
{
int laufzeit;
float kapital, zins;
float endkapital;
char c='j';
do
{
eingabe(&kapital, &laufzeit);
rechnen(&kapital, &laufzeit, &zins, &endkapital);
ausgabe(&kapital, &laufzeit, &zins, &endkapital);
//Hauptfunktion
cout<<"weitere Berechnungen durchfuehren? (j/n)";cin>>c;
}
while(c=='j');
}
/* im Vorfeld bitte die Praktikumsaufgabe 03-1.2 betrachten */
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
88
C/C++ Programmierung
3.5.1.2 Felder als Funktionsparameter
Werden Felder als Parameter in Funktionen benutzt, wird beim Funktionsaufruf nur
die Adresse des ersten Feldelements übergeben. Diese Art der Parameterübergabe
hat drei wichtige Konsequenzen:

Als Argument übergebene Felder können in Funktionen verändert werden.

Es findet keine Feldgrenzenüberprüfung beim Funktionsaufruf mit Feldern statt.

Bei der Definition von Feld-Parametern muss entweder ein entsprechender
Zeigertyp explizit angegeben werden oder es wird automatisch eine
Umwandlung in einen Zeigertyp vorgenommen.
Dies soll anhand einiger Beispiele verdeutlicht werden. Dabei wird die Funktion quad
definiert und aufgerufen. In quad werden alle Elemente eines Feldes quadriert.
1. Fall: Feld wird in der Funktionsdeklaration und –definition explizit mit seiner
Größe angegeben
Beispiel :
Projekt öffnen
# include <iostream>
using namespace std;
int quad(int a[10], int);
//Hauptmodul
int main(void)
{
int afeld[10];
int i;
for (i=0;i<10;i++) afeld[i]=i+1;
quad(afeld,10);
for(i=0;i<10;i++)
cout<<"a["<<i<<"] =" <<afeld[i] <<endl;
}
//Funktion
int quad(int a[10], int len)
{
int i;
for (i=0;i<len;i++)
a[i]=a[i]*a[i];
return 0;
}
Dr. E. Thiem
/*Prototyp von quad*/
/*Definition des Feldes afeld*/
/*Beschreibung der Komponenten afeld[i] */
/*Aufruf von quad*/
/*Die Änderung in quad ist auch in main wirksam*/
/*Ausgabe des quadrierten Feldes*/
/*Definition der Funktion quad*/
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
89
C/C++ Programmierung
Das Beschreiben von a[i] in der Funktion quad wird auch im Feld afeld[i] in main
wirksam, weil die Parameterdefinition vom Typ “Feld vom Typ int“ vom Compiler
automatisch in den Typ “Zeiger auf Feld vom Typ int“ umgewandelt wird.
Als Parameter wird eigentlich kein Feld, sondern nur ein Zeiger auf ein Feld übergeben.
Beim Funktionsaufruf wird deshalb durch quad(afeld, 10) nicht das Feld afeld, sondern
nur die Adresse des ersten Elementes übergeben, also &afeld[0].
Auch das Quadrieren der Feldelemente lässt sich einfacher mit Zeigern formulieren:
Beispiel:
//Funktion
int quad(int *a, int len)
{
int i;
for (;len>=0;) {*a=(*a) * (*a); a++; len--;}
return 0;
}
Dr. E. Thiem
/*Definition der Funktion quad*/
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
90
C/C++ Programmierung
3.5.2 Zeiger auf eine Struktur
Für Zeiger auf eine Struktur gibt es folgende Schreibweise für den Zugriff auf
eine Komponente:
Zeigervariable -> Komponentenname
Beispiel:
struct complex
{
double re;
double im;
};
complex x , *cptr;
/* Variable x dieses Typs, Zeiger auf eine Variable dieses
Typs */
float f;
/*Anweisungen: Zugriff */
f = x.re;
/* Zugriff auf die 1. Komponente re von x */
f = cptr -> im;
/* Zugriff auf die 2. Komponente im von cptr */
Beispiel:
struct Adresse{
int Nummer;
char Name[21];
char Ort[31];
char Plz[6];};
struct Adresse *Aptr, Adr;
/*Zeiger und Strukturvariable anlegen */
Aptr = &Adr;
/*Zeiger enthält die Adresse von Adr*/
Aptr -> Nummer = 1;
strcpy (Aptr -> Name, "Hans");
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
91
C/C++ Programmierung
Zusammenfassung – Syntax von Zeigern auf Strukturen
Zeiger auf Strukturen
struct Adresse
*p_Adresse, Meine_Freundin;
//Zeiger mit einer Adresse belegen
p_Adresse = &Meine_Freundin;
//Mit Pfeiloperator hat man über den Zeiger Zugriff auf die einzelnen Elemente:
p_Adresse -> Nummer=1,
Beispiel in C++:
Beispiel öffnen
#include<iostream>
using namespace std;
struct Adressen {
char Name[16];
char Ort[16];
char Tel[11];
};
void main(void)
{int i, index =0;
char Ende ='n';
Adressen *ptr, Adressdaten[10];
ptr = &Adressdaten[0];
// oder ptr = Adressbuch;
while ((index !=10) && (Ende != 'J') &&(Ende != 'j'))
{
cout <<"Bitte geben Sie den Namen ein: ";
cin>>ptr -> Name;
cout <<"Bitte geben Sie den Wohnort ein: ";
cin>>ptr -> Ort;
cout <<"Bitte geben Sie die Telefonnummer ein: ";
cin>>ptr -> Tel;
cout<<"Beenden j/n ?: ";
cin>>Ende;
index++;
ptr++;
}
ptr =&Adressdaten[0];
for (i=0; i<index;i++)
{cout<<ptr ->Name<<"\t"<<ptr ->Ort<<"\t"<<ptr ->Tel<<"\n";
*ptr++;}
cout<<endl;
}
/* siehe im Vorfeld Beispiel im Kapitel 3.4 */
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
92
C/C++ Programmierung
3.5.3 Zeiger auf Funktionen
Zeiger enthalten immer eine Adresse. Aus diesem Grund kann man mit einem Zeiger
auch die Startadresse einer Funktion speichern. Anwendungsmöglichkeiten bestehen
z.B. in:
 Sortierfunktion, denen über einen Zeiger die Adresse einer Funktion übergeben
wird, die zwei Elemente vergleicht. Dadurch kann eine Sortierfunktion für
verschiedene Datentypen oder auch verschiedene Sortierfunktionen verwendet
werden.
 Zweidimensionalen Feldern, die aus Paaren von Kommandos und Zeigern auf
Funktionen bestehen. Anhand einer Benutzereingabe (Kommando) wird die
entsprechende Funktion über den Zeiger ausgeführt.
Rückgabetyp(*Name)(Parameter1, Parameter2, …);
Name= FktName;
[Variable= ] Name (Parameter, Parameter2, …);]
Beispiel in C++:
Projekt öffnen
# include <iostream>
using namespace std;
#include <iomanip>
int mult (int a, int b)
{return a*b;}
int add (int a, int b)
{return a+b; }
void main(void)
{
int (*fptr)(int, int);
int i;
char c;
cout<<"Waehlen Sie Addition (A) oder Multiplikation (M)\n ";
cin>>setw(1)>>c;
switch (c){
case 'M': fptr =mult; break;
case 'A': fptr =add; break;}
i = fptr(12,13);
cout<<"i hat den Wert "<<i<<endl;
}
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
93
C/C++ Programmierung
3.6
Aufgaben zum Kapitel 3
1. Es werden zusätzlich zur Altersangabe die Namen der Schüler eingegeben. Es
sollen die Namen des ältesten und des jüngsten Schülers bestimmt werden!
2. Die Schülernamen aus Aufgabe 1 sollen alphabetisch sortiert ausgegeben werden.
3. Geben Sie über Tastatur die natürlichen Zahlen m und n ein. Anschließend werden
über Tastatur, die Elemente der (m,n)-Matrix A und anschließend die Elemente der
(n,m)-Matrix B abgefordert. Nach der Eingabe werden drei Matrizen auf Bildschirm
ausgegeben: A, B, A+B.
4. Geben Sie zusätzlich A*B aus!
5. Schreiben Sie ein C++-Programm, dass über Bediengerät die Eingabe einer
natürlichen Zahl n abfordert. Bestimmen Sie die Summe aller natürlichen Zahlen x für
die gilt: x  n. Bestimmen Sie auch die Summe aller geraden und aller durch 7
teilbaren Zahlen x für die x  n gilt!
6. Lösen Sie Aufgabe 5 mit Hilfe eines rekursiven Funktionsansatzes!
7. Durch die Zufallszahlenfunktion random() sind n Tipps für 6 aus 49 auf dem
Bildschirm auszugeben.
Über Tastatur ist die Anzahl der gewünschten Tipps abzufordern. Für die Tipps
gelten folgende Forderungen:
a) alle 6 Zahlen verschieden.
b) mindestens drei Zahlen sind größer als 31,
c) wenigstens zwei der Zahlen folgen unmittelbar aufeinander (z.B. 16,17)
Alle Tipps werden innerhalb der 6 Zahlen sortiert ausgegeben.
8. Schaffen Sie eine Struktur für die Bücher einer Bibliothek mit folgenden Angaben zu
jedem Buch: Lfd-Nummer, Titel, Verfasser, Preis, zur Entleihung zugelassen (j/n),
Erscheinungsjahr, Verlag, Datum der Aufnahme in die Bibliothek, Anzahl der
Exemplare. Schaffen Sie eine Möglichkeit zur Erfassung der Daten! Lassen Sie das
Programm folgende Angaben ausgeben
a) Titel und Erscheinungsjahr des Buches, das am längsten in der Bibliothek ist.
b) Titel, Verfasser und Preis des teuersten Buches
c) Titel, Verfasser aller Bücher eines einzugebenden Verlages
d) Titel, Verfasser aller Bücher eines einzugebenden Erscheinungsjahres.
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
94
C/C++ Programmierung
9. Wieso müssen die Datentypen der Argumente nicht mit dem Ergebnistyp
übereinstimmen?
10. Beschreiben Sie den Zusammenhang der C++-Funktionsdeklaration und einem
Funktionsprototyp!
11. Erklären Sie den Sinn rekursiver Funktionsaufrufe!
12. Wie viel Feldelemente besitzt das Feld Arr[21,3]?
13. Warum benötigt ein char-Array ein um 1Byte größeren Speicherbereich für die
Abspeicherung eines Strings?
14. Mit welchem Operator geben Sie den Inhalt der Adresse von x und mit welchem die
Adresse von x vor?
15. Was ist ein zweifach indirekter Zugriff auf einen Speicherbereich?
16. Welcher Operator reserviert Platz im Heap und welcher gibt die Reservierung wieder
frei?
17. Stellen Sie einen Zusammenhang zwischen den Begriffen „Datensatz“, Datenfeld“,
„C++-Struktur“ und
„C++-Strukturelement“ her!
18. Was ist der Zweck der Systemfunktion randomize()?
19. Können Pointervariablen als Strukturvariablen verwendet werden? Geben Sie ein
sinnvolles Beispiel!
Dr. E. Thiem
C/C++ Konsolenprogrammierung
Strukturierter Entwurf
95
Herunterladen