forked from pittlerf/ckurs2017
-
Notifications
You must be signed in to change notification settings - Fork 1
/
complexdatatypen.tex
172 lines (158 loc) · 5.23 KB
/
complexdatatypen.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
\newpage
\section{Komplexe Datentypen}
\subsection{Eigene Datentypen mit \texttt{typedef}}
\index{\texttt{typedef}}
Je nach Problemstellung ist es manchmal sehr hilfreich, Datenstrukturen selbst erzeugen zu können.
\texttt{C} bietet dafür die Möglichkeit, und zwar auf verschiedene Weisen.
Zunächst kann man in \texttt{C} einen neuen Typ definieren, z.B. einen eigenen Typ für reelle Zahlen:
\begin{lstlisting}
typedef float real;
\end{lstlisting}
Dieser kann im Quelltext danach wie native \texttt{C} Typen verwendet werden
\begin{lstlisting}
typedef float real;
int main()
{
real x, y = 3.718;
return 0;
}
\end{lstlisting}
Auf den ersten Blick mag eine eigene Definition für eine Datentyp für reelle Zahlen nicht besonders sinnvoll erscheinen.
Allerdings kann man mit dieser Typdefinition zu einem späteren Zeitpunkt sehr einfach die verwendete Genauigkeit für reelle Zahlen ändern.
Nämlich einfach, indem man die Zeile für die Typdefinition durch
\begin{lstlisting}
typedef double real;
\end{lstlisting}
ersetzt.
\subsection{Zusammengesetzte Datentypen}
\index{\texttt{struct}}
Eine weitere Art, einen neuen Datentyp zu definieren, ist zusammengesetzte Datentypen zu definieren.
Ein einfaches mathematisches Beispiel sind Vektoren, die $n$ Elemente haben.
Mithilfe des Schlüsselwrts \verb|struct| kann man in \texttt{C} zusammengesetzten Datentypen definieren, welche man sich wie Kontainer vorstellen kann.
Die allgemeine Benutzung von \verb|struct| ist wie folgt:
\begin{lstlisting}
struct name
{
Type1 name1;
Type2 name2;
Type3 name3;
...
};
\end{lstlisting}
Die Verwendung als Typ für eine Variable:
\begin{lstlisting}
struct name variablename;
\end{lstlisting}
Als Beispiel betrachten wir einen Datentyp für kartesiche Koordinaten mit $x$, $y$ und $z$ Komponente.
Der Datentyp wird wie folgt definiert:
\begin{lstlisting}
struct coord
{
double x, y, z;
};
\end{lstlisting}
mit drei \verb|double| Elementen, jeweils für die $x$, $y$ und $z$ Komponente.
Der Zugriff auf die einzelnen Elemente erfolgt über den Namen des \verb|struct| und den Namen des Elements, getrennt durch einen Punkt.
Für den allgemeinen Fall also wie folgt:
\begin{lstlisting}
struct name
{
Type1 name1;
Type2 name2;
Type3 name3;
...
};
name.name1 = value;
\end{lstlisting}
In unserem Beispiel für den Koordinatentyp sieht dies wie folgt aus
\begin{lstlisting}
#include <stdio.h>
struct coord
{
double x, y, z;
};
int main()
{
struct coord r;
r.x = 1.0;
r.y = 3.4;
r.z = -0.55;
printf("r hat Koordinaten (%e, %e, %e)\n", r.x, r.y, r.z);
return 0;
}
\end{lstlisting}
Also, allgemein gesprochen greift man auf die Elemente über
\begin{lstlisting}
structname.elementname = wert;
\end{lstlisting}
zu.
Elemente können selbst wieder ein \verb|struct| sein.
Einen Unterschied gibt es beim Zugriff auf Elemente, wenn man einen Zeiger auf einen \verb|struct| benutzt.
Dort kann man direkt mit dem Pfeil Operator \verb|->| auf die Elemente zugreifen:
\begin{lstlisting}
#include <stdio.h>
struct corrd
{
double x, y, z;
};
int main()
{
struct coord r;
struct coord *v = &r;
v->x = 1.0; // aequivalent zu (*v).x = 1.0;
v->y = 3.4; // aequivalent zu (*v).y = 3.4;
v->z = -0.55 // aequivalent zu (*v).z = -0.55;
printf("r hat Koordinaten (%e, %e, %e)\n", v->x, v->y, v->z);
return 0;
}
\end{lstlisting}
Elemente eines \verb|struct| können natürlich auch Zeiger sein.
Allerdings muss dann Speicher außerhalb der Deklaration des \texttt{struct} reserviert werden.
\subsection{Beispiel: Datentyp für kartesische Koordinaten}
Die Verwendung von \verb|struct| ist sehr hilfreich, um logisch zusammengehörige Daten gesammelt zu übergeben und zu bearbeiten.
Es muss dann nicht mehr jedes Element einzeln übergeben werden, sondern nur noch einmal der Kontainer.
Der Zusammenhang der einzelnen Elemente bleibt damit erhalten.
Man könnte nun beispielsweise eine Funktion für die Quadratnorm einer Koordinate wie folgt schreiben:
\begin{lstlisting}
#include <stdio.h>
struct coord
{
double x, y, z;
};
double sqnorm(struct coord r) {
return(r.x*r.x + r.y*r.y + r.z*r.z);
}
int main()
{
struct coord r;
r.x = 1.0;
r.y = 3.4;
r.z = -0.55;
printf("r hat Quadratnorm %e\n'', sqnorm(r));
return 0;
}
\end{lstlisting}
Mit einem \verb|struct| wird ebenfalls einer neuer Typ bereitgestellt.
Der entsprechende Name enthält aber immer das Schlüsselwort \verb|struct|, in unserem Fall \verb|struct coord|.
Man kann einen \verb|struct| mit einem \verb|typedef| kombinieren, um nicht immer \verb|struct| schreiben zu müssen.
Im Quelltext sähe das so aus:
\begin{lstlisting}
struct coord
{
double x, y, z;
};
typedef struct coord coord;
\end{lstlisting}
Das sieht etwas verwirrend aus, weil \verb|coord| zweimal auftaucht.
Aber der Ausdruck wird klar, wenn man sich erinnert, dass \verb|struct coord| im Prinzip ein Typ ist.
Und damit ist der Name \verb|coord| noch nicht vergeben.
Die etwas gebräuchlichere Art obiger Typdefinition geht über die Möglichekeit eines anonymen \verb|struct|.
Man kann nämlich auch schreiben:
\begin{lstlisting}
typedef struct
{
double x, y, z;
} coord;
\end{lstlisting}
Damit ist natürlich \verb|struct coord| nicht definiert, aber man kann \verb|coord| wie einen \texttt{C} Typ verwenden.
\endinput