diff --git a/20151105/Makefile-7 b/20151112/Makefile similarity index 59% rename from 20151105/Makefile-7 rename to 20151112/Makefile index 130c77b96aa3bcdffe81977d2bae8864585c4f29..30b65292f10f724409cdcd2b922b2f7a6a4a26a9 100644 --- a/20151105/Makefile-7 +++ b/20151112/Makefile @@ -1,6 +1,6 @@ -SOURCES = opengl-magic-test.c textured-spheres.c +SOURCES = opengl-magic.c textured-spheres.c INCLUDES = opengl-magic.h textured-spheres.h LIBS = -lGL -lGLU -lglut -: $(SOURCES) $(INCLUDES) +%: %.c $(SOURCES) $(INCLUDES) gcc -Wall $< $(SOURCES) $(LIBS) -o $@ diff --git a/20151112/Tower_of_Hanoi.jpeg b/20151112/Tower_of_Hanoi.jpeg new file mode 120000 index 0000000000000000000000000000000000000000..a1a794afda08596ffa2f46f278db53455de25b6c --- /dev/null +++ b/20151112/Tower_of_Hanoi.jpeg @@ -0,0 +1 @@ +../common/Tower_of_Hanoi.jpeg \ No newline at end of file diff --git a/20151112/ainf-20151112.pdf b/20151112/ainf-20151112.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ec8878278c5676b95ce2794b3267a1b4fe99c7b4 Binary files /dev/null and b/20151112/ainf-20151112.pdf differ diff --git a/20151112/ainf-20151112.tex b/20151112/ainf-20151112.tex new file mode 100644 index 0000000000000000000000000000000000000000..8ba1597dd1570876b89c6ddbd642b010070cec13 --- /dev/null +++ b/20151112/ainf-20151112.tex @@ -0,0 +1,384 @@ +% ainf-20151112.pdf - Lecture Slides on Applied Computer Sciences +% Copyright (C) 2012, 2013, 2015 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +\documentclass[10pt,t]{beamer} + +\usepackage{pgslides} +\usepackage{pdftricks} + +\newrgbcolor{orange}{0.7 0.2 0.0} + +\begin{psinputs} + \usepackage[latin1]{inputenc} + \usepackage[german]{babel} + \usepackage[T1]{fontenc} + \usepackage{helvet} + \renewcommand*\familydefault{\sfdefault} + \usepackage{pstricks,pst-grad} +\end{psinputs} + +\title{Angewandte Informatik} +\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski} +\date{12.\ November 2015} + +\begin{document} + +\maketitleframe + +\begin{frame} + \textbf{Sie können diese Vortragsfolien + einschließlich Beispielprogramme, Skript und sonstiger Lehrmaterialien + unter} + \begin{center} + \url{https://gitlab.cvh-server.de/pgerwinski/ainf.git} + \end{center} + \textbf{herunterladen.} + + \bigskip + + \begin{itemize} + \arrowitem + \textbf{\color{blue}Files}\\ + einzelne Dateien herunterladen + \arrowitem + \textbf{\color{blue}Download zip/tar.gz/tar.bz2/tar}\\ + als Archiv herunterladen + \arrowitem + \url{https://gitlab.cvh-server.de/pgerwinski/ainf.git}\\ + mit GIT herunterladen und synchronisieren + \end{itemize} +\end{frame} + +\sectionnonumber{\inserttitle} + +\begin{frame} + + \showsectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \begin{itemize} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliothek verwenden (Beispiel: OpenGL) + \color{medgreen} + \item[3.4] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Algorithmen} + \begin{itemize} + \color{red} + \item[4.1] Differentialgleichungen + \item[4.2] Rekursion + \color{black} + \item[4.3] Stack und FIFO + \item[4.4] Aufwandsabschätzungen + \end{itemize} + \color{gray} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\makebox(0,0){\textbf{\raisebox{0.5ex}{\dots}}}] +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\section{Einführung} +\section{Einführung in C} +\section{Bibliotheken} +\subsection{Der Präprozessor} +\subsection{Bibliotheken einbinden} +\subsection{Bibliothek verwenden (Beispiel: OpenGL)} +\subsection{Projekt organisieren: make} + +\begin{frame}[fragile] + + \showsubsection + \begin{itemize} + \item + Regeln + \medskip + \begin{onlyenv}<2> + \begin{lstlisting}[language=make,gobble=10] + earth-6: earth-6.c opengl-magic.h opengl-magic-test.c \ + textured-spheres.h textured-spheres.c + gcc -Wall earth-6.c \ + -lGL -lGLU -lglut opengl-magic-test.c textured-spheres.c \ + -o earth-6 + \end{lstlisting} + \end{onlyenv} + \item + Makros + \medskip + \begin{onlyenv}<3> + \begin{lstlisting}[language=make,gobble=10] + SOURCES = opengl-magic-test.c textured-spheres.c + INCLUDES = opengl-magic.h textured-spheres.h + LIBS = -lGL -lGLU -lglut + + earth-5: earth-5.c $(SOURCES) $(INCLUDES) + gcc -Wall earth-5.c $(SOURCES) $(LIBS) -o earth-5 + + earth-6: earth-6.c $(SOURCES) $(INCLUDES) + gcc -Wall earth-6.c $(SOURCES) $(LIBS) -o earth-6 + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<4-> + \begin{lstlisting}[language=make,gobble=10] + SOURCES = opengl-magic.c textured-spheres.c + INCLUDES = opengl-magic.h textured-spheres.h + LIBS = -lGL -lGLU -lglut + + %: %.c $(SOURCES) $(INCLUDES) + gcc -Wall $< $(SOURCES) $(LIBS) -o $@ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<5-> + \bigskip + \arrowitem + 3 Sprachen: C, Präprozessor, make + \end{onlyenv} + \end{itemize} + +\end{frame} + +\sectionnonumber{\inserttitle} + +\begin{frame} + + \showsectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \begin{itemize} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliothek verwenden (Beispiel: OpenGL) + \color{medgreen} + \item[3.4] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Algorithmen} + \begin{itemize} + \item[4.1] \color{red}Differentialgleichungen + \item[4.2] Rekursion + \item[4.3] \color{black}Stack und FIFO + \item[4.4] Aufwandsabschätzungen + \end{itemize} + \color{gray} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\makebox(0,0){\textbf{\raisebox{0.5ex}{\dots}}}] +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\section{Algorithmen} +\subsection{Differentialgleichungen} + +\begin{frame}[fragile] + \showsection + \showsubsection + + \vspace*{-\bigskipamount} + + \begin{eqnarray*} + \varphi'(t) &=& \omega(t) \\[\medskipamount] + \omega'(t) &=& -\frac{g}{l}\cdot\sin\varphi(t)\hspace*{7.1cm} + \end{eqnarray*} + + \begin{itemize} + \item + Von Hand (analytisch): Lösung raten (Ansatz), Parameter berechnen + \item + Mit Computer (numerisch): Eulersches Polygonzugverfahren + \end{itemize} + + \medskip + + \begin{lstlisting}[gobble=0] + phi += dt * omega; + omega += - dt * g / l * sin (phi); + \end{lstlisting} + + \bigskip + + Praktikumsaufgabe: Basketball + +\end{frame} + +\subsection{Rekursion} + +\begin{frame}[fragile] + + \showsubsection + + Vollständige Induktion: + \vspace*{-0.725cm} + \begin{displaymath} + \hspace*{4cm} + \left. + \begin{array}{r} + \mbox{Aussage gilt für $n = 1$}\\[2pt] + \mbox{Schluß von $n - 1$ auf $n$} + \end{array} + \right\} + \mbox{Aussage gilt für alle $n\in\mathbb{N}$} + \end{displaymath} + \vspace*{-0.5cm} + + \pause + + Türme von Hanoi + + \begin{onlyenv}<2> + \begin{center} + \includegraphics[width=12.2cm]{Tower_of_Hanoi.jpeg} + \end{center} + \end{onlyenv} + + \begin{onlyenv}<3-> + \begin{itemize} + \item + 64 Scheiben, 3 Plätze, + \only<3-4>{\hfill\makebox(0,0)[rt]{\includegraphics[width=6cm]{Tower_of_Hanoi.jpeg}}}\\ + immer 1 Scheibe verschieben + \item + Ziel: Turm verschieben + \item + Es dürfen nur kleinere Scheiben\\ + auf größeren liegen. + \bigskip + \pause + \pause + \item + $n = 1$ Scheibe: fertig + \item + Wenn $n - 1$ Scheiben verschiebbar:\\ + schiebe $n - 1$ Scheiben auf Hilfsplatz,\\ + verschiebe die darunterliegende,\\ + hole $n - 1$ Scheiben von Hilfsplatz + \end{itemize} + \pause + \vspace{-4.3cm} + \begin{lstlisting}[gobble=6,xleftmargin=6.2cm] + void verschiebe (int n, int start, int ziel) + { + if (n == 1) + verschiebe_1_scheibe (start, ziel); + else + { + verschiebe (1, start, hilfsplatz); + verschiebe (n - 1, start, ziel); + verschiebe (1, hilfsplatz, ziel); + } + } + \end{lstlisting} + \end{onlyenv} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + \begin{minipage}[t]{6cm} + \vspace*{0.5cm} + Floodfill\strut\\ + \begin{lstlisting}[gobble=6] + void fill (int x, int y, char c, char o) + { + if (get_point (x, y) == o) + { + put_point (x, y, c); + fill (x + 1, y, c, o); + fill (x - 1, y, c, o); + fill (x, y + 1, c, o); + fill (x, y - 1, c, o); + } + } + \end{lstlisting} + \end{minipage}\pause + \begin{minipage}[t]{6.3cm} + \vspace*{-1cm} + Aufgabe: Schreiben Sie eine\\ + Bibliothek für "`Text-Grafik"'\\ + mit folgenden Funktionen: + \begin{itemize} + \item + \lstinline|void clear (char c)|\\ + Bildschirm auf Zeichen \lstinline|c| löschen + \item + \lstinline|void put_point (int x, int y, char c)|\\ + Punkt setzen + \item + \lstinline|char get_point (int x, int y)|\\ + Punkt lesen + \item + \lstinline|void fill (int x, int y, char c, char o)|\\ + Fläche in der "`Farbe"' \lstinline|o|,\\ + die den Punkt \lstinline|(x, y)| enthält,\\ + mit der "`Farbe"' \lstinline|c| ausmalen + \item + \lstinline|void display (void)|\\ + Inhalt des Arrays auf dem\\ + Bildschirm ausgeben + \end{itemize} + Hinweis: Verwenden Sie ein\\Array als "`Bildschirm"'. + \end{minipage} + +\end{frame} + +\sectionnonumber{\inserttitle} + +\begin{frame} + + \showsectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \begin{itemize} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliothek verwenden (Beispiel: OpenGL) + \color{medgreen} + \item[3.4] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Algorithmen} + \begin{itemize} + \item[4.1] \color{medgreen}Differentialgleichungen + \item[4.2] Rekursion + \item[4.3] \color{black}Stack und FIFO + \item[4.4] Aufwandsabschätzungen + \end{itemize} + \color{gray} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\makebox(0,0){\textbf{\raisebox{0.5ex}{\dots}}}] +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\end{document} diff --git a/20151112/earth-texture.rgb b/20151112/earth-texture.rgb new file mode 120000 index 0000000000000000000000000000000000000000..0cdfa3a22a83b195aef06eb5392a69adc01735ad --- /dev/null +++ b/20151112/earth-texture.rgb @@ -0,0 +1 @@ +../common/earth-texture.rgb \ No newline at end of file diff --git a/20151112/logo-hochschule-bochum-cvh-text.pdf b/20151112/logo-hochschule-bochum-cvh-text.pdf new file mode 120000 index 0000000000000000000000000000000000000000..a05946126bc0ce6a2818740da2893f59eb0c659c --- /dev/null +++ b/20151112/logo-hochschule-bochum-cvh-text.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum-cvh-text.pdf \ No newline at end of file diff --git a/20151112/logo-hochschule-bochum.pdf b/20151112/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20151112/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20151112/moon-texture.rgb b/20151112/moon-texture.rgb new file mode 120000 index 0000000000000000000000000000000000000000..355b16c44076b25cbbce0cd5978ccad54a85af1e --- /dev/null +++ b/20151112/moon-texture.rgb @@ -0,0 +1 @@ +../common/moon-texture.rgb \ No newline at end of file diff --git a/20151112/opengl-magic.c b/20151112/opengl-magic.c new file mode 100644 index 0000000000000000000000000000000000000000..bcb0b73c7b6070fce08b22866282aa782f59e1bf --- /dev/null +++ b/20151112/opengl-magic.c @@ -0,0 +1,31 @@ +#include <GL/gl.h> +#include <GL/glu.h> +#include <GL/glut.h> +#include "opengl-magic.h" + +void init_opengl (int *argcp, char **argv, char *window_name) +{ + glutInit (argcp, argv); + glutInitDisplayMode (GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH); + glutInitWindowSize (1024, 768); + glutCreateWindow (window_name); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective (20.0, -1.33333, 3.0, 7.0); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + glTranslatef (0.0, 0.0, -5.0); + glClearColor (0.0, 0.0, 0.0, 0.0); + glEnable (GL_DEPTH_TEST); + glEnable (GL_LIGHTING); + glEnable (GL_LIGHT0); + static GLfloat light0_position[] = { 1.0, 0.0, 1.0, 0.0 }; + glLightfv (GL_LIGHT0, GL_POSITION, light0_position); +} + +void set_material_color (float r, float g, float b) +{ + GLfloat color[] = { r, g, b }; + glMaterialfv (GL_FRONT, GL_AMBIENT, color); + glMaterialfv (GL_FRONT, GL_DIFFUSE, color); +} diff --git a/20151112/opengl-magic.h b/20151112/opengl-magic.h new file mode 100644 index 0000000000000000000000000000000000000000..16db806cad2b1aa3e51a2a138707717ab75fcbde --- /dev/null +++ b/20151112/opengl-magic.h @@ -0,0 +1,2 @@ +extern void init_opengl (int *argcp, char **argv, char *window_name); +extern void set_material_color (float r, float g, float b); diff --git a/20151112/orbit-x.c b/20151112/orbit-x.c new file mode 100644 index 0000000000000000000000000000000000000000..ad0fe2444cceb37f5a565ade13f0b4b36b9864c7 --- /dev/null +++ b/20151112/orbit-x.c @@ -0,0 +1,59 @@ +#include <GL/gl.h> +#include <GL/glu.h> +#include <GL/glut.h> +#include "opengl-magic.h" +#include "textured-spheres.h" + +float t = 0.0; +GLuint earth_texture, moon_texture; + +void draw_earth (void) +{ + glPushMatrix (); + glRotatef (90, 1.0, 0.0, 0.0); + glRotatef (100.0 * t, 0.0, 0.0, 1.0); + draw_textured_sphere (earth_texture, 0.25512, 63, 20); + glPopMatrix (); +} + +void draw_moon (void) +{ + glPushMatrix (); + glRotatef (90, 1.0, 0.0, 0.0); + glRotatef (-90, 0.0, 0.0, 1.0); + draw_textured_sphere (moon_texture, 0.06952, 31, 10); + glPopMatrix (); +} + +void draw (void) +{ + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix (); + glRotatef (23.44, 1.0, 0.0, -1.0); + draw_earth (); + glRotatef (5.145, 0.0, 1.0, 1.0); + glRotatef (30.0 * t, 0.0, -1.0, 0.0); + glTranslatef (0.9, 0.0, 0.0); + draw_moon (); + glPopMatrix (); + glFlush (); + glutSwapBuffers (); +} + +void timer_handler (int value) +{ + t += 0.05; + glutPostRedisplay (); + glutTimerFunc (50, timer_handler, 0); +} + +int main (int argc, char **argv) +{ + init_opengl (&argc, argv, "Orbit"); + init_texture ("earth-texture.rgb", 1024, &earth_texture); + init_texture ("moon-texture.rgb", 1080, &moon_texture); + glutDisplayFunc (draw); + glutTimerFunc (50, timer_handler, 0); + glutMainLoop (); + return 0; +} diff --git a/20151112/pgscript.sty b/20151112/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20151112/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20151112/pgslides.sty b/20151112/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20151112/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file diff --git a/20151112/textured-spheres.c b/20151112/textured-spheres.c new file mode 100644 index 0000000000000000000000000000000000000000..3296ae0e53a98d2c3bb3dc22c2caf523bd16c20a --- /dev/null +++ b/20151112/textured-spheres.c @@ -0,0 +1,55 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include "textured-spheres.h" + +#ifndef __USE_POSIX + extern int fileno (FILE *stream); +#endif + +void init_texture (char *image_filename, int image_width, GLuint *texture) +{ + FILE *f = fopen (image_filename, "r"); + if (!f) + { + fprintf (stderr, "textured-spheres.c: cannot open texture file \"%s\": %s", + image_filename, strerror (errno)); + exit (1); + } + struct stat st; + fstat (fileno (f), &st); + size_t size = st.st_size; + int image_height = size / (3 * image_width); + char *image = malloc (size); + if (!image) + { + fprintf (stderr, "textured-spheres.c: cannot load texture file \"%s\": out of memory", + image_filename); + exit (1); + } + fread (image, size, 1, f); + fclose (f); + glGenTextures (1, texture); + glBindTexture (GL_TEXTURE_2D, *texture); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + gluBuild2DMipmaps (GL_TEXTURE_2D, 3, image_width, image_height, GL_RGB, GL_UNSIGNED_BYTE, image); +} + +void draw_textured_sphere (GLuint texture, GLdouble radius, GLint slices, GLint stacks) +{ + static GLfloat white_color[] = { 1.0, 1.0, 1.0 }; + glMaterialfv (GL_FRONT, GL_AMBIENT, white_color); + glMaterialfv (GL_FRONT, GL_DIFFUSE, white_color); + glBindTexture (GL_TEXTURE_2D, texture); + glEnable (GL_TEXTURE_2D); + GLUquadric *sphere = gluNewQuadric (); + gluQuadricTexture (sphere, GL_TRUE); + gluSphere (sphere, radius, slices, stacks); + glDisable (GL_TEXTURE_2D); +} diff --git a/20151112/textured-spheres.h b/20151112/textured-spheres.h new file mode 100644 index 0000000000000000000000000000000000000000..39f8283cbf767f07652cea373109b6319eeb9411 --- /dev/null +++ b/20151112/textured-spheres.h @@ -0,0 +1,10 @@ +#ifndef TEXTURED_SPHERES_H +#define TEXTURED_SPHERES_H + +#include <GL/gl.h> +#include <GL/glu.h> + +extern void init_texture (char *image_filename, int image_width, GLuint *texture); +extern void draw_textured_sphere (GLuint texture, GLdouble radius, GLint slices, GLint stacks); + +#endif /* TEXTURED_SPHERES_H */ diff --git a/common/pgscript.sty b/common/pgscript.sty index 9cade03a54224124de882522a8c59394e5bf2ba0..1de1a990ad440123dad1e25a0fdc421932587687 100644 --- a/common/pgscript.sty +++ b/common/pgscript.sty @@ -1,5 +1,5 @@ % pgscript.sty - LaTeX Settings for Lecture Notes -% Copyright (C) 2012 Peter Gerwinski +% Copyright (C) 2012, 2015 Peter Gerwinski % % This document is free software: you can redistribute it and/or % modify it either under the terms of the Creative Commons @@ -20,16 +20,42 @@ % Attribution-ShareAlike 3.0 Unported License along with this % document. If not, see <http://creativecommons.org/licenses/>. -\usepackage[latin1]{inputenc} -\usepackage[british,german]{babel} -\selectlanguage{german} +\usepackage{amsfonts} +\usepackage[colorlinks,allcolors=blue]{hyperref} +\usepackage[british,german]{babel} % Yes, really "german" and not "ngerman". +\usepackage[utf8]{luainputenc} % Without this, umlauts are broken. Weird. +\usepackage{microtype} \usepackage[T1]{fontenc} \usepackage{times} \usepackage{helvet} \renewcommand*\familydefault{\sfdefault} \usepackage{graphicx} - \usepackage{pstricks} + +% Repair kerning: Automatically insert "\kern{-0.15em}" between "//" % (in URLs). +\directlua{ + local glyph = node.id ("glyph") + local function my_kerning (head) + for t in node.traverse (head) do + if t.id == glyph and t.char == 47 then + if t.next + and t.next.next + and t.next.next.id == glyph + and t.next.next.char == 47 then + local k = node.new ("kern") + k.kern = tex.sp ("-0.15em") + k.next = t.next + k.prev = t + t.next.prev = k + t.next = k + end + end + end + node.kerning (head) + end + luatexbase.add_to_callback ("kerning", my_kerning, "URL kerning") +} + \definecolor{blendedblue}{rgb}{0.2,0.2,0.7} \definecolor{darkgreen}{rgb}{0.0,0.3,0.0} \definecolor{darkred}{rgb}{0.7,0.0,0.0} @@ -41,9 +67,7 @@ \newenvironment{whiteout}{\definecolor{darkgreen}{rgb}{1.0,1.0,1.0}% \definecolor{darkred}{rgb}{1.0,1.0,1.0}% \color{white}}{} -\catcode`\_=13\def_{\kern1pt\rule{0.4em}{0.9pt}\kern1pt}\catcode`\_=8 -\catcode`\/=13\def/#1{\ifx#1/\char`\/\char`\/\else\char`\/#1\fi}\catcode`\/=12 -\newcommand{\url}[1]{{\color{blendedblue}\catcode`~=12\catcode`##=12\catcode`_=13\catcode`/=13\textsf{#1}}}% +\urlstyle{sf} \newcommand{\file}[1]{{\color{blendedblue}#1}} \newcommand{\textarrow}{{\boldmath $\longrightarrow$}} \newcommand{\arrowitem}{\item[\textarrow]} @@ -56,22 +80,22 @@ gobble=4, xleftmargin=1em, columns=fullflexible, - moredelim=**[is][\color{red}]{�}{�}} + moredelim=**[is][\color{red}]{¡}{¿}} \lstdefinestyle{numbered}{xleftmargin=2em, numbers=left, numberstyle=\footnotesize\color{gray}} \lstdefinestyle{terminal}{basicstyle=\ttfamily\color{darkgreen}, language={}, columns=fixed, - moredelim=**[is][\color{darkred}]{�}{�}, - moredelim=**[is][\color{blendedblue}]{�}{�}, - moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{�}{�}} + moredelim=**[is][\color{darkred}]{¡}{¿}, + moredelim=**[is][\color{blendedblue}]{°}{¿}, + moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{²}{¿}} \lstdefinestyle{cmd}{basicstyle=\ttfamily\color{darkred}, language={}, columns=fixed, - moredelim=**[is][\color{darkgreen}]{�}{�}, - moredelim=**[is][\color{blendedblue}]{�}{�}, - moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{�}{�}} + moredelim=**[is][\color{darkgreen}]{¡}{¿}, + moredelim=**[is][\color{blendedblue}]{°}{¿}, + moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{²}{¿}} \setlength{\textwidth}{16.5cm} \setlength{\textheight}{26.0cm} diff --git a/common/pgslides.sty b/common/pgslides.sty index 8d4e35596f6555f427df3d88030dddf362a64084..cde7d23dea1cf8bc70ff12fd6a2b454fc4c6ab24 100644 --- a/common/pgslides.sty +++ b/common/pgslides.sty @@ -20,11 +20,43 @@ % Attribution-ShareAlike 3.0 Unported License along with this % document. If not, see <http://creativecommons.org/licenses/>. -\usepackage[latin1]{inputenc} -\usepackage[german]{babel} +\usepackage{amsfonts} +\usepackage[british,german]{babel} % Yes, really "german" and not "ngerman". +\usepackage[utf8]{luainputenc} % Without this, umlauts are broken. Weird. +\usepackage{microtype} \usepackage[T1]{fontenc} +\usepackage{times} \usepackage{helvet} \renewcommand*\familydefault{\sfdefault} +\usepackage{graphicx} +\usepackage{pstricks} + +\hypersetup{colorlinks,allcolors=blue} + +%% @@@ Not necessary for slides. Why??? +%% Repair kerning: Automatically insert "\kern{-0.15em}" between "//" % (in URLs). +%\directlua{ +% local glyph = node.id ("glyph") +% local function my_kerning (head) +% for t in node.traverse (head) do +% if t.id == glyph and t.char == 47 then +% if t.next +% and t.next.next +% and t.next.next.id == glyph +% and t.next.next.char == 47 then +% local k = node.new ("kern") +% k.kern = tex.sp ("-0.15em") +% k.next = t.next +% k.prev = t +% t.next.prev = k +% t.next = k +% end +% end +% end +% node.kerning (head) +% end +% luatexbase.add_to_callback ("kerning", my_kerning, "URL kerning") +%} \usetheme{default} \usefonttheme{structurebold} @@ -117,9 +149,6 @@ \definecolor{darkgray}{rgb}{0.4,0.4,0.4} \newenvironment{experts}{\color{darkgray}}{} -\catcode`\_=13\def_{\kern1pt\rule{0.4em}{0.9pt}\kern1pt}\catcode`\_=8 -\catcode`\/=13\def/#1{\ifx#1/\char`\/\kern-2pt\char`\/\else\char`\/#1\fi}\catcode`\/=12 -\renewcommand{\url}[1]{{\color{structure}\catcode`~=12\catcode`##=12\catcode`_=13\catcode`/=13\textsf{#1}}} \usepackage{listings} \lstset{basicstyle=\color{structure}, @@ -129,27 +158,27 @@ columns=fullflexible, aboveskip=0pt, belowskip=0pt, - moredelim=**[is][\color{structure}]{�}{�}, - moredelim=**[is][\only<2->{\color{structure}}]{�}{�}, - moredelim=**[is][\only<3->{\color{structure}}]{�}{�}, - moredelim=**[is][\only<4->{\color{structure}}]{�}{�}, - moredelim=**[is][\only<5->{\color{structure}}]{�}{�}, - moredelim=**[is][\only<6->{\color{structure}}]{�}{�}, - moredelim=**[is][\only<7->{\color{structure}}]{�}{�}, - moredelim=**[is][\only<8->{\color{structure}}]{�}{�}} + moredelim=**[is][\color{structure}]{¡}{¿}, + moredelim=**[is][\only<2->{\color{structure}}]{²}{¿}, + moredelim=**[is][\only<3->{\color{structure}}]{³}{¿}, + moredelim=**[is][\only<4->{\color{structure}}]{°}{¿}, + moredelim=**[is][\only<5->{\color{structure}}]{¤}{¿}, + moredelim=**[is][\only<6->{\color{structure}}]{¢}{¿}, + moredelim=**[is][\only<7->{\color{structure}}]{æ}{¿}, + moredelim=**[is][\only<8->{\color{structure}}]{ø}{¿}} \lstdefinestyle{terminal}{basicstyle=\ttfamily\color{darkgreen}, language={}, columns=fixed, - moredelim=**[is][\color{red}]{�}{�}, - moredelim=**[is][\color{blendedblue}]{�}{�}, - moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{�}{�}} + moredelim=**[is][\color{red}]{¡}{¿}, + moredelim=**[is][\color{blendedblue}]{°}{¿}, + moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{²}{¿}} \lstdefinestyle{cmd}{basicstyle=\ttfamily\color{red}, language={}, gobble=2, columns=fixed, - moredelim=**[is][\color{darkgreen}]{�}{�}, - moredelim=**[is][\color{structure}]{�}{�}, - moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{�}{�}} + moredelim=**[is][\color{darkgreen}]{¡}{¿}, + moredelim=**[is][\color{structure}]{°}{¿}, + moredelim=**[is][\sffamily\it\lstset{columns=fullflexible}]{²}{¿}} \lstdefinestyle{shy}{basicstyle=\color{lightgray}} \setcounter{topnumber}{3} @@ -163,6 +192,7 @@ \setlength{\unitlength}{1cm} \newcommand{\protectfile}[1]{#1} +\urlstyle{sf} \newcommand{\file}[1]{{\color{structure}\protectfile{#1}}} \newcommand{\textarrow}{{\boldmath $\longrightarrow$}} \newcommand{\arrowitem}{\item[\textarrow]} diff --git a/script/ainf-2015ws.pdf b/script/ainf-2015ws.pdf index b098db1dff99984f0a9d8ecaeb0eb479159c4524..b7e19e27413582fe24027d48646449fa044eb75c 100644 Binary files a/script/ainf-2015ws.pdf and b/script/ainf-2015ws.pdf differ diff --git a/script/ainf-2015ws.tex b/script/ainf-2015ws.tex index 698c9682b92155cabefe0a51f719e5653fb4c83d..57348129e3b798e2540d6f5623fd16c129beb095 100644 --- a/script/ainf-2015ws.tex +++ b/script/ainf-2015ws.tex @@ -30,8 +30,8 @@ \newcommand{\name}[1]{\textsc{#1}} \newcommand{\ccbysanp}{CC-by-sa (Version 3.0, nicht portiert)} -\newcommand{\fdl}{GNU FDL (Version 1.2 oder h�her)} -\newcommand{\mylicense}{CC-by-sa (Version 3.0) oder GNU GPL (Version 3 oder h�her)} +\newcommand{\fdl}{GNU FDL (Version 1.2 oder höher)} +\newcommand{\mylicense}{CC-by-sa (Version 3.0) oder GNU GPL (Version 3 oder höher)} \newcommand{\pd}{gemeinfrei -- \emph{public domain}} \makeatletter @@ -80,16 +80,15 @@ \strut\vfill - Stand: 10.\ November 2015 + Stand: 11.\ November 2015 Soweit nicht anders angegeben:\\ Copyright \copyright\ 2012, 2013, 2015\quad Peter Gerwinski\\ Lizenz: \mylicense -% Sie k�nnen dieses Skript -% einschlie�lich Beispielprogramme -% herunterladen unter:\\ -% \url{http://www.peter.gerwinski.de/download/ainf-2012ws.tar.gz} + Sie können dieses Skript + einschließlich Vortragsfolien, Beispielprogramme und sonstiger Lehrmaterialien + unter \url{https://gitlab.cvh-server.de/pgerwinski/ainf.git} herunterladen. \endgroup @@ -99,11 +98,11 @@ \clearpage - \section{Einf�hrung} + \section{Einführung} \subsection{Was ist angewandte Informatik?} - Die angewandte Informatik befa�t sich mit der Praxis der Programmierung von Computern. + Die angewandte Informatik befaßt sich mit der Praxis der Programmierung von Computern. Sie vermittelt zwischen den Fachgebieten der Rechnertechnik ("`Wie funktioniert ein Computer?"') und der Softwaretechnik (Theorie des Programmierens). @@ -113,7 +112,7 @@ \small \psset{unit=0.5cm} \psline[arrows=<->](-1,0)(-1,22) - \rput(-1.3,0){\makebox(0,0)[br]{\textbf{gegenst�ndlich}}} + \rput(-1.3,0){\makebox(0,0)[br]{\textbf{gegenständlich}}} \rput(-1.3,22){\makebox(0,0)[tr]{\textbf{abstrakt}}} \rput(-1.3,2){\makebox(0,0)[r]{Elektromagnetismus, Halbleiter}} \rput(-1.3,4){\makebox(0,0)[r]{Elektronische Bauelemente}} @@ -169,30 +168,30 @@ \end{center} Im Gegensatz zu z.\,B.\ Lebewesen wurden Computer von Menschen entwickelt und gebaut. - Daher ist es grunds�tzlich m�glich, sie durch Programmierung vollst�ndig zu beherrschen. + Daher ist es grundsätzlich möglich, sie durch Programmierung vollständig zu beherrschen. \subsection{Programmierung in C} - Ein gro�er Teil dieser Vorlesung wird der Programmierung in der Programmiersprache C gewidmet sein. + Ein großer Teil dieser Vorlesung wird der Programmierung in der Programmiersprache C gewidmet sein. Warum C? - C hat sich als Kompromi� zwischen einer Hochsprache und maximaler N�he zur Hardware + C hat sich als Kompromiß zwischen einer Hochsprache und maximaler Nähe zur Hardware sehr weit etabliert. - Es l�uft auf nahezu jeder Plattform (= Kombination aus Hardware und Betriebssystem) + Es läuft auf nahezu jeder Plattform (= Kombination aus Hardware und Betriebssystem) und stellt somit einen "`kleinsten gemeinsamen Nenner der Programmierung"' dar. C orientiert sich sehr eng an der Funktionsweise der Computer-Hardware und wird daher auch als "`High-Level-Assembler"' bezeichnet. Wie die Assembler-Sprache, die Sie in \emph{Grundlagen Rechnertechnik\/} kennenlernen werden, - ist C ein Profi-Werkzeug und als solches "`leistungsf�hig, aber gef�hrlich"'. - Programme k�nnen in C sehr kompakt geschrieben werden. - C kommt mit verh�ltnism��ig wenigen Sprach"-elementen aus, + ist C ein Profi-Werkzeug und als solches "`leistungsfähig, aber gefährlich"'. + Programme können in C sehr kompakt geschrieben werden. + C kommt mit verhältnismäßig wenigen Sprach"-elementen aus, die je nach Kombination etwas anderes bewirken. - Dies hat zur Folge, da� einfache Schreibfehler, - die in anderen Programmiersprachen als Fehler bem�ngelt w�rden, - in C h�ufig ein ebenfalls g�ltiges Programm ergeben, - das sich aber v�llig anders als beabsichtigt verh�lt. + Dies hat zur Folge, daß einfache Schreibfehler, + die in anderen Programmiersprachen als Fehler bemängelt würden, + in C häufig ein ebenfalls gültiges Programm ergeben, + das sich aber völlig anders als beabsichtigt verhält. \breath @@ -201,44 +200,44 @@ \begin{itemize} \item \textbf{Kompakte Schreibweise:} - H�ufig verwendete Konstrukte werden m�glichst platzsparend notiert. + Häufig verwendete Konstrukte werden möglichst platzsparend notiert. Wie in C, kann auch unter Unix ein falsch geschriebenes Kommando - ein ebenfalls g�ltiges Kommando mit anderer Wirkung bedeuten. + ein ebenfalls gültiges Kommando mit anderer Wirkung bedeuten. \item \textbf{Baukastenprinzip:} - In C wie in Unix bem�ht man sich darum, den unver�nderlichen Kern m�glichst klein zu halten. - Das meiste, was man in C tats�chlich benutzt, ist in Form von Bibliotheken modularisiert; - das meiste, was man unter Unix tats�chlich benutzt, ist in Form von Programmen modularisiert. + In C wie in Unix bemüht man sich darum, den unveränderlichen Kern möglichst klein zu halten. + Das meiste, was man in C tatsächlich benutzt, ist in Form von Bibliotheken modularisiert; + das meiste, was man unter Unix tatsächlich benutzt, ist in Form von Programmen modularisiert. \item \textbf{Konsequente Regeln:} - In C wie in Unix bem�ht man sich darum, - feste Regeln -- mathematisch betrachtet -- m�glichst einfach zu halten + In C wie in Unix bemüht man sich darum, + feste Regeln -- mathematisch betrachtet -- möglichst einfach zu halten und Ausnahmen zu vermeiden. - (Beispiel: Unter MS-DOS und seinen Nachfolgern wird eine ausf�hrbare Datei gefunden, + (Beispiel: Unter MS-DOS und seinen Nachfolgern wird eine ausführbare Datei gefunden, wenn sie sich \emph{entweder} im aktuellen Verzeichnis \emph{oder} im Suchpfad befindet. Unter Unix wird sie gefunden, wenn sie sich im Suchpfad befindet. - Es ist unter Unix m�glich, das aktuelle Verzeichnis in den Suchpfad aufzunehmen; - aus Sicherheitserw�gungen heraus geschieht dies jedoch �blicherweise nicht.) + Es ist unter Unix möglich, das aktuelle Verzeichnis in den Suchpfad aufzunehmen; + aus Sicherheitserwägungen heraus geschieht dies jedoch üblicherweise nicht.) \item \textbf{Kein "`Fallschirm"':} - C und Unix f�hren Befehle ohne Nachfrage aus. + C und Unix führen Befehle ohne Nachfrage aus. (Beispiel: Ein eingegebener Unix-Befehl zum Formatieren einer Festplatte - wird ohne R�ckfrage ausgef�hrt.) + wird ohne Rückfrage ausgeführt.) \end{itemize} - Trotz dieser Warnungen besteht bei Programmier�bungen in C - normalerweise \emph{keine\/} Gefahr f�r den Rechner. - Moderne PC-Betriebssysteme �berwachen die aufgerufenen Programme + Trotz dieser Warnungen besteht bei Programmierübungen in C + normalerweise \emph{keine\/} Gefahr für den Rechner. + Moderne PC-Betriebssysteme überwachen die aufgerufenen Programme und beenden sie notfalls mit einer Fehlermeldung ("`Schutzverletzung"'). Experimente mit Mikro-Controllern, die im Rahmen dieser Vorlesung stattfinden werden, erfolgen ebenfalls in einer Testumgebung, in der kein Schaden entstehen kann. Bitte nutzen Sie die Gelegenheit, in diesem Rahmen Ihre Programmierkenntnisse zu trainieren, - damit Sie sp�ter in Ihrer beruflichen Praxis, - wenn durch ein fehlerhaftes Programm ernsthafter Schaden entstehen k�nnte, + damit Sie später in Ihrer beruflichen Praxis, + wenn durch ein fehlerhaftes Programm ernsthafter Schaden entstehen könnte, wissen, was Sie tun. - \section{Einf�hrung in C} + \section{Einführung in C} \subsection{Hello, world!} @@ -253,29 +252,29 @@ return 0; } \end{lstlisting} - Dieses traditionell erste -- "`einfachste"' -- Beispiel enth�lt in C bereits viele Elemente, - die erst zu einem sp�teren Zeitpunkt zufriedenstellend erkl�rt werden k�nnen: + Dieses traditionell erste -- "`einfachste"' -- Beispiel enthält in C bereits viele Elemente, + die erst zu einem späteren Zeitpunkt zufriedenstellend erklärt werden können: \begin{itemize} \item \lstinline{#include <stdio.h>} - Wir deuten diese Zeile im Moment so, da� uns damit gewisse Standardfunktionen - (darunter \lstinline{printf()} -- siehe unten) zur Verf�gung gestellt werden. + Wir deuten diese Zeile im Moment so, daß uns damit gewisse Standardfunktionen + (darunter \lstinline{printf()} -- siehe unten) zur Verfügung gestellt werden. Diese Betrachtungsweise ist nicht wirklich korrekt - und wird in Abschnitt \ref{Praeprozessor} genauer erkl�rt. + und wird in Abschnitt \ref{Praeprozessor} genauer erklärt. \item \lstinline|int main (void) { ... }| Dies ist das C-Hauptprogramm. - Das, was zwischen den geschweiften Klammern steht, wird ausgef�hrt. + Das, was zwischen den geschweiften Klammern steht, wird ausgeführt. - Auch hier wird zu einem sp�teren Zeitpunkt (Abschnitt \ref{Funktionen}) - genauer erkl�rt werden, was die einzelnen Elemente bedeuten und welchen Sinn sie haben. + Auch hier wird zu einem späteren Zeitpunkt (Abschnitt \ref{Funktionen}) + genauer erklärt werden, was die einzelnen Elemente bedeuten und welchen Sinn sie haben. \end{itemize} \goodbreak - Im folgenden soll nun der eigentliche Inhalt des Programms erkl�rt werden: + Im folgenden soll nun der eigentliche Inhalt des Programms erklärt werden: \begin{lstlisting} printf ("Hello, world!\n"); return 0; @@ -288,147 +287,147 @@ Jede Anweisung wird mit einem Semikolon abgeschlossen. \item Bei \lstinline{printf()} handelt es sich um einen \newterm{Funktionsaufruf}, - dessen Wirkung darin besteht, da� der zwischen den Klammern angegebene \newterm{Parameter\/} + dessen Wirkung darin besteht, daß der zwischen den Klammern angegebene \newterm{Parameter\/} (oder: das \newterm{Argument\/}) der Funktion - auf dem Standardausgabeger�t ausgegeben wird. + auf dem Standardausgabegerät ausgegeben wird. (In unserem Fall handelt es sich dabei um einen Bildschirm.) - Der Name "`\lstinline{printf}"' der Funktion steht f�r "`print formatted"' -- formatierte Ausgabe. + Der Name "`\lstinline{printf}"' der Funktion steht für "`print formatted"' -- formatierte Ausgabe. \item \lstinline{"Hello, world!\n"} ist eine \newterm{Konstante\/} vom Typ \newterm{String\/} (= Zeichenkette). \item \lstinline{\n} ist eine \newterm{Escape-Sequenz}. - Sie steht f�r ein einzelnes, normalerweise unsichtbares Zeichen + Sie steht für ein einzelnes, normalerweise unsichtbares Zeichen mit der Bedeutung "`neue Zeile"'. \item Die Anweisung \lstinline{return 0} bedeutet: Beende die laufende Funktion (hier: \lstinline{main()}, also das Hauptprogramm) - mit dem R�ckgabewert 0. - (Bedeutung: "`Programm erfolgreich ausgef�hrt."' -- siehe Abschnitt \ref{Funktionen}.) + mit dem Rückgabewert 0. + (Bedeutung: "`Programm erfolgreich ausgeführt."' -- siehe Abschnitt \ref{Funktionen}.) \end{itemize} - \subsection{Programme compilieren und ausf�hren} + \subsection{Programme compilieren und ausführen} Der Programmtext wird mit Hilfe eines Eingabeprogramms, des \newterm{Texteditors}, in den Computer eingegeben und als Datei gespeichert. Als Dateiname sei hier \file{hello-1.c} angenommen. Die Dateiendung \file{.c} soll anzeigen, - da� es sich um einen Programmquelltext in der Programmiersprache C handelt. + daß es sich um einen Programmquelltext in der Programmiersprache C handelt. - Die \file{.c}-Datei ist f�r den Computer nicht direkt ausf�hrbar. - Um eine ausf�hrbare Datei zu erhalten, - mu� das Programm zuerst in die Maschinensprache des verwendeten Computers �bersetzt werden. + Die \file{.c}-Datei ist für den Computer nicht direkt ausführbar. + Um eine ausführbare Datei zu erhalten, + muß das Programm zuerst in die Maschinensprache des verwendeten Computers übersetzt werden. Diesen Vorgang nennt man \newterm{Compilieren}. In einer Unix-Shell mit installierter GNU-Compiler-Collection - (GCC; fr�here Bedeutung der Abk�rzung: GNU-C-Compiler) + (GCC; frühere Bedeutung der Abkürzung: GNU-C-Compiler) geschieht das Compilieren durch Eingabe der folgenden Zeile, der \newterm{Kommandozeile\/}: \begin{lstlisting}[style=terminal] - $ �gcc hello-1.c -o hello-1� + $ ¡gcc hello-1.c -o hello-1¿ \end{lstlisting} - Das Zeichen \lstinline[style=terminal]{$} steht f�r die \newterm{Eingabeaufforderung\/} + Das Zeichen \lstinline[style=terminal]{$} steht für die \newterm{Eingabeaufforderung\/} (oder das \newterm{Prompt\/}) der Unix-Shell. Es kann auch anders aussehen, z.\,B.\ \lstinline[style=terminal]{voyager2/home/peter/bo/2012ws/ainf/script/examples>}. Die Eingabeaufforderung wird vom Computer ausgegeben; - die Kommandozeile rechts daneben m�ssen wir eingeben und mit der Eingabetaste (Enter) best�tigen. + die Kommandozeile rechts daneben müssen wir eingeben und mit der Eingabetaste (Enter) bestätigen. \lstinline[style=cmd]{gcc} ist ein Befehl an den Computer, - n�mlich der Name eines Programms, das wir aufrufen wollen (hier: der Compiler). - Die darauf folgenden Teile der Kommandozeile hei�en die \newterm{Parameter\/} + nämlich der Name eines Programms, das wir aufrufen wollen (hier: der Compiler). + Die darauf folgenden Teile der Kommandozeile heißen die \newterm{Parameter\/} oder \newterm{Argumente\/} des Befehls. Der Parameter \lstinline[style=cmd]{hello-1.c} ist der Name der Datei, die compiliert werden soll. \lstinline[style=cmd]{-o} ist eine \newterm{Option\/} an den Compiler, - mit der man ihm mitteilt, da� der n�chste Parameter \lstinline[style=cmd]{hello-1} - der Name der ausf�hrbaren Datei ist, die erzeugt werden soll. + mit der man ihm mitteilt, daß der nächste Parameter \lstinline[style=cmd]{hello-1} + der Name der ausführbaren Datei ist, die erzeugt werden soll. - Unter Unix ist es �blich, ausf�hrbaren Dateien \emph{keine\/} Endung zu geben. - Unter Microsoft Windows w�re es stattdessen �blich, - die ausf�hrbare Datei \lstinline[style=cmd]{hello-1.exe} zu nennen. + Unter Unix ist es üblich, ausführbaren Dateien \emph{keine\/} Endung zu geben. + Unter Microsoft Windows wäre es stattdessen üblich, + die ausführbare Datei \lstinline[style=cmd]{hello-1.exe} zu nennen. \breath Um von einer Unix-Shell aus ein Programm aufzurufen, - gibt man dessen vollst�ndigen Namen - -- einschlie�lich Verzeichnispfad und eventueller Endung -- als Kommando ein: + gibt man dessen vollständigen Namen + -- einschließlich Verzeichnispfad und eventueller Endung -- als Kommando ein: \begin{lstlisting}[style=terminal] - $ �./hello-1� + $ ¡./hello-1¿ \end{lstlisting} - Der Punkt steht f�r das aktuelle Verzeichnis; - der Schr�gstrich trennt das Verzeichnis vom eigentlichen Dateinamen. + Der Punkt steht für das aktuelle Verzeichnis; + der Schrägstrich trennt das Verzeichnis vom eigentlichen Dateinamen. Wenn sich ein Programm im Suchpfad befindet (z.\,B.: \lstinline[style=cmd]{gcc}), darf die Angabe des Verzeichnisses entfallen. (Den Suchpfad kann man sich mit dem Kommando \lstinline[style=cmd]{echo $PATH} anzeigen lassen.) - Aus Sicherheitsgr�nden steht das aktuelle Verzeichnis - unter Unix �blicherweise \emph{nicht\/} im Suchpfad. + Aus Sicherheitsgründen steht das aktuelle Verzeichnis + unter Unix üblicherweise \emph{nicht\/} im Suchpfad. \breath \begin{experts} - Dateiendungen dienen unter Unix nur der �bersicht, + Dateiendungen dienen unter Unix nur der Übersicht, haben aber keine technischen Konsequenzen: \begin{itemize} \item - Ob eine Datei als ausf�hrbar betrachtet wird oder nicht, - wird nicht anhand einer Endung, sondern �ber ein \newterm{Dateiattribut\/} entschieden. + Ob eine Datei als ausführbar betrachtet wird oder nicht, + wird nicht anhand einer Endung, sondern über ein \newterm{Dateiattribut\/} entschieden. Die Dateiattribute werden beim Listen des Verzeichnisinhalts angezeigt: \begin{lstlisting}[style=terminal,gobble=10] - $ �ls -l� + $ ¡ls -l¿ -rwxr-x--- 1 peter ainf 6294 4. Okt 14:34 hello-1 -rw-r--r-- 1 peter ainf 82 4. Okt 15:11 hello-1.c \end{lstlisting} - Jedes \lstinline[style=terminal]{r} steht f�r "`read"' (Datei lesbar), - jedes \lstinline[style=terminal]{w} f�r "`write"' (Datei schreibbar) - und jedes \lstinline[style=terminal]{x} f�r "`execute"' (Datei ausf�hrbar). - Von links nach rechts stehen die \lstinline[style=terminal]{rwx}-Gruppen f�r + Jedes \lstinline[style=terminal]{r} steht für "`read"' (Datei lesbar), + jedes \lstinline[style=terminal]{w} für "`write"' (Datei schreibbar) + und jedes \lstinline[style=terminal]{x} für "`execute"' (Datei ausführbar). + Von links nach rechts stehen die \lstinline[style=terminal]{rwx}-Gruppen für den Besitzer der Datei (hier: \lstinline[style=terminal]{peter}) eine Benutzergruppe (hier: \lstinline[style=terminal]{ainf}) - und f�r alle anderen Benutzer des Computers. + und für alle anderen Benutzer des Computers. Im o.\,a.\ Beispiel ist die Datei \file{hello-1.c} - f�r den Benutzer \lstinline[style=terminal]{peter} les- und schreibbar, - f�r alle Angeh�rigen der Gruppe \lstinline[style=terminal]{ainf} nur lesbar - und f�r alle anderen Benutzer des Computers ebenfalls nur lesbar. + für den Benutzer \lstinline[style=terminal]{peter} les- und schreibbar, + für alle Angehörigen der Gruppe \lstinline[style=terminal]{ainf} nur lesbar + und für alle anderen Benutzer des Computers ebenfalls nur lesbar. Die Datei \file{hello-1} (ohne Endung) ist hingegen - f�r den Benutzer \lstinline[style=terminal]{peter} les-, schreib- und ausf�hrbar, - f�r alle Angeh�rigen der Gruppe \lstinline[style=terminal]{ainf} les- und ausf�hrbar, - aber nicht schreibbar. Alle anderen Benutzer des Computer haben f�r die Datei - \file{hello-1} �berhaupt keine Zugriffsrechte. + für den Benutzer \lstinline[style=terminal]{peter} les-, schreib- und ausführbar, + für alle Angehörigen der Gruppe \lstinline[style=terminal]{ainf} les- und ausführbar, + aber nicht schreibbar. Alle anderen Benutzer des Computer haben für die Datei + \file{hello-1} überhaupt keine Zugriffsrechte. \item Welcher Art der Inhalt der Datei ist, entnimmt Unix dem Inhalt selbst. Man kann sich dies mit Hilfe des Befehls \lstinline[style=cmd]{file} anzeigen lassen: \begin{lstlisting}[style=terminal,gobble=10] - $ �file hello-1� + $ ¡file hello-1¿ hello-1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped - $ �file hello-1.c� + $ ¡file hello-1.c¿ hello-1.c: ASCII C program text \end{lstlisting} \item - Eine ausf�hrbare Datei, die Text enth�lt, ist ein sogenanntes \newterm{Shell-Skript}. + Eine ausführbare Datei, die Text enthält, ist ein sogenanntes \newterm{Shell-Skript}. Der Aufruf eines Shell-Skripts bewirkt i.\,w.\ dasselbe, - als wenn man den darin enthaltenen Text als Kommandos eingeben w�rde. + als wenn man den darin enthaltenen Text als Kommandos eingeben würde. \item - Ein C-Quelltext enth�lt i.\,d.\,R.\ \emph{keine\/} g�ltigen Unix-Kommandos - und kann daher \emph{nicht\/} "`einfach so"' ausgef�hrt werden. + Ein C-Quelltext enthält i.\,d.\,R.\ \emph{keine\/} gültigen Unix-Kommandos + und kann daher \emph{nicht\/} "`einfach so"' ausgeführt werden. \item - Es ist zul�ssig, aber normalerweise nicht sinnvoll, - einer ausf�hrbaren Datei die Endung \file{.c} zu geben. + Es ist zulässig, aber normalerweise nicht sinnvoll, + einer ausführbaren Datei die Endung \file{.c} zu geben. \end{itemize} \end{experts} \subsection{Zahlenwerte ausgeben} - Da es m�glich ist, mittels der Funktion \lstinline{printf()} + Da es möglich ist, mittels der Funktion \lstinline{printf()} eine String-Konstante wie z.\,B.\ \lstinline{"Hello, world!\n"} "`einfach so"' auszugeben, - liegt die Vermutung nahe, Integer-Konstanten auf gleiche Weise ausgeben zu k�nnen. + liegt die Vermutung nahe, Integer-Konstanten auf gleiche Weise ausgeben zu können. Datei \file{output-12.c}: \begin{lstlisting} @@ -442,7 +441,7 @@ \end{lstlisting} Beim Compilieren dieses Programms erhalten wir eine Warnung: \begin{lstlisting}[style=terminal] - $ �gcc output-12.c -o output-12� + $ ¡gcc output-12.c -o output-12¿ output-12.c: In function 'main': output-12.c:5: warning: passing argument 1 of 'printf' makes pointer from integer without a cast @@ -450,39 +449,39 @@ 'const char * __restrict__' but argument is of type 'int' \end{lstlisting} \goodbreak - Es entsteht trotzdem eine ausf�hrbare Datei \file{output-12}. - Wenn wir diese jedoch ausf�hren, erhalten wir eine Fehlermeldung: + Es entsteht trotzdem eine ausführbare Datei \file{output-12}. + Wenn wir diese jedoch ausführen, erhalten wir eine Fehlermeldung: \begin{lstlisting}[style=terminal] - $ �./output-12� + $ ¡./output-12¿ Segmentation fault \end{lstlisting} - Tats�chlich ist die direkte �bergabe einer Integer-Konstanten an \lstinline{printf()} - ein grober Fehler: \lstinline{printf()} akzeptiert als ersten Parameter nur Ausdr�cke vom Typ String. + Tatsächlich ist die direkte Übergabe einer Integer-Konstanten an \lstinline{printf()} + ein grober Fehler: \lstinline{printf()} akzeptiert als ersten Parameter nur Ausdrücke vom Typ String. Der C-Compiler nimmt eine implizite Umwandlung der Integer-Konstanten in einen String vor: Die Zahl wird als eine Speicheradresse interpretiert, an der sich der Text befindet. - Dies ist nicht besonders sinnvoll (daher die Warnung), aber in C zul�ssig. + Dies ist nicht besonders sinnvoll (daher die Warnung), aber in C zulässig. - Wenn nun das Programm ausgef�hrt wird, versucht es, auf die Speicheradresse Nr.\ 42 zuzugreifen. - Diese befindet sich normalerweise au�erhalb des Programms. + Wenn nun das Programm ausgeführt wird, versucht es, auf die Speicheradresse Nr.\ 42 zuzugreifen. + Diese befindet sich normalerweise außerhalb des Programms. Das Betriebssystem bemerkt den illegalen Zugriffsversuch und bricht das Programm mit einer Fehlermeldung - ("`Speicherzugriffsfehler"', "`Schutzverletzung"' o.\,�.) ab. + ("`Speicherzugriffsfehler"', "`Schutzverletzung"' o.\,ä.) ab. Auf einer Plattform ohne derartige Schutzmechanismen (z.\,B.\ einem Mikro-Controller) - wird das fehlerhafte Programm hingegen klaglos ausgef�hrt. - Es werden dann sinnlose Texte, die sich zuf�llig an Speicheradresse Nr.\ 42 befinden, - auf dem Standardausgabeger�t ausgegeben. + wird das fehlerhafte Programm hingegen klaglos ausgeführt. + Es werden dann sinnlose Texte, die sich zufällig an Speicheradresse Nr.\ 42 befinden, + auf dem Standardausgabegerät ausgegeben. \breath Dieses fehlerhafte Programm illustriert, wie leicht es in der Programmiersprache C ist, einen Absturz zu programmieren. - Die meisten anderen Programmiersprachen w�rden das fehlerhafte Programm nicht akzeptieren; - anstelle der o.\,a.\ Warnung bek�me man eine �hnlichlautende Fehlermeldung. + Die meisten anderen Programmiersprachen würden das fehlerhafte Programm nicht akzeptieren; + anstelle der o.\,a.\ Warnung bekäme man eine ähnlichlautende Fehlermeldung. \breath - Wie man nun tats�chlich in C Zahlenwerte ausgibt, + Wie man nun tatsächlich in C Zahlenwerte ausgibt, illustriert das Beispielprogramm \file{output-1.c}: \begin{lstlisting} #include <stdio.h> @@ -494,10 +493,10 @@ } \end{lstlisting} Der erste Parameter von \lstinline{printf()}, der sog.\ \newterm{Format-String}, - enth�lt das Symbol \lstinline{%d}. + enthält das Symbol \lstinline{%d}. Diese sog.\ \newterm{Formatspezifikation\/} wird in der Ausgabe durch den Zahlenwert des zweiten Parameters von \lstinline{printf()} ersetzt. - Das \lstinline{d} steht hierbei f�r "`dezimal"'. + Das \lstinline{d} steht hierbei für "`dezimal"'. \breath @@ -505,18 +504,18 @@ % Wenn man anstelle von \lstinline{%d} die Formatspezifikation \lstinline{%x} verwendet, % wird die Zahl in hexadezimaler anstatt in dezimaler Schreibweise ausgegeben. Wenn man zwischen das Prozentzeichen un das \lstinline{d} eine Zahl schreibt (z.\,B.\ \lstinline{%3d}), - gibt man damit die Breite eines Feldes an, in die die auszugebende Zahl rechtsb�ndig geschrieben wird. - Wenn man die Feldbreite mit einer Null beginnen l��t (z.\,B.\ \lstinline{%03d}) - wird die auszugebende Zahl von links mit Nullen bis zur Feldbreite aufgef�llt. + gibt man damit die Breite eines Feldes an, in die die auszugebende Zahl rechtsbündig geschrieben wird. + Wenn man die Feldbreite mit einer Null beginnen läßt (z.\,B.\ \lstinline{%03d}) + wird die auszugebende Zahl von links mit Nullen bis zur Feldbreite aufgefüllt. - Eine vollst�ndige Liste der in \lstinline{printf()} zul�ssigen Formatspezifikationen + Eine vollständige Liste der in \lstinline{printf()} zulässigen Formatspezifikationen finden Sie in der Dokumentation des Compiler-Herstellers zu \lstinline{printf()}. - Von der Unix-Shell aus k�nnen Sie diese + Von der Unix-Shell aus können Sie diese mit dem Befehl \lstinline[style=cmd]{man 3 printf} abrufen. % -% Umgekehrt k�nnen Sie in C Integer-Konstanten +% Umgekehrt können Sie in C Integer-Konstanten % durch Voranstellen von \lstinline{0x} in hexadezimaler anstatt dezimaler Schreibweise eingeben. -% Die Hexadezimalzahl \lstinline{0x2a} steht in C f�r genau dieselbe Konstante +% Die Hexadezimalzahl \lstinline{0x2a} steht in C für genau dieselbe Konstante % wie die Dezimalzahl \lstinline{42}. \end{experts} @@ -532,7 +531,7 @@ Die Position des \lstinline{\n} ist relevant, z.\,B.\ geht \lstinline{printf ("\n42");} zuerst in eine neue Zeile und gibt danach den Text aus. - Auch mehrere \lstinline{\n} in derselben String-Konstanten sind zul�ssig. + Auch mehrere \lstinline{\n} in derselben String-Konstanten sind zulässig. \item C akzeptiert auch sehr seltsame Konstrukte. Das folgende Beispiel (Datei: \file{hello-5.c}) @@ -549,14 +548,14 @@ wird vom Compiler akzeptiert. (Warum das so ist, wird in Abschnitt \ref{Seiteneffekte} behandelt.) - Bei Verwendung der zus�tzlichen Option \lstinline[style=cmd]{-Wall} - erhalten wir zumindest eine Warnung �ber eine "`Anweisung ohne Effekt"': + Bei Verwendung der zusätzlichen Option \lstinline[style=cmd]{-Wall} + erhalten wir zumindest eine Warnung über eine "`Anweisung ohne Effekt"': \begin{lstlisting}[style=terminal,gobble=8] - $ �gcc -Wall hello-5.c -o hello-5� + $ ¡gcc -Wall hello-5.c -o hello-5¿ hello-5.c: In function 'main': hello-5.c:6: warning: statement with no effect \end{lstlisting} - Es empfiehlt sich, die Option \lstinline[style=cmd]{-Wall} grunds�tzlich zu verwenden + Es empfiehlt sich, die Option \lstinline[style=cmd]{-Wall} grundsätzlich zu verwenden und die Warnungen ernstzunehmen. \end{itemize} @@ -570,51 +569,51 @@ int main (void) { - printf ("Richtige Antworten w�ren %d oder %d oder sonstige.\n", 1, 2); + printf ("Richtige Antworten wären %d oder %d oder sonstige.\n", 1, 2); return 0; } \end{lstlisting} \begin{lstlisting}[style=terminal] - $ �gcc output-7.c -o output-7� - $ �./output-7� - Richtige Antworten w�ren 1 oder 2 oder sonstige. + $ ¡gcc output-7.c -o output-7¿ + $ ¡./output-7¿ + Richtige Antworten wären 1 oder 2 oder sonstige. $ \end{lstlisting} Achtung: Zu viele oder zu wenige Werte in der Parameterliste - ergeben trotzdem ein g�ltiges, wenn auch fehlerhaftes C-Programm + ergeben trotzdem ein gültiges, wenn auch fehlerhaftes C-Programm (Datei: \file{output-6.c}): \begin{lstlisting} #include <stdio.h> int main (void) { - printf ("Richtige Antworten w�ren %d", 1, " oder %d", 2, " oder sonstige.\n"); + printf ("Richtige Antworten wären %d", 1, " oder %d", 2, " oder sonstige.\n"); return 0; } \end{lstlisting} - Wenn man dieses Programm laufen l��t, + Wenn man dieses Programm laufen läßt, wird nicht etwa das zweite \lstinline{%d} durch den Zahlenwert 2 ersetzt. Vielmehr endet das, was ausgegeben wird, mit dem ersten \lstinline{%d}, - f�r das der Zahlenwert 1 eingesetzt wird, + für das der Zahlenwert 1 eingesetzt wird, und alles, was nach der 1 kommt, wird schlichtweg ignoriert. \begin{lstlisting}[style=terminal] - $ �gcc output-6.c -o output-6� - $ �./output-6� - Richtige Antworten w�ren 1$ + $ ¡gcc output-6.c -o output-6¿ + $ ¡./output-6¿ + Richtige Antworten wären 1$ \end{lstlisting} Bei Verwendung der Option \lstinline[style=cmd]{-Wall} erhalten wir auch hier eine Warnung: \begin{lstlisting}[style=terminal] - $ �gcc -Wall output-6.c -o output-6� + $ ¡gcc -Wall output-6.c -o output-6¿ output-6.c: In function 'main': output-6.c:5: warning: too many arguments for format \end{lstlisting} \subsection{Elementares Rechnen} - Der \newterm{bin�re Operator} \lstinline{+} kann in C (und den meisten Programmiersprachen) - dazu verwendet werden, zwei Integer-Ausdr�cke, die sogenannten \newterm{Operanden}, - durch Addition zu einem neuen Integer-Ausdruck zu verkn�pfen. + Der \newterm{binäre Operator} \lstinline{+} kann in C (und den meisten Programmiersprachen) + dazu verwendet werden, zwei Integer-Ausdrücke, die sogenannten \newterm{Operanden}, + durch Addition zu einem neuen Integer-Ausdruck zu verknüpfen. Beispiel: \file{mathe-1.c} \begin{lstlisting} @@ -626,17 +625,17 @@ return 0; } \end{lstlisting} - (Tats�chlich f�hrt bereits die erste Stufe des Compilers eine Optimierung durch, - die bewirkt, da� die ausf�hrbare Datei keine Additionsbefehle, - sondern direkt das Ergebnis der Addition enth�lt.) + (Tatsächlich führt bereits die erste Stufe des Compilers eine Optimierung durch, + die bewirkt, daß die ausführbare Datei keine Additionsbefehle, + sondern direkt das Ergebnis der Addition enthält.) - Die Operatoren f�r die Grundrechenarten lauten in C: + Die Operatoren für die Grundrechenarten lauten in C: \begin{center} \begin{tabular}{cl} \lstinline|+| & Addition \\ \lstinline|-| & Subtraktion \\ \lstinline|*| & Multiplikation \\ - \lstinline|/| & Division: Bei ganzen Zahlen wird grunds�tzlich abgerundet. \\ + \lstinline|/| & Division: Bei ganzen Zahlen wird grundsätzlich abgerundet. \\ \lstinline|%| & Modulo-Operation: Rest bei Division (\lstinline|39 % 4| ergibt \lstinline|3|.) \end{tabular} \end{center} @@ -655,7 +654,7 @@ \end{lstlisting} deklariert zwei Variable vom Typ Integer und initialisiert die zweite mit dem Wert 3. - F�r Flie�kommazahlen verwendet man meistens den Datentyp \lstinline{double}: + Für Fließkommazahlen verwendet man meistens den Datentyp \lstinline{double}: \begin{lstlisting}[belowskip=0pt] double x = 3.141592653589793; \end{lstlisting} @@ -663,18 +662,18 @@ \bigskip \begin{experts} - Die Bezeichnung \lstinline{double} steht f�r "`doppelt genau"'. - Daneben gibt es noch einen Datentyp \lstinline{float} f�r "`einfach genaue"' Flie�kommazahlen - sowie einen Datentyp \lstinline{long double} noch h�here Genauigkeiten. - Typischerweise folgen Flie�kommazahlen in C dem Standard IEEE 754. + Die Bezeichnung \lstinline{double} steht für "`doppelt genau"'. + Daneben gibt es noch einen Datentyp \lstinline{float} für "`einfach genaue"' Fließkommazahlen + sowie einen Datentyp \lstinline{long double} noch höhere Genauigkeiten. + Typischerweise folgen Fließkommazahlen in C dem Standard IEEE 754. In diesem Fall hat \lstinline{float} eine Genauigkeit von ca.\ 6 und \lstinline{double} eine Genauigkeit von ca.\ 15 Nachkommastellen. \end{experts} Das Einlesen von Werten erfolgt in C mit der Funktion \lstinline{scanf()}. - Das Beispielprogramm \file{input-1.c} liest einen Wert vom Standardeingabeger�t (hier: Tastatur) ein - und gibt das Doppelte des Wertes auf dem Standardausgabeger�t aus: + Das Beispielprogramm \file{input-1.c} liest einen Wert vom Standardeingabegerät (hier: Tastatur) ein + und gibt das Doppelte des Wertes auf dem Standardausgabegerät aus: \begin{lstlisting} #include <stdio.h> @@ -691,28 +690,28 @@ Damit \lstinline{scanf()} in die Variable \lstinline{a} einen Wert schreiben kann, ist es erforderlich, nicht den aktuellen Wert von \lstinline{a}, - sondern die Variable selbst an \lstinline{scanf()} zu �bergeben. + sondern die Variable selbst an \lstinline{scanf()} zu übergeben. Dies geschieht durch Voranstellen eines Und-Symbols \lstinline{&}. - (Genaugenommen handelt es sich um die �bergabe einer Speicheradresse. + (Genaugenommen handelt es sich um die Übergabe einer Speicheradresse. Dies wird in Abschnitt \ref{Zeiger} genauer behandelt.) Wenn wir das \lstinline{&} vergessen (Beispielprogramm: \file{input-3.c}), kann das C-Programm weiterhin compiliert werden. Bei Verwendung der Option \lstinline[style=cmd]{-Wall} erhalten wir eine Warnung. - Wenn wir das Programm ausf�hren und versuchen, einen Wert einzugeben, st�rzt das Programm ab. - (Hintergrund: Es betrachtet den aktuellen -- zuf�lligen -- Wert der Variablen \lstinline{a} + Wenn wir das Programm ausführen und versuchen, einen Wert einzugeben, stürzt das Programm ab. + (Hintergrund: Es betrachtet den aktuellen -- zufälligen -- Wert der Variablen \lstinline{a} als Adresse einer Speicherzelle, an der der eingelesene Wert gespeichert werden soll. - Das Programm greift also schreibend auf eine Speicherzelle au�erhalb des ihm zugeteilten Bereichs zu.) + Das Programm greift also schreibend auf eine Speicherzelle außerhalb des ihm zugeteilten Bereichs zu.) \breath - Zuweisungen an Variable erfolgen in C mit Hilfe des bin�ren Operators \lstinline{=}. - Es ist ausdr�cklich erlaubt, den "`alten"' Wert einer Variablen in Berechnungen zu verwenden, + Zuweisungen an Variable erfolgen in C mit Hilfe des binären Operators \lstinline{=}. + Es ist ausdrücklich erlaubt, den "`alten"' Wert einer Variablen in Berechnungen zu verwenden, deren Ergebnis man dann derselben Variablen zuweist. Die Zeile \lstinline{a = 2 * a} in Zeile 8 von \file{input-1.c} ist insbesondere keine mathematische Gleichung - (mit der L�sung 0 f�r die Unbekannte \lstinline{a}), + (mit der Lösung 0 für die Unbekannte \lstinline{a}), sondern die Berechnung des Doppelten des aktuellen Wertes der Variablen \lstinline{a}, welches dann wiederum in der Variablen \lstinline{a} gespeichert wird. @@ -721,25 +720,25 @@ \begin{experts} Die Funktion \lstinline{scanf()} kann, analog zu \lstinline{printf()}, gleichzeitig mehrere Werte abfragen. - Hierzu m�ssen wir im Format-String mehrere Formatspezifikationen angeben - und die Adressen mehrerer Variabler als Parameter �bergeben. + Hierzu müssen wir im Format-String mehrere Formatspezifikationen angeben + und die Adressen mehrerer Variabler als Parameter übergeben. - Genau wie bei \lstinline{printf()} werden �berz�hlige Parameter ignoriert, - und fehlende Parameter f�hren zu einem Absturz des Programms. + Genau wie bei \lstinline{printf()} werden überzählige Parameter ignoriert, + und fehlende Parameter führen zu einem Absturz des Programms. Zeichen zwischen den Formatspezifikationen fungieren als Trennzeichen. - Damit die Zahlen angenommen werden, mu� die Eingabe die Trennzeichen enthalten. + Damit die Zahlen angenommen werden, muß die Eingabe die Trennzeichen enthalten. - F�r doppelt genaue Flie�kommazahlen (\lstinline{double}) + Für doppelt genaue Fließkommazahlen (\lstinline{double}) lautet die Formatspezifikation \lstinline{%lf}; - f�r einfach genaue Flie�kommazahlen (\lstinline{float}) + für einfach genaue Fließkommazahlen (\lstinline{float}) lautet sie \lstinline{%f}. (Siehe die Beispielprogramme \file{input-6.c} bis \file{input-11.c}.) Weitere Informationen zu den Formatspezifikationen von \lstinline{scanf()} finden Sie in der Dokumentation zu \lstinline{scanf()}. - (In der Unix-Shell k�nnen Sie diese mit dem Befehl \lstinline[style=cmd]{man 3 scanf} abrufen.) + (In der Unix-Shell können Sie diese mit dem Befehl \lstinline[style=cmd]{man 3 scanf} abrufen.) \end{experts} \subsection{Verzweigungen} @@ -759,22 +758,22 @@ return 0; } \end{lstlisting} - hat den Nachteil, da� bei Eingabe von 0 f�r die zweite Zahl das Programm abst�rzt: + hat den Nachteil, daß bei Eingabe von 0 für die zweite Zahl das Programm abstürzt: \begin{lstlisting}[style=terminal] - $ �gcc -Wall if-0.c -o if-0� - $ �./if-0� - Bitte a eingeben: �13� - Bitte b eingeben: �0� + $ ¡gcc -Wall if-0.c -o if-0¿ + $ ¡./if-0¿ + Bitte a eingeben: ¡13¿ + Bitte b eingeben: ¡0¿ Floating point exception \end{lstlisting} Die Fehlermeldung stammt nicht vom Programm selbst, sondern vom Betriebssystem, das auf einen vom Prozessor signalisierten Fehlerzustand reagiert. ("`Floating point exception"' ist die Bezeichnung dieses Fehlerzustands. - In diesem Fall ist die Bezeichnung leicht irref�hrend, - da konkret dieser Fehler durch eine Division ganzer Zahlen ausgel�st wird.) + In diesem Fall ist die Bezeichnung leicht irreführend, + da konkret dieser Fehler durch eine Division ganzer Zahlen ausgelöst wird.) - F�r Programme wie dieses ist es notwendig, - in Abh�ngigkeit von den Benutzereingaben unterschiedliche Anweisungen auszuf�hren. + Für Programme wie dieses ist es notwendig, + in Abhängigkeit von den Benutzereingaben unterschiedliche Anweisungen auszuführen. Diese sog.\ \newterm{Verzweigung\/} geschieht mittels einer \lstinline{if}-Anweisung. \goodbreak @@ -796,20 +795,20 @@ \end{lstlisting} In den Klammern hinter dem \lstinline{if} steht ein Ausdruck, die sog.\ \newterm{Bedingung}. - Die auf das \lstinline{if} folgende Anweisung wird nur dann ausgef�hrt, + Die auf das \lstinline{if} folgende Anweisung wird nur dann ausgeführt, wenn die Bedingung \emph{ungleich Null\/} ist. (C kennt keinen eigenen "`Booleschen"' Datentyp. - Stattdessen steht \lstinline{0} f�r den Wahrheitswert "`falsch"' - und alles andere f�r den Wahrheitswert "`wahr"'.) + Stattdessen steht \lstinline{0} für den Wahrheitswert "`falsch"' + und alles andere für den Wahrheitswert "`wahr"'.) - Der bin�re Operator \lstinline{!=} pr�ft zwei Ausdr�cke auf Ungleichheit. - Er liefert \lstinline{0} zur�ck, wenn beide Operanden gleich sind, + Der binäre Operator \lstinline{!=} prüft zwei Ausdrücke auf Ungleichheit. + Er liefert \lstinline{0} zurück, wenn beide Operanden gleich sind, und \lstinline{1}, wenn sie ungleich sind. \breath Die \lstinline{if}-Anweisung kennt einen optionalen \lstinline{else}-Zweig. - Dieser wird dann ausgef�hrt, wenn die Bedingung \emph{nicht\/} erf�llt ist. + Dieser wird dann ausgeführt, wenn die Bedingung \emph{nicht\/} erfüllt ist. Beispielprogramm: \file{if-2.c} \begin{lstlisting} @@ -833,7 +832,7 @@ \breath Sowohl auf das \lstinline{if} als auch auf das \lstinline{else} - folgt nur jeweils \emph{eine\/} Anweisung, die von der Bedingung abh�ngt. + folgt nur jeweils \emph{eine\/} Anweisung, die von der Bedingung abhängt. In dem folgenden Beispielprogramm (Datei: \file{if-3.c}) \begin{lstlisting} @@ -854,20 +853,20 @@ return 0; } \end{lstlisting} - wird die Zeile \lstinline{printf ("Das tut man nicht.\n");} auch dann ausgef�hrt, + wird die Zeile \lstinline{printf ("Das tut man nicht.\n");} auch dann ausgeführt, wenn die Variable \lstinline{b} ungleich 0 ist. \breath - In C ist die Einr�ckung der Zeilen im Programmquelltext "`nur"' eine optische Hilfe f�r Programmierer. - Welche Anweisung von welcher Bedingung abh�ngt, + In C ist die Einrückung der Zeilen im Programmquelltext "`nur"' eine optische Hilfe für Programmierer. + Welche Anweisung von welcher Bedingung abhängt, entscheidet der Compiler allein anhand der Regeln der Programmiersprache, und diese besagen eindeutig: "`Sowohl auf das \lstinline{if} als auch auf das \lstinline{else} - folgt nur jeweils \emph{eine\/} Anweisung, die von der Bedingung abh�ngt."' + folgt nur jeweils \emph{eine\/} Anweisung, die von der Bedingung abhängt."' - Wenn wir m�chten, da� mehrere Anweisungen von der Bedingung abh�ngen, - m�ssen wir diese mittels geschweifter Klammern + Wenn wir möchten, daß mehrere Anweisungen von der Bedingung abhängen, + müssen wir diese mittels geschweifter Klammern zu einem sog.\ \newterm{Anweisungsblock\/} zusammenfassen. \goodbreak @@ -893,8 +892,8 @@ } \end{lstlisting} - Aus Sicht des Computers ist die Einr�ckung belanglos. - Die folgende Schreibweise (Datei: \file{if-4.c}) ist f�r ihn + Aus Sicht des Computers ist die Einrückung belanglos. + Die folgende Schreibweise (Datei: \file{if-4.c}) ist für ihn vollkommen gleichwertig zu \file{if-5.c}: \begin{lstlisting} #include <stdio.h> @@ -904,19 +903,19 @@ "a geteilt durch b ist: %d\n", a / b); else printf ("Bitte nicht durch 0 teilen!\n"); printf ("Das tut man nicht.\n"); return 0; } \end{lstlisting} - Aus Sicht eines Menschen hingegen kann eine \emph{korrekte\/} Einr�ckung des Quelltextes - \emph{sehr\/} hilfreich dabei sein, in einem Programm die �bersicht zu behalten. + Aus Sicht eines Menschen hingegen kann eine \emph{korrekte\/} Einrückung des Quelltextes + \emph{sehr\/} hilfreich dabei sein, in einem Programm die Übersicht zu behalten. Daher hier der dringende Rat: \begin{center} \bf - Achten Sie in Ihren Programmen auf korrekte und �bersichtliche Einr�ckung! + Achten Sie in Ihren Programmen auf korrekte und übersichtliche Einrückung! \end{center} \medskip \goodbreak - Um zwei Ausdr�cke auf Gleichheit zu pr�fen, - verwendet man in C den bin�ren Operator \lstinline{==}. + Um zwei Ausdrücke auf Gleichheit zu prüfen, + verwendet man in C den binären Operator \lstinline{==}. Die Anweisungen \begin{lstlisting}[belowskip=0pt] @@ -928,7 +927,7 @@ else printf ("Bitte nicht durch 0 teilen!\n"); \end{lstlisting} - sind also �quivalent zu: + sind also äquivalent zu: \begin{lstlisting} if (b == 0) printf ("Bitte nicht durch 0 teilen!\n"); @@ -949,15 +948,15 @@ printf ("%d, Rest %d \n", a / b, a % b); } \end{lstlisting} - (mit \lstinline{=} anstelle von \lstinline{==}) sind ebenfalls g�ltiges C, + (mit \lstinline{=} anstelle von \lstinline{==}) sind ebenfalls gültiges C, haben jedoch eine andere Bedeutung! \goodbreak Der Hintergrund ist der folgende: - Alle bin�ren Operatoren, sei es \lstinline{+} oder \lstinline{=} oder \lstinline{==}, + Alle binären Operatoren, sei es \lstinline{+} oder \lstinline{=} oder \lstinline{==}, sind in C vom Prinzip her gleichwertig. - Alle nehmen zwei numerische Operanden entgegen und liefern einen numerischen Wert zur�ck. - Wenn wir nun beispielsweise annehmen, da� die Variable \lstinline{a} den Wert 3 hat, dann gilt: + Alle nehmen zwei numerische Operanden entgegen und liefern einen numerischen Wert zurück. + Wenn wir nun beispielsweise annehmen, daß die Variable \lstinline{a} den Wert 3 hat, dann gilt: \begin{center} \begin{tabular}{cl} \lstinline|a + 7| & ergibt \lstinline|10|. \\ @@ -967,16 +966,16 @@ \end{center} Das o.\,a.\ Programmfragment bedeutet demnach: Weise der Variablen \lstinline{b} den Wert \lstinline{0} zu, - und f�hre anschlie�end \emph{immer\/} eine Division durch \lstinline{b} aus. - (Die \lstinline{if}-Bedingung bekommt den Wert \lstinline{0}, ist also niemals erf�llt.) + und führe anschließend \emph{immer\/} eine Division durch \lstinline{b} aus. + (Die \lstinline{if}-Bedingung bekommt den Wert \lstinline{0}, ist also niemals erfüllt.) \breath - Da� es sich bei Wahrheitswerten in C tats�chlich um Integer-Werte handelt, wird auch deutlich, - wenn man sich diese mittels \lstinline{printf()} ausgeben l��t. + Daß es sich bei Wahrheitswerten in C tatsächlich um Integer-Werte handelt, wird auch deutlich, + wenn man sich diese mittels \lstinline{printf()} ausgeben läßt. Wenn man beispielsweise in dem folgenden Programm \file{if-10.c} - den Wert \lstinline{7} f�r die Variable \lstinline{b} eingibt, + den Wert \lstinline{7} für die Variable \lstinline{b} eingibt, \begin{lstlisting} #include <stdio.h> @@ -995,24 +994,24 @@ lautet die Ausgabe: \goodbreak \begin{lstlisting}[style=terminal] - $ �./if-10� - Bitte b eingeben: �7� + $ ¡./if-10¿ + Bitte b eingeben: ¡7¿ Der Ausdruck b != 0 hat den Wert 1 Der Ausdruck b == 0 hat den Wert 0 Der Ausdruck b = 0 hat den Wert 0 \end{lstlisting} - In der ersten und zweiten Zeile wird gepr�ft, ob \lstinline{b} den Wert 0 hat, - und \lstinline{1} f�r "`ja"' bzw.\ \lstinline{0} f�r "`nein"' ausgegeben. + In der ersten und zweiten Zeile wird geprüft, ob \lstinline{b} den Wert 0 hat, + und \lstinline{1} für "`ja"' bzw.\ \lstinline{0} für "`nein"' ausgegeben. In der dritten Zeile wird \lstinline{b} der Wert \lstinline{0} zugewiesen - und anschlie�end der neue Wert von \lstinline{b} ausgegeben. + und anschließend der neue Wert von \lstinline{b} ausgegeben. \subsection{Schleifen} - Mit Hilfe der \lstinline{while}-Anweisung ist es m�glich, - Anweisungen in Abh�ngigkeit von einer Bedingung mehrfach auszuf�hren. + Mit Hilfe der \lstinline{while}-Anweisung ist es möglich, + Anweisungen in Abhängigkeit von einer Bedingung mehrfach auszuführen. Das folgende Beispielprogramm \file{loop-1.c} - schreibt die Zahlen von 1 bis einschlie�lich 10 auf den Bildschirm: + schreibt die Zahlen von 1 bis einschließlich 10 auf den Bildschirm: \begin{lstlisting} #include <stdio.h> @@ -1029,10 +1028,10 @@ } \end{lstlisting} Die Auswertung der Bedingung erfolgt analog zur \lstinline{if}-Anweisung. - Ebenso folgt auf \lstinline{while} nur eine eine einzige Anweisung, die wiederholt ausgef�hrt wird; - mehrere Anweisungen m�ssen mit geschweiften Klammern zu einem Anweisungsblock zusammengefa�t werden. + Ebenso folgt auf \lstinline{while} nur eine eine einzige Anweisung, die wiederholt ausgeführt wird; + mehrere Anweisungen müssen mit geschweiften Klammern zu einem Anweisungsblock zusammengefaßt werden. - Der bin�re Operator \lstinline{<=} liefert 1 zur�ck, + Der binäre Operator \lstinline{<=} liefert 1 zurück, wenn der linke Operand kleiner oder gleich dem rechten ist, ansonsten 0. Entsprechend sind die Operatoren \lstinline{>=}, \lstinline{<} und \lstinline{>} definiert. @@ -1057,15 +1056,15 @@ return 0; } \end{lstlisting} - Das endlos laufende Programm kann nur noch �ber das Betriebssystem beendet werden. + Das endlos laufende Programm kann nur noch über das Betriebssystem beendet werden. Von der Unix-Shell aus geschieht dies durch Eingabe von \lstinline[style=cmd]{Strg+C}. - In der Ausgabe des oben dargestellten Beispielprogramms f�llt auf, - da� die Zweierpotenzen zun�chst wie erwartet anwachsen, - sp�ter aber nur noch der Zahlenwert 0 ausgegeben wird: + In der Ausgabe des oben dargestellten Beispielprogramms fällt auf, + daß die Zweierpotenzen zunächst wie erwartet anwachsen, + später aber nur noch der Zahlenwert 0 ausgegeben wird: \begin{lstlisting}[style=terminal] - $ �gcc -Wall while-2.c -o while-2� - $ �./while-2� + $ ¡gcc -Wall while-2.c -o while-2¿ + $ ¡./while-2¿ 2 4 8 @@ -1103,26 +1102,26 @@ ... \end{lstlisting} \goodbreak - Dies h�ngt mit der Art und Weise zusammen, + Dies hängt mit der Art und Weise zusammen, wie Zahlen in einem Computer gespeichert werden. Im Detail ist dies Gegenstand der Vorlesung "`Rechnertechnik"'; - ein paar f�r uns wichtige Eckdaten seien an dieser Stelle erw�hnt: + ein paar für uns wichtige Eckdaten seien an dieser Stelle erwähnt: \begin{itemize} \item - Computer speichern Zahlen im Bin�rformat, das nur die Ziffern 0 und 1 kennt.\\ - Beispielsweise lautet die Dezimalzahl 9 in Bin�rdarstellung 1001. + Computer speichern Zahlen im Binärformat, das nur die Ziffern 0 und 1 kennt.\\ + Beispielsweise lautet die Dezimalzahl 9 in Binärdarstellung 1001. \item Zweierpotenzen entsprechen jeweils einer 1 mit folgenden Nullen.\\ - Die Dezimalzahlen 2, 4, 8 und 16 haben die Bin�rdarstellungen 10, 100, 1000 und 10000. + Die Dezimalzahlen 2, 4, 8 und 16 haben die Binärdarstellungen 10, 100, 1000 und 10000. \item - Auf einem 32-Bit-Prozessor zeigt die zweiundrei�igste Ziffer von rechts das Vorzeichen an. + Auf einem 32-Bit-Prozessor zeigt die zweiundreißigste Ziffer von rechts das Vorzeichen an. Steht hier eine 1, ist die Zahl negativ. - Dies erkl�rt, weshalb die Verdopplung von 1073741824 (bin�r: eine 1 mit 30 Nullen) - $-$2147483648 ergibt (bin�r: eine 1 mit 31 Nullen). + Dies erklärt, weshalb die Verdopplung von 1073741824 (binär: eine 1 mit 30 Nullen) + $-$2147483648 ergibt (binär: eine 1 mit 31 Nullen). \item - Bei einer weiteren Verdopplung w�rde bin�r eine 1 mit 32 Nullen entstehen, + Bei einer weiteren Verdopplung würde binär eine 1 mit 32 Nullen entstehen, die aber von einem 32-Bit-Prozessor nicht mehr dargestellt werden kann. - Ohne weitere Ma�nahmen ist daher das Doppelte von $-$2147483648 auf einem 32-Bit-Prozessor + Ohne weitere Maßnahmen ist daher das Doppelte von $-$2147483648 auf einem 32-Bit-Prozessor die Zahl 0. \end{itemize} @@ -1135,10 +1134,10 @@ \item Vor dem Betreten der Schleife findet eine Initialisierung statt, z.\,B.\ \lstinline{i = 1}. \item - Am Ende jedes Schleifendurchlaufs wird eine "`Schritt-Anweisung"' durchgef�hrt, + Am Ende jedes Schleifendurchlaufs wird eine "`Schritt-Anweisung"' durchgeführt, z.\,B.\ \lstinline{i = i + 1}. \end{itemize} - F�r dieses spezielle \lstinline{while} kennt C die Abk�rzung \lstinline{for}: + Für dieses spezielle \lstinline{while} kennt C die Abkürzung \lstinline{for}: \begin{center} \begin{minipage}{4cm} \begin{lstlisting}[gobble=8] @@ -1178,8 +1177,8 @@ while (i <= 10) \end{lstlisting} Der Unterschied zur "`normalen"' \lstinline{while}-Schleife besteht darin, - da� eine \lstinline{do}-\lstinline{while}-Schleife mindestens einmal ausgef�hrt wird, - weil die Bedingung nicht bereits am Anfang, sondern erst am Ende des Schleifendurchlaufs gepr�ft wird. + daß eine \lstinline{do}-\lstinline{while}-Schleife mindestens einmal ausgeführt wird, + weil die Bedingung nicht bereits am Anfang, sondern erst am Ende des Schleifendurchlaufs geprüft wird. \bigbreak @@ -1191,9 +1190,9 @@ printf ("%d\n", i); \end{lstlisting} \vspace{-\smallskipamount} - zwar zul�ssiges C, aber nicht sinnvoll (Datei: \file{loop-4.c}). + zwar zulässiges C, aber nicht sinnvoll (Datei: \file{loop-4.c}). Dies kann man sofort erkennen, indem man die \lstinline{for}-Schleife - in eine \lstinline{while}-Schleife �bersetzt: + in eine \lstinline{while}-Schleife übersetzt: \begin{lstlisting} i = 1; while (10) @@ -1207,11 +1206,11 @@ (Die \lstinline{while}-Bedingung \lstinline{10} ist ungleich Null, hat also stets den Wahrheitswert "`wahr"'.) Am Ende jedes Schleifendurchlaufs wird \lstinline{i + 1} berechnet; der berechnete Wert wird jedoch nirgendwo verwendet, sondern schlichtweg verworfen. - Insbesondere �ndert \lstinline{i} seinen Wert nicht. + Insbesondere ändert \lstinline{i} seinen Wert nicht. \subsection{Seiteneffekte\label{Seiteneffekte}} - Das Verwerfen berechneter Werte verdient eine n�here Betrachtung + Das Verwerfen berechneter Werte verdient eine nähere Betrachtung -- insbesondere in der Programmiersprache C. Wie das Beispielprogramm \file{statements-1.c} illustriert, \begin{lstlisting} @@ -1223,26 +1222,26 @@ return 0; } \end{lstlisting} - ist es anscheinend zul�ssig, Werte als Anweisung zu verwenden. + ist es anscheinend zulässig, Werte als Anweisung zu verwenden. - Grunds�tzlich gilt in C: - Man kann jeden g�ltigen Ausdruck als Anweisung verwenden. + Grundsätzlich gilt in C: + Man kann jeden gültigen Ausdruck als Anweisung verwenden. Der Wert des Ausdrucks wird dabei ignoriert. - Die Bedeutung der (g�ltigen!) C-Anweisung \lstinline{2 + 2;} lautet somit: - "`Berechne den Wert \lstinline{2 + 2} und vergi� ihn wieder."' + Die Bedeutung der (gültigen!) C-Anweisung \lstinline{2 + 2;} lautet somit: + "`Berechne den Wert \lstinline{2 + 2} und vergiß ihn wieder."' - Tats�chlich gilt dasselbe auch f�r \lstinline{printf()}: - Die Funktion \lstinline{printf()} liefert eine ganze Zahl zur�ck. + Tatsächlich gilt dasselbe auch für \lstinline{printf()}: + Die Funktion \lstinline{printf()} liefert eine ganze Zahl zurück. Der \lstinline{printf()}-Aufruf ist somit ein Ausdruck, dessen Wert ignoriert wird. "`Nebenbei"' hat \lstinline{printf()} aber noch eine weitere Bedeutung, - n�mlich die Ausgabe des Textes auf dem Standardausgabeger�t (Bildschirm). - Diese weitere Bedeutung hei�t \newterm{Seiteneffekt\/} des Ausdrucks. + nämlich die Ausgabe des Textes auf dem Standardausgabegerät (Bildschirm). + Diese weitere Bedeutung heißt \newterm{Seiteneffekt\/} des Ausdrucks. Das Beispielprogramm \file{statements-3.c} - gibt den vom ersten \lstinline{printf()} zur�ckgegebenen Wert + gibt den vom ersten \lstinline{printf()} zurückgegebenen Wert mit Hilfe eines zweiten \lstinline{printf()} aus: \begin{lstlisting} #include <stdio.h> @@ -1260,71 +1259,71 @@ 4 2 \end{lstlisting} - Bei dem von \lstinline{printf()} zur�ckgegebenen Wert handelt es sich um die Anzahl der geschriebenen Zeichen. - In diesem Fall ist sind es zwei Zeichen, n�mlich die Ziffer \lstinline{4} + Bei dem von \lstinline{printf()} zurückgegebenen Wert handelt es sich um die Anzahl der geschriebenen Zeichen. + In diesem Fall ist sind es zwei Zeichen, nämlich die Ziffer \lstinline{4} sowie das Zeilenendesymbol, im Programm als \lstinline{\n} notiert. \breath - Auch Operatoren k�nnen in C Seiteneffekte haben. + Auch Operatoren können in C Seiteneffekte haben. \begin{itemize} \item - Der bin�re Operator \lstinline{=} (Zuweisung) + Der binäre Operator \lstinline{=} (Zuweisung) hat als Seiteneffekt die Zuweisung des zweiten Operanden an den ersten Operanden - und als R�ckgabewert den zugewiesenen Wert. + und als Rückgabewert den zugewiesenen Wert. (Siehe das Beispielprogramm \file{side-effects-5.c}.) \item - �hnlich funktionieren die bin�ren Operatoren \lstinline{+= -= *= /* %=}. + Ähnlich funktionieren die binären Operatoren \lstinline{+= -= *= /* %=}. Sie wenden die vor dem \lstinline{=} stehende Rechenoperation auf die beiden Operatoren an, weisen als Seiteneffekt das Ergebnis dem ersten Operanden zu - und geben das Rechenergebnis als Wert zur�ck. + und geben das Rechenergebnis als Wert zurück. \item - Die bin�ren Rechnoperatoren \lstinline{+ - * / %} + Die binären Rechnoperatoren \lstinline{+ - * / %} und Vergleichsoperatoren \lstinline{== != < > <= >=} haben \emph{keinen\/} Seiteneffekt. \item - Der un�re Rechenoperator \lstinline{-} (arithmetische Negation, Vorzeichen) + Der unäre Rechenoperator \lstinline{-} (arithmetische Negation, Vorzeichen) hat ebenfalls \emph{keinen\/} Seiteneffekt. \item - Ein weiterer un�rer Operator \emph{ohne\/} Seiteneffekt ist die logische Negation,\\ - in C ausgedr�ckt durch ein Ausrufezeichen: \lstinline{!}\\ + Ein weiterer unärer Operator \emph{ohne\/} Seiteneffekt ist die logische Negation,\\ + in C ausgedrückt durch ein Ausrufezeichen: \lstinline{!}\\ \lstinline{!a} ist 1, wenn \lstinline{a} den Wert 0 hat; ansonsten ist es 0.\\ \lstinline{!(a < b)} ist demzufolge dasselbe wie \lstinline{a >= b}. \item - Der Funktionsaufruf \lstinline{()} (Klammerpaar) ist in C ebenfalls ein un�rer Operator. - Er liefert einen Wert zur�ck (R�ckgabewert der Funktion) + Der Funktionsaufruf \lstinline{()} (Klammerpaar) ist in C ebenfalls ein unärer Operator. + Er liefert einen Wert zurück (Rückgabewert der Funktion) und hat einen Seiteneffekt (Aufruf der Funktion). \item - Die un�ren Operatoren \lstinline{++} und \lstinline{--} haben den Seiteneffekt, - da� sie die Variable, vor oder hinter der sie stehen, um 1 erh�hen (\lstinline{++}) + Die unären Operatoren \lstinline{++} und \lstinline{--} haben den Seiteneffekt, + daß sie die Variable, vor oder hinter der sie stehen, um 1 erhöhen (\lstinline{++}) bzw.\ vermindern (\lstinline{--}). Wenn der Operator \emph{vor\/} der Variablen steht (\lstinline{++a}), - ist der R�ckgabewert der um 1 erh�hte/verminderte Wert der Variablen. + ist der Rückgabewert der um 1 erhöhte/verminderte Wert der Variablen. Wenn er hingegen \emph{hinter\/} der Variablen steht (\lstinline{a++}), - ist der R�ckgabewert der urspr�ngliche Wert der Variablen; - das Erh�hen/Vermindern findet in diesem Fall erst danach statt. + ist der Rückgabewert der ursprüngliche Wert der Variablen; + das Erhöhen/Vermindern findet in diesem Fall erst danach statt. (Siehe die Beispielprogramme \file{side-effects-1.c} bis \file{side-effects-5.c}.) \begin{experts} Da die Reihenfolge, in der ein Ausdruck ausgewertet wird, nicht immer festliegt, - sollte man darauf achten, da� die Seiteneffekte eines Ausdruck dessen Wert nicht beeinflussen. + sollte man darauf achten, daß die Seiteneffekte eines Ausdruck dessen Wert nicht beeinflussen. (Siehe die Beispielprogramme \file{side-effects-10.c} und \file{side-effects-11.c}. - \lstinline[style=cmd]{gcc} warnt in derartigen F�llen.) + \lstinline[style=cmd]{gcc} warnt in derartigen Fällen.) \end{experts} \begin{experts} \item - Ein weiterer bin�rer Operator \emph{ohne\/} Seiteneffekt ist das Komma. + Ein weiterer binärer Operator \emph{ohne\/} Seiteneffekt ist das Komma. Der Ausdruck \lstinline{a, b} bedeutet: - "`Berechne \lstinline{a}, vergi� es wieder, und gib stattdessen \lstinline{b} zur�ck."' + "`Berechne \lstinline{a}, vergiß es wieder, und gib stattdessen \lstinline{b} zurück."' Dies ist nur dann sinnvoll, wenn der Ausdruck \lstinline{a} einen Seiteneffekt hat. \end{experts} \end{itemize} - Die folgenden vier Programmfragmente sind verschiedene Schreibweisen f�r genau denselben Code. + Die folgenden vier Programmfragmente sind verschiedene Schreibweisen für genau denselben Code. \begin{lstlisting} int i; @@ -1345,12 +1344,12 @@ for (i = 0; i < 10; printf ("%d\n", i++)); \end{lstlisting} Sie bewirken nicht nur dasselbe (Ausgabe der Zahlen von 0 bis 9), - sondern stehen tats�chlich f�r \emph{genau dasselbe Programm}. + sondern stehen tatsächlich für \emph{genau dasselbe Programm}. Sie laufen genau gleich schnell und unterscheiden sich nur hinsichtlich ihrer Lesbarkeit, - wobei es vom pers�nlichen Geschmack abh�ngt, welche Variante man jeweils als lesbarer empfindet. + wobei es vom persönlichen Geschmack abhängt, welche Variante man jeweils als lesbarer empfindet. \begin{center} \bf - Schreiben Sie Ihre Programme stets so lesbar wie m�glich.\\ + Schreiben Sie Ihre Programme stets so lesbar wie möglich.\\ Platzsparende Schreibweise macht ein Programm nicht schneller. \end{center} @@ -1358,18 +1357,18 @@ Bei den bisher vorgestellten Verzweigungen und Schleifen ist die Reihenfolge, in der die Befehle abgearbeitet werden, klar erkennbar. - Dar�berhinaus kennt C auch Anweisungen, + Darüberhinaus kennt C auch Anweisungen, die einen Sprung des Programms bewirken, der diese Struktur durchbricht: \begin{itemize} \item Mit der \lstinline{break}-Anweisung kann das Programm - die n�chst"-�u�ere \lstinline{while}- oder \lstinline{for}-Schleife + die nächst"-äußere \lstinline{while}- oder \lstinline{for}-Schleife unmittelbar verlassen. - Das folgende Beispielprogramm z�hlt von 0 bis 9, + Das folgende Beispielprogramm zählt von 0 bis 9, indem es eine Endlosschleife beim Erreichen von 10 mittels \lstinline{break} unterbricht. - Der Schleifenz�her \lstinline{i} wird innerhalb des \lstinline{printf()} + Der Schleifenzäher \lstinline{i} wird innerhalb des \lstinline{printf()} "`nebenbei"' inkrementiert. \begin{lstlisting}[gobble=8] int i = 0; @@ -1380,16 +1379,16 @@ printf ("%d\n", i++); } \end{lstlisting} - Eine �bersichtlichere Schreibweise derselben Schleife lautet: + Eine übersichtlichere Schreibweise derselben Schleife lautet: \begin{lstlisting}[gobble=8] int i; for (i = 0; i < 10; i++) printf ("%d\n", i++); \end{lstlisting} - (Der erzeugte Code ist in beiden F�llen genau derselbe.) + (Der erzeugte Code ist in beiden Fällen genau derselbe.) \item Mit der \lstinline{continue}-Anweisung springt ein Programm - unmittelbar in den n�chsten Durchlauf der n�chst"-�u�eren Schleife. + unmittelbar in den nächsten Durchlauf der nächst"-äußeren Schleife. \item Mit der \lstinline{return}-Anweisung kann man eine Funktion (siehe Abschnitt~\ref{Funktionen}) ohne Umweg direkt verlassen. @@ -1409,28 +1408,28 @@ \end{itemize} Ein Programmquelltext sollte immer so gestaltet werden, - da� er den Ablauf des Programms unmittelbar ersichtlich macht. + daß er den Ablauf des Programms unmittelbar ersichtlich macht. Ein vorzeitiges \lstinline{return} stellt einen "`Hinterausgang"' einer Funktion dar und sollte mit Bedacht eingesetzt werden. - �hnliches gilt in noch st�rkerem Ma�e f�r \lstinline{break} und \lstinline{continue} - als "`Hinterausg�nge"' von Schleifen. - Diese sind sicherlich bequeme M�glichkeiten, zus�tzliche \lstinline{if}s - und zus�tzliche Wahrheitswert-Variable zu vermeiden, + Ähnliches gilt in noch stärkerem Maße für \lstinline{break} und \lstinline{continue} + als "`Hinterausgänge"' von Schleifen. + Diese sind sicherlich bequeme Möglichkeiten, zusätzliche \lstinline{if}s + und zusätzliche Wahrheitswert-Variable zu vermeiden, verschleiern aber langfristig den Ablauf der Befehle. - In besonderem Ma�e gilt dies f�r die \lstinline{goto}-Anweisung. + In besonderem Maße gilt dies für die \lstinline{goto}-Anweisung. Hier ist nicht erkennbar, ob der Sprung nach oben geht (Schleife) oder nach unten (Verzweigung). - Verschachtelungen von Bl�cken und \lstinline{goto}-Spr�ngen - bereiten dem Compiler zus�tzliche Arbeit und stehen somit der Optimierung entgegen. - (Es stimmt insbesondere nicht, da� Konstruktionen mit \lstinline{goto} - schneller abgearbeitet w�rden als Konstruktionen mit \lstinline{if} und \lstinline{while}.) + Verschachtelungen von Blöcken und \lstinline{goto}-Sprüngen + bereiten dem Compiler zusätzliche Arbeit und stehen somit der Optimierung entgegen. + (Es stimmt insbesondere nicht, daß Konstruktionen mit \lstinline{goto} + schneller abgearbeitet würden als Konstruktionen mit \lstinline{if} und \lstinline{while}.) Es ist daher besser, \lstinline{goto} nicht zu verwenden und stattdessen den Programmablauf mit Hilfe von Verzweigungen und Schleifen zu strukturieren. (Siehe auch: \url{http://xkcd.org/292/}) - Zusammengefa�t: + Zusammengefaßt: \begin{center} \bf Verwenden Sie vorzeitiges \lstinline{return} mit Bedacht. @@ -1467,33 +1466,33 @@ } \end{lstlisting} (Das Wort "`foo"' ist eine sog.\ \newterm{metasyntaktische Variable} -- - ein Wort, das absichtlich nichts bedeutet und f�r einen beliebig austauschbaren Namen steht.) + ein Wort, das absichtlich nichts bedeutet und für einen beliebig austauschbaren Namen steht.) Mit dem Funktionsaufruf \lstinline{foo (3, 7)} stellt das Hauptprogramm der Funktion \lstinline{foo()} - die Parameterwerte 3 f�r \lstinline{a} und 7 f�r \lstinline{b} zur Verf�gung. + die Parameterwerte 3 für \lstinline{a} und 7 für \lstinline{b} zur Verfügung. - Der R�ckgabewert der Funktion \lstinline{foo()} ist vom Typ \lstinline{void}. - Im Gegensatz zu Datentypen wie z.\,B.\ \lstinline{int}, das f�r ganze Zahlen steht, - steht \lstinline{void} f�r "`nichts"'. + Der Rückgabewert der Funktion \lstinline{foo()} ist vom Typ \lstinline{void}. + Im Gegensatz zu Datentypen wie z.\,B.\ \lstinline{int}, das für ganze Zahlen steht, + steht \lstinline{void} für "`nichts"'. - Von Ausdr�cken zur�ckgegebene \lstinline{void}-Werte \emph{m�ssen\/} ignoriert werden. - (Von Ausdr�cken zur�ckgegebene Werte anderer Typen \emph{d�rfen\/} ignoriert werden.) + Von Ausdrücken zurückgegebene \lstinline{void}-Werte \emph{müssen\/} ignoriert werden. + (Von Ausdrücken zurückgegebene Werte anderer Typen \emph{dürfen\/} ignoriert werden.) \breath Das Hauptprogramm ist in C eine ganz normale Funktion. - Dadurch, da� sie den Namen \lstinline{main} hat, - wei� das Betriebssystem, da� es sie bei Programmbeginn aufrufen soll. + Dadurch, daß sie den Namen \lstinline{main} hat, + weiß das Betriebssystem, daß es sie bei Programmbeginn aufrufen soll. \lstinline{main()} kann dann seinerseits weitere Funktionen aufrufen. - �ber seinen R�ckgabewert (vom Typ \lstinline{int}) teilt \lstinline{main()} dem Betriebssystem mit, + Über seinen Rückgabewert (vom Typ \lstinline{int}) teilt \lstinline{main()} dem Betriebssystem mit, ob das Programm erfolgreich beendet werden konnte. - Der R�ckgabewert 0 steht f�r "`Erfolg"'; andere Werte stehen f�r verschiedenartige Fehler. + Der Rückgabewert 0 steht für "`Erfolg"'; andere Werte stehen für verschiedenartige Fehler. \breath Je nachdem, wo und wie Variable deklariert werden, - sind sie von verschiedenen Stellen im Programm aus zug�nglich + sind sie von verschiedenen Stellen im Programm aus zugänglich und/oder verhalten sich unterschiedlich. Beispielprogramm: \file{functions-2.c} @@ -1533,24 +1532,24 @@ foo(): a = 6, b = 7 main(): a = 12, b = 13 \end{lstlisting} - Erkl�rung: + Erklärung: \begin{itemize} \item Der erste Aufruf der Funktion \lstinline{printf()} in Zeile 17 des Programms gibt die Werte der in Zeile 3 deklarierten Variablen aus. - Diese lauten 0 f�r \lstinline{a} und 3 f�r \lstinline{b}. + Diese lauten 0 für \lstinline{a} und 3 für \lstinline{b}. Weil es sich um sog.\ \newterm{globale Variable\/} handelt - (Die Deklaration steht au�erhalb jeder Funktion.), + (Die Deklaration steht außerhalb jeder Funktion.), werden diese Variablen \emph{bei Programmbeginn\/} initialisiert. - F�r \lstinline{b} steht der Wert 3 f�r die Initialisierung innerhalb der Deklaration; - f�r \lstinline{a} gilt der implizite Wert 0. + Für \lstinline{b} steht der Wert 3 für die Initialisierung innerhalb der Deklaration; + für \lstinline{a} gilt der implizite Wert 0. \item - Der zweite Aufruf von \lstinline{printf()} erfolgt indirekt �ber die Funktion \lstinline{foo()}, + Der zweite Aufruf von \lstinline{printf()} erfolgt indirekt über die Funktion \lstinline{foo()}, die ihrerseits vom Hauptprogramm aus aufgerufen wurde (Zeile 18). - Oberhalb des \lstinline{printf()} (Zeile 10) befinden sich neue Deklarationen f�r Variable, - die ebenfalls \lstinline{a} (Zeile 8) und \lstinline{b} hei�en (Zeile 9). + Oberhalb des \lstinline{printf()} (Zeile 10) befinden sich neue Deklarationen für Variable, + die ebenfalls \lstinline{a} (Zeile 8) und \lstinline{b} heißen (Zeile 9). Diese sog.\ \newterm{lokalen Variablen\/} werden auf neue Werte initialisiert, die korrekt ausgegeben werden. @@ -1562,24 +1561,24 @@ \lstinline{a} hat immer noch den Wert 0, weil durch das \lstinline{a++} in Zeile 11 eine andere Variable inkrementiert wurde, - die ebenfalls \lstinline{a} hei�t, n�mlich die lokale Variable, die in Zeile 8 deklariert wurde. + die ebenfalls \lstinline{a} heißt, nämlich die lokale Variable, die in Zeile 8 deklariert wurde. - Dasselbe gilt f�r \lstinline{b} hinsichtlich der Zeile 12. + Dasselbe gilt für \lstinline{b} hinsichtlich der Zeile 12. In Zeile 7 jedoch greift die Funktion \lstinline{foo()} auf die in Zeile 3 deklarierte globale Variable \lstinline{b} zu, - die dadurch den Wert 4 (statt vorher: 3) erh�lt. + die dadurch den Wert 4 (statt vorher: 3) erhält. \item In Zeile 20 weist das Hauptprogramm beiden in Zeile 3 deklarierten Variablen den Wert 12 zu. Genauer: Es weist der Variablen \lstinline{a} den Wert \lstinline{b = 12} zu. Bei \lstinline{b = 12} handelt es sich um einen Ausdruck mit Seiteneffekt, - n�mlich die Zuweisung des Wertes 12 an die Variable \lstinline{b}. + nämlich die Zuweisung des Wertes 12 an die Variable \lstinline{b}. Der Wert des Zuweisungsausdrucks ist ebenfalls 12. \item Der vierte Aufruf von \lstinline{printf()} erfolgt wieder direkt durch das Hauptprogramm (Zeile 21) - und gibt erwartungsgem�� zweimal den Wert 12 aus. + und gibt erwartungsgemäß zweimal den Wert 12 aus. \item - Der f�nfte Aufruf von \lstinline{printf()} erfolgt wieder indirekt �ber die Funktion \lstinline{foo()}, + Der fünfte Aufruf von \lstinline{printf()} erfolgt wieder indirekt über die Funktion \lstinline{foo()}, die ihrerseits vom Hauptprogramm aus aufgerufen wurde (Zeile 22). Die Funktion \lstinline{foo()} gibt wiederum die Werte @@ -1592,45 +1591,45 @@ Die Variable \lstinline{a} (Zeile 8) ist hingegen als \newterm{statisch\/} (engl.\ \lstinline{static}) deklariert. - Sie beh�lt ihren Wert zwischen zwei Aufrufen von \lstinline{foo()}, + Sie behält ihren Wert zwischen zwei Aufrufen von \lstinline{foo()}, wird nur zu Programmbeginn initialisiert - und ist von au�erhalb der Funktion nicht ver�nderbar. + und ist von außerhalb der Funktion nicht veränderbar. \begin{experts} Ausnahme: Wenn einer anderen Funktion die Adresse der \lstinline{static}-Variablen bekannt ist, - kann diese die Variable �ber einen Zeiger ver�ndern. + kann diese die Variable über einen Zeiger verändern. Siehe Abschnitt~\ref{Zeiger} sowie das Beispielprogramm \file{variable-22.c}. \end{experts} - Da der Anfangswert 5 der Variablen \lstinline{a} bereits einmal erh�ht wurde (Zeile 11), + Da der Anfangswert 5 der Variablen \lstinline{a} bereits einmal erhöht wurde (Zeile 11), wird der Wert 6 ausgegeben. (Die Zuweisung des Wertes 12 im Hauptprogramm bezog sich auf ein anderes \lstinline{a}, - n�mlich das in Zeile 3 deklarierte.) + nämlich das in Zeile 3 deklarierte.) \item Der letzte Aufruf von \lstinline{printf()} erfolgt wieder direkt durch das Hauptprogramm (Zeile 23). \lstinline{a} hat immer noch den Wert 12, weil durch das \lstinline{a++} in Zeile 11 eine andere Variable inkrementiert wurde, - die ebenfalls \lstinline{a} hei�t, n�mlich die, die in Zeile 8 deklariert wurde. + die ebenfalls \lstinline{a} heißt, nämlich die, die in Zeile 8 deklariert wurde. - Dasselbe gilt f�r \lstinline{b} hinsichtlich der Zeile 12. + Dasselbe gilt für \lstinline{b} hinsichtlich der Zeile 12. In Zeile 7 jedoch greift die Funktion \lstinline{foo()} auf die in Zeile 3 deklarierte Variable \lstinline{b} zu, - die dadurch den Wert 13 (statt vorher: 12) erh�lt. + die dadurch den Wert 13 (statt vorher: 12) erhält. \end{itemize} \subsection{Zeiger\label{Zeiger}} - In C k�nnen an Funktionen grunds�tzlich nur Werte �bergeben werden. - Vom Funktionsr�ckgabewert abgesehen, hat eine C-Funktion keine M�glichkeit, - dem Aufrufer Werte zur�ckzugeben (siehe Beispielprogramm \file{pointers-0.c}). + In C können an Funktionen grundsätzlich nur Werte übergeben werden. + Vom Funktionsrückgabewert abgesehen, hat eine C-Funktion keine Möglichkeit, + dem Aufrufer Werte zurückzugeben (siehe Beispielprogramm \file{pointers-0.c}). - Es ist dennoch m�glich, eine C-Funktion aufzurufen, + Es ist dennoch möglich, eine C-Funktion aufzurufen, um eine Variable (oder mehrere) auf einen Wert zu setzen. - Hierf�r �bergibt man der Funktion die \newterm{Speicheradresse\/} der Variablen als Wert. + Hierfür übergibt man der Funktion die \newterm{Speicheradresse\/} der Variablen als Wert. Der Wert ist ein \newterm{Zeiger\/} auf die Variable. - Wenn einem Zeiger der un�re Operator \lstinline{*} vorangestellt wird, + Wenn einem Zeiger der unäre Operator \lstinline{*} vorangestellt wird, ist der resultierende Ausdruck diejenige Variable, auf die der Zeiger zeigt. In Deklarationen wird dasselbe Symbol dem Namen vorangestellt, um anstelle einer Variablen des genannten Typs @@ -1638,7 +1637,7 @@ (Das \lstinline{*}-Symbol wirkt jeweils nur auf den unmittelbar folgenden Bezeichner -- siehe die Beispielprogramme \file{test-1.c} und \file{test-2.c}.) - Umgekehrt wird der un�re Operator \lstinline{&} einer Variablen vorangestellt, + Umgekehrt wird der unäre Operator \lstinline{&} einer Variablen vorangestellt, um einen Ausdruck vom Typ "`Zeiger auf Variable dieses Typs"' mit dem Wert "`Speicheradresse dieser Variablen"' zu erhalten. @@ -1660,35 +1659,35 @@ return 0; } \end{lstlisting} - Die Funktion \lstinline{calc_answer()} l��t sich vom Hauptprogramm einen Zeiger \lstinline{a} - auf die lokale Variable \lstinline{answer} des Hauptprogramms �bergeben. + Die Funktion \lstinline{calc_answer()} läßt sich vom Hauptprogramm einen Zeiger \lstinline{a} + auf die lokale Variable \lstinline{answer} des Hauptprogramms übergeben. (Aus Sicht des Hauptprogramms ist dieser Zeiger die Adresse \lstinline{&answer} der lokalen Variablen \lstinline{answer}.) Sie schreibt einen Wert in die Variable \lstinline{*a}, auf die der Zeiger \lstinline{a} zeigt. - Das Hauptprogramm kann diesen Wert anschlie�end seiner Variablen \lstinline{answer} entnehmen + Das Hauptprogramm kann diesen Wert anschließend seiner Variablen \lstinline{answer} entnehmen und mit \lstinline{printf()} ausgeben. - Vergi�t man beim Aufruf den Adre�operator \lstinline{&}, - �bergibt man den aktuellen Wert der Variablen (hier: eine Zahl) - anstelle eines Zeigers (und erh�lt eine Warnung durch den Compiler). + Vergißt man beim Aufruf den Adreßoperator \lstinline{&}, + übergibt man den aktuellen Wert der Variablen (hier: eine Zahl) + anstelle eines Zeigers (und erhält eine Warnung durch den Compiler). Dieser Wert wird als eine Speicheradresse interpretiert. - Diese befindet sich in der Regel au�erhalb des Bereichs, + Diese befindet sich in der Regel außerhalb des Bereichs, den das Betriebssystem dem Programm zugewiesen hat. Ein Versuch der Funktion, auf diese Speicheradresse zuzugreifen, - f�hrt dann zum Absturz des Programms + führt dann zum Absturz des Programms (Speicherschutzverletzung -- siehe Beispielprogramm \file{pointers-2.c}). \subsection{Arrays und Strings\label{Strings}} \subsubsection{Arrays} - In C ist es m�glich, mit einem Zeiger Arithmetik zu betreiben, - so da� er nicht mehr auf die urspr�ngliche Variable zeigt, + In C ist es möglich, mit einem Zeiger Arithmetik zu betreiben, + so daß er nicht mehr auf die ursprüngliche Variable zeigt, sondern auf ihren Nachbarn im Speicher. Solche Nachbarn gibt es dann, wenn mehrere Variable gleichen Typs gemeinsam angelegt werden. - Eine derartige Ansammlung von Variablen gleichen Typs hei�t \newterm{Array\/} (Feldvariable, Vektor). + Eine derartige Ansammlung von Variablen gleichen Typs heißt \newterm{Array\/} (Feldvariable, Vektor). Beispielprogramm: \file{arrays-4.c} \begin{lstlisting} @@ -1704,7 +1703,7 @@ } \end{lstlisting} - Die initialisierte Variable \lstinline{prime} ist ein Array von f�nf ganzen Zahlen. + Die initialisierte Variable \lstinline{prime} ist ein Array von fünf ganzen Zahlen. Der Bezeichner \lstinline{prime} des Arrays wird als Zeiger auf eine \lstinline{int}-Variable verwendet. In diesem Sinne sind Arrays und Zeiger in C dasselbe. @@ -1712,15 +1711,15 @@ Durch Dereferenzieren \lstinline{*(p + i)} erhalten wir den \lstinline{i}-ten Nachbarn von \lstinline{*p} selbst. - Da diese Kombination -- Zeigerarithmetik mit anschlie�endem Dereferenzieren -- - sehr h�ufig auftritt, stellt C f�r die Konstruktion \lstinline{*(p + i)} - die Abk�rzung \lstinline{p[i]} zur Verf�gung + Da diese Kombination -- Zeigerarithmetik mit anschließendem Dereferenzieren -- + sehr häufig auftritt, stellt C für die Konstruktion \lstinline{*(p + i)} + die Abkürzung \lstinline{p[i]} zur Verfügung (siehe Beispielprogramm \file{arrays-5.c}). Die von anderen Sprachen her bekannte Schreibweise \lstinline{p[i]} - f�r das \lstinline{i}-te Element eines Arrays \lstinline{p} - ist also in C lediglich eine Abk�rzung f�r \lstinline{*(p + i)}, - wobei man \lstinline{p} gleicherma�en als Array wie als Zeiger auffassen kann. + für das \lstinline{i}-te Element eines Arrays \lstinline{p} + ist also in C lediglich eine Abkürzung für \lstinline{*(p + i)}, + wobei man \lstinline{p} gleichermaßen als Array wie als Zeiger auffassen kann. Wenn wir uns dieser Schreibweise bedienen und anstelle des Zeigers \lstinline{p}, der durchgehend den Wert \lstinline{prime} hat, @@ -1740,41 +1739,41 @@ } \end{lstlisting} - Achtung: C pr�ft \emph{nicht}, ob der Array-Index - innerhalb des zul�ssigen Bereichs liegt, + Achtung: C prüft \emph{nicht}, ob der Array-Index + innerhalb des zulässigen Bereichs liegt, ob also der durch Addition des Index auf die Array-Adresse erhaltene Zeiger noch auf eine Adresse innerhalb des Arrays zeigt. - �bergelaufene Indizes f�hren nicht immer sofort zum Absturz des Programms, - sondern k�nnen z.\,B.\ andere Variablen des Programms �berschreiben + Übergelaufene Indizes führen nicht immer sofort zum Absturz des Programms, + sondern können z.\,B.\ andere Variablen des Programms überschreiben (siehe Beispielprogramm \file{arrays-13.c}). - Da derartige Fehler �u�erst schwer zu entdecken sind, + Da derartige Fehler äußerst schwer zu entdecken sind, lohnt es sich, Array-Indices vor ihrer Verwendung - mit Hilfe von \lstinline{if}-Anweisungen "`von Hand"' zu pr�fen. + mit Hilfe von \lstinline{if}-Anweisungen "`von Hand"' zu prüfen. \subsubsection{Strings} Ein wichtiger Spezialfall ist ein Array, dessen Komponenten den Datentyp \lstinline{char} haben. In C ist \lstinline{char} wie \lstinline{int} eine ganze Zahl; - der einzige Unterschied besteht darin, da� der Wertebereich von \lstinline{char} daran angepa�t ist, + der einzige Unterschied besteht darin, daß der Wertebereich von \lstinline{char} daran angepaßt ist, ein Zeichen (Buchstabe, Ziffer, Satz- oder Sonderzeichen, engl.\ character) aufzunehmen. - Ein typischer Wertebereich f�r den Datentyp \lstinline{char} ist von $-$128 bis 127. + Ein typischer Wertebereich für den Datentyp \lstinline{char} ist von $-$128 bis 127. - Ein Initialisierer f�r ein Array von \lstinline{char}-Variablen kann direkt als Folge von Zeichen - (Zeichenkette, engl.\ \newterm{String\/}) mit doppelten Anf�hrungszeichen geschrieben werden. + Ein Initialisierer für ein Array von \lstinline{char}-Variablen kann direkt als Folge von Zeichen + (Zeichenkette, engl.\ \newterm{String\/}) mit doppelten Anführungszeichen geschrieben werden. Jedes Zeichen initialisiert eine ganzzahlige Variable mit seinem ASCII-Wert. An das Ende eines in dieser Weise notierten Array-Initialisierers - f�gt der Compiler implizit einen Ganzzahl-Initialisierer f�r den Zahlenwert 0 an. + fügt der Compiler implizit einen Ganzzahl-Initialisierer für den Zahlenwert 0 an. Der Array-Initialisierer \lstinline{"Hello"} ist also gleichbedeutend mit \lstinline|{ 72, 101, 108, 108, 111, 0 }|. - (Die 72 steht f�r ein gro�es H, die 111 f�r ein kleines o. Man beachte die abschlie�ende 0 am Ende!) + (Die 72 steht für ein großes H, die 111 für ein kleines o. Man beachte die abschließende 0 am Ende!) Ein String in C ist also ein Array von \lstinline{char}s, also ein Zeiger auf \lstinline{char}s, - also ein Zeiger auf ganze Zahlen, deren Wertebereich daran angepa�t ist, Zeichen aufzunehmen. + also ein Zeiger auf ganze Zahlen, deren Wertebereich daran angepaßt ist, Zeichen aufzunehmen. - Wenn bei der Deklaration eines Arrays die L�nge aus dem Initialisierer hervorgeht, - braucht diese nicht ausdr�cklich angegeben zu werden. + Wenn bei der Deklaration eines Arrays die Länge aus dem Initialisierer hervorgeht, + braucht diese nicht ausdrücklich angegeben zu werden. In diesem Fall folgt auf den Bezeichner nur das Paar eckiger Klammern und der Initialisierer. Das Beispielprogramm \file{strings-1.c} zeigt, @@ -1792,9 +1791,9 @@ } \end{lstlisting} - Durch die Formatangabe \lstinline{%d} wird jedes Zeichen -- korrekterma�en -- als Dezimalzahl ausgegeben. - Wenn wir stattdessen die Formatangabe \lstinline{%c} verwenden (f�r \emph{character\/}), - wird f�r jedes Zeichen -- ebenso korrekterma�en -- sein Zeichenwert (Buchstabe, Ziffer, \dots) ausgegeben + Durch die Formatangabe \lstinline{%d} wird jedes Zeichen -- korrektermaßen -- als Dezimalzahl ausgegeben. + Wenn wir stattdessen die Formatangabe \lstinline{%c} verwenden (für \emph{character\/}), + wird für jedes Zeichen -- ebenso korrektermaßen -- sein Zeichenwert (Buchstabe, Ziffer, \dots) ausgegeben (Datei: \file{strings-2.c}): \begin{lstlisting} #include <stdio.h> @@ -1810,8 +1809,8 @@ \end{lstlisting} Durch Verwendung von Pointer-Arithmetik - und Weglassen der �berfl�ssigen Abfrage \lstinline{!= 0} - erhalten wir das �quivalente Beispielprogramm \file{strings-3.c}: + und Weglassen der überflüssigen Abfrage \lstinline{!= 0} + erhalten wir das äquivalente Beispielprogramm \file{strings-3.c}: \begin{lstlisting} #include <stdio.h> @@ -1824,13 +1823,13 @@ return 0; } \end{lstlisting} - Dieses ist die in C �bliche Art, eine Schleife zu schreiben, + Dieses ist die in C übliche Art, eine Schleife zu schreiben, die nacheinander alle Zeichen in einem String bearbeitet. \breath Eine weitere Formatangabe \lstinline{%s} dient in \lstinline{printf()} dazu, - direkt einen kompletten String bis ausschlie�lich der abschlie�enden 0 auszugeben. + direkt einen kompletten String bis ausschließlich der abschließenden 0 auszugeben. Beispielprogramm: \file{strings-4.c} \begin{lstlisting} @@ -1846,9 +1845,9 @@ Anstatt als Array, das dann einem Zeiger zugewiesen wird, deklarieren wir die Variable \lstinline{hello_world} direkt als Zeiger. - Dies ist die in C �bliche Art, mit String-Konstanten umzugehen. + Dies ist die in C übliche Art, mit String-Konstanten umzugehen. - Allein die Formatspezifikation entscheidet dar�ber, + Allein die Formatspezifikation entscheidet darüber, wie die Parameter von \lstinline{printf()} bei der Ausgabe dargestellt werden: \begin{quote} \begin{tabular}{cl} @@ -1871,7 +1870,7 @@ \end{lstlisting} geschrieben. - Tats�chlich kann das Hauptprogramm vom Betriebssystem Parameter entgegennehmen + Tatsächlich kann das Hauptprogramm vom Betriebssystem Parameter entgegennehmen (Datei: \file{params-1.c}): \begin{lstlisting} #include <stdio.h> @@ -1884,36 +1883,36 @@ return 0; } \end{lstlisting} - Bei der ganzen Zahl \lstinline{int argc} handelt es sich um die Anzahl der �bergebenen Parameter. + Bei der ganzen Zahl \lstinline{int argc} handelt es sich um die Anzahl der übergebenen Parameter. \lstinline{char **argv} ist ein Zeiger auf einen Zeiger, also ein Array von Arrays von \lstinline{char}s, also ein Array von Strings. Wenn wir es mit einem Index \lstinline{i} versehen, greifen wir auf auf den \lstinline{i}-ten Parameter zu. - Der Index \lstinline{i} l�uft, wie in C �blich, von \lstinline{0} bis \lstinline{argc - 1}. - Das o.\,a.\ Beispielprogramm gibt alle �bergebenen Parameter auf dem Standardausgabeger�t aus: + Der Index \lstinline{i} läuft, wie in C üblich, von \lstinline{0} bis \lstinline{argc - 1}. + Das o.\,a.\ Beispielprogramm gibt alle übergebenen Parameter auf dem Standardausgabegerät aus: \begin{lstlisting}[style=terminal] - $ �gcc -std=c99 -Wall -O params-1.c -o params-1� - $ �./params-1 foo bar baz� + $ ¡gcc -std=c99 -Wall -O params-1.c -o params-1¿ + $ ¡./params-1 foo bar baz¿ argc = 4 argv[0] = "./params-1" argv[1] = "foo" argv[2] = "bar" argv[3] = "baz" \end{lstlisting} - Genaugenommen �bergibt das Betriebssystem dem Programm die gesamte Kommandozeile: - Der nullte Parameter ist der Aufruf der ausf�hrbaren Datei selbst + Genaugenommen übergibt das Betriebssystem dem Programm die gesamte Kommandozeile: + Der nullte Parameter ist der Aufruf der ausführbaren Datei selbst -- in genau der Weise, in der er eingegeben wurde. Neben \lstinline{argc} gibt es noch einen weiteren Mechanismus, - mit dem das Betriebssystem dem Programm die Anzahl der �bergebenen Parameter mitteilt: - Als Markierung f�r das Ende der Liste wird ein zus�tzlicher Zeiger �bergeben, der auf "`nichts"' zeigt, + mit dem das Betriebssystem dem Programm die Anzahl der übergebenen Parameter mitteilt: + Als Markierung für das Ende der Liste wird ein zusätzlicher Zeiger übergeben, der auf "`nichts"' zeigt, dargestellt durch die Speicheradresse mit dem Zahlenwert 0, in C mit \lstinline{NULL} bezeichnet. Um die Parameter des Programms in einer Schleife durchzugehen, - k�nnen wir also entweder von \lstinline{0} bis \lstinline{argc - 1} z�hlen + können wir also entweder von \lstinline{0} bis \lstinline{argc - 1} zählen (Schleifenbedingung \lstinline{i < argc}) oder die Schleife mit dem Erreichen der Endmarkierung abbrechen (Schleifenbedingung \lstinline{argv[i] != NULL}). @@ -1928,9 +1927,9 @@ return 0; } \end{lstlisting} - Auch f�r Zeiger gilt: \lstinline{NULL} entspricht dem Wahrheitswert "`falsch"'; + Auch für Zeiger gilt: \lstinline{NULL} entspricht dem Wahrheitswert "`falsch"'; alles andere dem Wahrheitswert "`wahr"'. - Wir d�rfen die Schleifenbedingung also wie folgt abk�rzen (Datei: params-2.c): + Wir dürfen die Schleifenbedingung also wie folgt abkürzen (Datei: params-2.c): \begin{lstlisting} #include <stdio.h> @@ -1949,7 +1948,7 @@ mehrere Variable zu einer Einheit zusammenzufassen. Das folgende Beispielprogramm \file{structs-1.c} - fa�t drei Variable \lstinline{day}, \lstinline{month} und \lstinline{year} + faßt drei Variable \lstinline{day}, \lstinline{month} und \lstinline{year} zu einem einzigen -- neuen -- Datentyp \lstinline{date} zusammen: \begin{lstlisting} #include <stdio.h> @@ -1977,12 +1976,12 @@ \put(5.65,1.1){\makebox(0,0)[l]{Zugriff auf die Komponente day der strukturierten Variablen today}} \end{picture}% - (Zur Erinnerung: Der Datentyp \lstinline{char} steht f�r Zahlen, - die mindestens die Werte von $-$128 bis 127 annehmen k�nnen. + (Zur Erinnerung: Der Datentyp \lstinline{char} steht für Zahlen, + die mindestens die Werte von $-$128 bis 127 annehmen können. C unterscheidet nicht zwischen Zahlen und darstellbaren Zeichen.) Eine wichtige Anwendung derartiger \newterm{strukturierter Datentypen\/} besteht darin, - zusammengeh�rige Daten als Einheit an Funktionen �bergeben zu k�nnen + zusammengehörige Daten als Einheit an Funktionen übergeben zu können (Beispielprogramm: \file{structs-2.c}): \begin{lstlisting} #include <stdio.h> @@ -2011,15 +2010,15 @@ } \end{lstlisting} Die Funktion \lstinline{set_date()} hat die Aufgabe, - eine \lstinline{date}-Variable mit Werten zu f�llen (sog.\ \newterm{Setter\/}-Funktion). - Damit dies funktionieren kann, �bergibt das Hauptprogramm an die Funktion + eine \lstinline{date}-Variable mit Werten zu füllen (sog.\ \newterm{Setter\/}-Funktion). + Damit dies funktionieren kann, übergibt das Hauptprogramm an die Funktion einen Zeiger auf die strukturierte Variable. - �ber diesen Zeiger kann die Funktion dann auf alle Komponenten der Struktur zugreifen. - (Die Alternative w�re gewesen, f�r jede Komponente einen separaten Zeiger zu �bergeben.) + Über diesen Zeiger kann die Funktion dann auf alle Komponenten der Struktur zugreifen. + (Die Alternative wäre gewesen, für jede Komponente einen separaten Zeiger zu übergeben.) Da die Zeigerdereferenzierung \lstinline{*foo} - mit anschlie�endem Komponentenzugriff \lstinline{(*foo).bar} - eine sehr h�ufige Kombination ist, kennt C hierf�r eine Abk�rzung: + mit anschließendem Komponentenzugriff \lstinline{(*foo).bar} + eine sehr häufige Kombination ist, kennt C hierfür eine Abkürzung: \lstinline{foo->bar} Beispielprogramm: \file{structs-3.c} @@ -2055,23 +2054,23 @@ Schreiben Sie eine Funktion \lstinline{inc_date (date *d)} die ein gegebenes Datum \lstinline{d} - unter Beachtung von Schaltjahren auf den n�chsten Tag setzt. + unter Beachtung von Schaltjahren auf den nächsten Tag setzt. \goodbreak - \subsubsection*{L�sung} + \subsubsection*{Lösung} - Wir l�sen die Aufgabe �ber den sog.\ \newterm{Top-Down-Ansatz} ("`vom Allgemeinen zum Konkreten"'). - Als besonderen Trick approximieren wir unfertige Programmteile zun�chst durch einfachere, fehlerbehaftete. + Wir lösen die Aufgabe über den sog.\ \newterm{Top-Down-Ansatz} ("`vom Allgemeinen zum Konkreten"'). + Als besonderen Trick approximieren wir unfertige Programmteile zunächst durch einfachere, fehlerbehaftete. Diese fehlerhaften Programmteile sind in den untenstehenden Beispielen rot markiert. - (In der Praxis w�rde man diese Zeilen unmittelbar durch die richtigen ersetzen; - die fehlerhaften "`Platzhalter"' sollten also jeweils nur f�r Sekundenbruchteile im Programm stehen. - Falls man einmal tats�chlich einen Platzhalter f�r mehrere Sekunden oder l�nger stehen lassen sollte - -- z.\,B., weil an mehreren Stellen �nderungen notwendig sind --, + (In der Praxis würde man diese Zeilen unmittelbar durch die richtigen ersetzen; + die fehlerhaften "`Platzhalter"' sollten also jeweils nur für Sekundenbruchteile im Programm stehen. + Falls man einmal tatsächlich einen Platzhalter für mehrere Sekunden oder länger stehen lassen sollte + -- z.\,B., weil an mehreren Stellen Änderungen notwendig sind --, sollte man ihn durch etwas Uncompilierbares (z.\,B.\ \lstinline{@@@}) markieren, damit man auf jeden Fall vermeidet, ein fehlerhaftes Programm auszuliefern.) - Zun�chst kopieren wir das Beispielprogramm \file{structs-3.c} - und erg�nzen den Aufruf der -- noch nicht existierenden -- Funktion \lstinline{inc_date()} + Zunächst kopieren wir das Beispielprogramm \file{structs-3.c} + und ergänzen den Aufruf der -- noch nicht existierenden -- Funktion \lstinline{inc_date()} (Datei: \file{incdate-0.c}): \begin{lstlisting} #include <stdio.h> @@ -2094,14 +2093,14 @@ { date today; set_date (&today); - �inc_date (&today);� + ¡inc_date (&today);¿ printf ("%d.%d.%d\n", today.day, today.month, today.year); return 0; } \end{lstlisting} - Als n�chstes kopieren wir innerhalb des Programms die Funktion \lstinline{get_date()} - als "`Schablone"' f�r \lstinline{inc_date()}: + Als nächstes kopieren wir innerhalb des Programms die Funktion \lstinline{get_date()} + als "`Schablone"' für \lstinline{inc_date()}: \filbreak \begin{lstlisting} void get_date (date *d) @@ -2111,30 +2110,30 @@ d->year = 2012; } - �void inc_date (date *d) + ¡void inc_date (date *d) { d->day = 31; d->month = 1; d->year = 2012; - }� + }¿ \end{lstlisting} \filbreak Da die Funktion jetzt existiert, ist der Aufruf nicht mehr fehlerhaft. Stattdessen haben wir jetzt eine fehlerhafte Funktion \lstinline{inc_date()}. - Im n�chsten Schritt ersetzen wir die fehlerhafte Funktion - durch ein simples Hochz�hlen der \lstinline{day}-Kom\-po\-nen\-te (Datei: \file{incdate-1.c}) + Im nächsten Schritt ersetzen wir die fehlerhafte Funktion + durch ein simples Hochzählen der \lstinline{day}-Kom\-po\-nen\-te (Datei: \file{incdate-1.c}) \filbreak \begin{lstlisting} void inc_date (date *d) { - �d->day += 1; /* FIXME */� + ¡d->day += 1; /* FIXME */¿ } \end{lstlisting} \filbreak - Diese naive Vorgehensweise versagt, sobald wir den Tag �ber das Ende des Monats hinausz�hlen. - Dies reparieren wir im n�chsten Schritt, - wobei wir f�r den Moment inkorrekterweise annehmen, da� alle Monate 30 Tage h�tten + Diese naive Vorgehensweise versagt, sobald wir den Tag über das Ende des Monats hinauszählen. + Dies reparieren wir im nächsten Schritt, + wobei wir für den Moment inkorrekterweise annehmen, daß alle Monate 30 Tage hätten und das Jahr beliebig viele Monate. (Datei: \file{incdate-2.c}): \filbreak @@ -2142,15 +2141,15 @@ void inc_date (date *d) { d->day++; - �if (d->day > 31) /* FIXME */ + ¡if (d->day > 31) /* FIXME */ { d->month++; /* FIXME */ d->day = 1; - }� + }¿ } \end{lstlisting} \filbreak - Zun�chst reparieren wir den Fehler, der am Ende des Jahres entsteht + Zunächst reparieren wir den Fehler, der am Ende des Jahres entsteht (Datei: \file{incdate-3.c}). \filbreak \begin{lstlisting} @@ -2161,17 +2160,17 @@ { d->month++; d->day = 1; - �if (d->month > 12) + ¡if (d->month > 12) { d->year++; d->month = 1; - }� + }¿ } } \end{lstlisting} \filbreak Das Problem der unterschiedlich langen Monate gehen wir wieder stufenweise an. - Zun�chst ersetzen wir die Konstante \lstinline{31} + Zunächst ersetzen wir die Konstante \lstinline{31} durch eine Variable \lstinline{days_in_month}. (Datei: \file{incdate-4.c}) \filbreak @@ -2179,8 +2178,8 @@ void inc_date (date *d) { d->day++; - �int days_in_month = 31; /* FIXME */ - if (d->day > days_in_month)� + ¡int days_in_month = 31; /* FIXME */ + if (d->day > days_in_month)¿ { d->month++; d->day = 1; @@ -2193,18 +2192,18 @@ } \end{lstlisting} \filbreak - Anschlie�end reparieren wir den fehlerhaften (konstanten) Wert der Variablen, - wobei wir zun�chst das Problem der Schaltjahre aussparen (Datei: \file{incdate-5.c}): + Anschließend reparieren wir den fehlerhaften (konstanten) Wert der Variablen, + wobei wir zunächst das Problem der Schaltjahre aussparen (Datei: \file{incdate-5.c}): \filbreak \begin{lstlisting} void inc_date (date *d) { d->day++; int days_in_month = 31; - �if (d->month == 2) + ¡if (d->month == 2) days_in_month = 28; /* FIXME */ else if (d->month == 4 || d->month == 6 || d->month == 9 || d->month == 11) - days_in_month = 30;� + days_in_month = 30;¿ if (d->day > days_in_month) { d->month++; @@ -2218,7 +2217,7 @@ } \end{lstlisting} Auf dieselbe Weise lagern wir das Problem "`Schaltjahr oder nicht?"' - in eine Variable aus. Diese ist wieder zun�chst konstant + in eine Variable aus. Diese ist wieder zunächst konstant (Datei: \file{incdate-6.c}): \filbreak \begin{lstlisting} @@ -2228,11 +2227,11 @@ int days_in_month = 31; if (d->month == 2) { - �int is_leap_year = 1; /* FIXME */ + ¡int is_leap_year = 1; /* FIXME */ if (is_leap_year) days_in_month = 29; else - days_in_month = 28;� + days_in_month = 28;¿ } else if (d->month == 4 || d->month == 6 || d->month == 9 || d->month == 11) days_in_month = 30; @@ -2249,30 +2248,30 @@ } \end{lstlisting} \filbreak - Als n�chstes erg�nzen wir die Vier-Jahres-Regel f�r Schaltjahre + Als nächstes ergänzen wir die Vier-Jahres-Regel für Schaltjahre (Datei \file{incdate-7.c}): \filbreak \begin{lstlisting} - �int is_leap_year = 0; + ¡int is_leap_year = 0; if (d->year % 4 == 0) - is_leap_year = 1; /* FIXME */� + is_leap_year = 1; /* FIXME */¿ if (is_leap_year) days_in_month = 29; else days_in_month = 28; \end{lstlisting} \filbreak - Das nun vorliegende Programm arbeitet bereits f�r den julianischen Kalender - sowie f�r alle Jahre von 1901 bis 2099 korrekt, - nicht jedoch f�r z.\,B.\ das Jahr 2100 (Datei: \file{incdate-8.c}). - Damit das Programm f�r den aktuell verwendeten gregorianischen Kalender korrekt arbeitet, - erg�nzen wir noch die Ausnahme, da� durch 100 teilbare Jahre keine Schaltjahre sind, - sowie die Ausnahme von der Ausnahme, da� durch 400 teilbare Jahre + Das nun vorliegende Programm arbeitet bereits für den julianischen Kalender + sowie für alle Jahre von 1901 bis 2099 korrekt, + nicht jedoch für z.\,B.\ das Jahr 2100 (Datei: \file{incdate-8.c}). + Damit das Programm für den aktuell verwendeten gregorianischen Kalender korrekt arbeitet, + ergänzen wir noch die Ausnahme, daß durch 100 teilbare Jahre keine Schaltjahre sind, + sowie die Ausnahme von der Ausnahme, daß durch 400 teilbare Jahre (z.\,B.\ das Jahr 2000) eben doch Schaltjahre sind (Datei: \file{incdate-9.c}): \begin{lstlisting} int is_leap_year = 0; if (d->year % 4 == 0) - �{ + ¡{ is_leap_year = 1; if (d->year % 100 == 0) { @@ -2280,14 +2279,14 @@ if (d->year % 400 == 0) is_leap_year = 1; } - }� + }¿ if (is_leap_year) days_in_month = 29; else days_in_month = 28; \end{lstlisting} - Damit ist die Aufgabe gel�st. - Der vollst�ndige Quelltext der L�sung (Datei: \file{incdate-9.c}) lautet: + Damit ist die Aufgabe gelöst. + Der vollständige Quelltext der Lösung (Datei: \file{incdate-9.c}) lautet: \begin{lstlisting} #include <stdio.h> @@ -2353,68 +2352,68 @@ Bemerkungen: \begin{itemize} \item - Der Top-Down-Ansatz ist eine bew�hrte Methode, - um eine zun�chst komplexe Aufgabe in handhabbare Teilaufgaben zu zerlegen. - Dies hilft ungemein, in l�ngeren Programmen (mehrere Zehntausend bis Millionen Zeilen) - die �bersicht zu behalten. + Der Top-Down-Ansatz ist eine bewährte Methode, + um eine zunächst komplexe Aufgabe in handhabbare Teilaufgaben zu zerlegen. + Dies hilft ungemein, in längeren Programmen (mehrere Zehntausend bis Millionen Zeilen) + die Übersicht zu behalten. \item - Der Trick mit dem zun�chst fehlerhaften Code hat den Vorteil, - da� man jeden Zwischenstand des Programms compilieren und somit austesten kann. + Der Trick mit dem zunächst fehlerhaften Code hat den Vorteil, + daß man jeden Zwischenstand des Programms compilieren und somit austesten kann. Er birgt andererseits die Gefahr in sich, - die �bersicht �ber den fehlerhaften Code zu verlieren, - so da� es dieser bis in die Endfassung schafft. - Neben dem bereits erw�hnten Trick uncompilierbarer Symbole - haben sich hier Kommentare wie \lstinline{/* FIXME */} bew�hrt, + die Übersicht über den fehlerhaften Code zu verlieren, + so daß es dieser bis in die Endfassung schafft. + Neben dem bereits erwähnten Trick uncompilierbarer Symbole + haben sich hier Kommentare wie \lstinline{/* FIXME */} bewährt, auf die man seinen Code vor der Auslieferung der Endfassung - noch einmal automatisch durchsuchen l��t. + noch einmal automatisch durchsuchen läßt. % \item % Allen an der Berechnung beteiligten Funktionen -% wurde hier ein Zeiger \lstinline{d} auf die vollst�ndige \lstinline{date}-Struktur �bergeben. +% wurde hier ein Zeiger \lstinline{d} auf die vollständige \lstinline{date}-Struktur übergeben. % Dies ist ein \newterm{objektorientierter Ansatz}, -% bei dem man die Funktionen als \newterm{Methoden\/} der \newterm{Klasse\/} \lstinline{date} auffa�t. -% (Von sich aus unterst�tzt die Sprache C -- im Gegensatz zu z.\,B.\ C++ -- keine Klassen und Methoden, -% sondern man mu� diese bei Bedarf in der oben beschrieben Weise selbst basteln. -% F�r eine fertige L�sung siehe z.\,B.\ die \file{GObject}-Bibliothek -- \url{http://gtk.org}.) +% bei dem man die Funktionen als \newterm{Methoden\/} der \newterm{Klasse\/} \lstinline{date} auffaßt. +% (Von sich aus unterstützt die Sprache C -- im Gegensatz zu z.\,B.\ C++ -- keine Klassen und Methoden, +% sondern man muß diese bei Bedarf in der oben beschrieben Weise selbst basteln. +% Für eine fertige Lösung siehe z.\,B.\ die \file{GObject}-Bibliothek -- \url{http://gtk.org}.) % -% Alternativ k�nnte man sich mit den zu �bergebenden Parametern auf diejenigen beschr�nken, -% die in der Funktion tats�chlich ben�tigt werden, +% Alternativ könnte man sich mit den zu übergebenden Parametern auf diejenigen beschränken, +% die in der Funktion tatsächlich benötigt werden, % also z.\,B.\ \lstinline{int days_in_month (int month, int year)} % und \lstinline{int is_leap_year (int year)}. -% Damit w�ren die Funktionen allgemeiner verwendbar. +% Damit wären die Funktionen allgemeiner verwendbar. % -% Welcher dieser beiden Ans�tze der bessere ist, h�ngt von der Situation -% und von pers�nlichen Vorlieben ab. +% Welcher dieser beiden Ansätze der bessere ist, hängt von der Situation +% und von persönlichen Vorlieben ab. \end{itemize} \section{Bibliotheken} - \subsection{Der Pr�prozessor\label{Praeprozessor}} + \subsection{Der Präprozessor\label{Praeprozessor}} Der erste Schritt beim Compilieren eines C-Programms ist das - Aufl�sen der sogenannten Pr�prozessor-Direktiven und -Macros. + Auflösen der sogenannten Präprozessor-Direktiven und -Macros. \begin{lstlisting} #include <stdio.h> \end{lstlisting} \vspace{-\medskipamount} - bewirkt, da� aus Sicht des Compilers anstelle der Zeile + bewirkt, daß aus Sicht des Compilers anstelle der Zeile der Inhalt der Datei \file{stdio.h} im C-Quelltext erscheint. - Dies ist zun�chst unabh�ngig von Bibliotheken und auch nicht auf die Programmiersprache C beschr�nkt. + Dies ist zunächst unabhängig von Bibliotheken und auch nicht auf die Programmiersprache C beschränkt. Beispiel: - Die Datei \file{maerchen.c} enth�lt: + Die Datei \file{maerchen.c} enthält: \begin{lstlisting}[language={}] Vor langer, langer Zeit gab es einmal #include "hexe.h" Die lebte in einem Wald. \end{lstlisting} - Die Datei \file{hexe.h} enth�lt: + Die Datei \file{hexe.h} enthält: \begin{lstlisting}[language={}] eine kleine Hexe. \end{lstlisting} Der Aufruf \begin{lstlisting}[style=terminal] - $ �gcc -E -P maerchen.c� + $ ¡gcc -E -P maerchen.c¿ \end{lstlisting} produziert die Ausgabe \begin{lstlisting}[style=terminal] @@ -2424,11 +2423,11 @@ Die lebte in einem Wald. \end{lstlisting} Mit der Option \lstinline[style=cmd]{-E} weisen wir \lstinline[style=cmd]{gcc} an, - nicht zu compilieren, sondern nur den Pr�prozessor aufzurufen. - Die Option \lstinline[style=cmd]{-P} unterdr�ckt Herkunftsangaben, + nicht zu compilieren, sondern nur den Präprozessor aufzurufen. + Die Option \lstinline[style=cmd]{-P} unterdrückt Herkunftsangaben, die normalerweise vom Compiler verwendet werden, um Fehlermeldungen den richtigen Zeilen in den richtigen Dateien - zuordnen zu k�nnen. Ohne das \lstinline[style=cmd]{-P} lautet die Ausgabe: + zuordnen zu können. Ohne das \lstinline[style=cmd]{-P} lautet die Ausgabe: \begin{lstlisting}[style=terminal] # 1 "maerchen.c" # 1 "<built-in>" @@ -2453,18 +2452,18 @@ return 0; } \end{lstlisting} - Die Datei \file{stdio.h} ist wesentlich l�nger als \file{hexe.txt} in dem o.\,a.\ + Die Datei \file{stdio.h} ist wesentlich länger als \file{hexe.txt} in dem o.\,a.\ Beispiel, und sie ruft weitere Include-Dateien auf, - so da� wir insgesamt auf �ber 1000 Zeilen Quelltext kommen. - Die spitzen Klammern anstelle der Anf�hrungszeichen bedeuten, - da� es sich um eine \newterm{Standard-Include-Datei\/} handelt, + so daß wir insgesamt auf über 1000 Zeilen Quelltext kommen. + Die spitzen Klammern anstelle der Anführungszeichen bedeuten, + daß es sich um eine \newterm{Standard-Include-Datei\/} handelt, die nur in den Standard-Include-Verzeichnissen gesucht werden soll, nicht jedoch im aktuellen Verzeichnis. \subsection{Bibliotheken einbinden} - Tats�chlich ist von den �ber 1000 Zeilen aus \file{stdio.h} nur eine - einzige relevant, n�mlich: + Tatsächlich ist von den über 1000 Zeilen aus \file{stdio.h} nur eine + einzige relevant, nämlich: \begin{lstlisting} extern int printf (__const char *__restrict __format, ...); \end{lstlisting} @@ -2473,30 +2472,30 @@ \begin{itemize} \item Die Parameter \lstinline{__const char *__restrict __format, ...} - hei�en etwas ungew�hnlich. + heißen etwas ungewöhnlich. \item - Der Funktionsk�rper \lstinline|{ ... }| fehlt. Stattdessen folgt auf die + Der Funktionskörper \lstinline|{ ... }| fehlt. Stattdessen folgt auf die Kopfzeile direkt ein Semikolon \lstinline{;}. \item - Der Deklaration ist das Schl�sselwort \lstinline{extern} vorangestellt. + Der Deklaration ist das Schlüsselwort \lstinline{extern} vorangestellt. \end{itemize} - Dies bedeutet f�r den Compiler: + Dies bedeutet für den Compiler: "`Es gibt diese Funktion und sie sieht aus, wie beschrieben. - Benutze sie einfach, und k�mmere dich nicht darum, wer die Funktion schreibt."' + Benutze sie einfach, und kümmere dich nicht darum, wer die Funktion schreibt."' \begin{experts} - Wenn wir tats�chlich nur \lstinline{printf()} ben�tigen, - k�nnen wir also die Standard-Datei \file{stdio.h} durch eine eigene ersetzen, - die nur die o.\,a.\ Zeile \lstinline{extern int printf (...)} enth�lt. - (Dies ist in der Praxis nat�rlich keine gute Idee, weil nur derjenige, der die + Wenn wir tatsächlich nur \lstinline{printf()} benötigen, + können wir also die Standard-Datei \file{stdio.h} durch eine eigene ersetzen, + die nur die o.\,a.\ Zeile \lstinline{extern int printf (...)} enthält. + (Dies ist in der Praxis natürlich keine gute Idee, weil nur derjenige, der die Funktion \lstinline{printf()} geschrieben hat, den korrekten Aufruf kennt. In der Praxis sollten wir immer diejenige Include-Datei benutzen, - die gemeinsam mit der tats�chlichen Funktion ausgeliefert wurde.) + die gemeinsam mit der tatsächlichen Funktion ausgeliefert wurde.) \end{experts} \breath - Der Pr�prozessor kann nicht nur \lstinline{#include}-Direktiven aufl�sen. + Der Präprozessor kann nicht nur \lstinline{#include}-Direktiven auflösen. Mit \lstinline{#define} kann man sog.\ \newterm{Makros\/} definieren, die bei Benutzung durch einen Text ersetzt werden. Auf diese Weise kann man \newterm{Konstante\/} definieren. @@ -2514,8 +2513,8 @@ } \end{lstlisting} - Genau wie bei \lstinline{#include} nimmt der Pr�prozessor auch bei \lstinline{#define} - eine rein textuelle Ersetzung vor, ohne sich um den Sinn des Ersetzten zu k�mmern. + Genau wie bei \lstinline{#include} nimmt der Präprozessor auch bei \lstinline{#define} + eine rein textuelle Ersetzung vor, ohne sich um den Sinn des Ersetzten zu kümmern. Beispiel: \file{higher-math-2.c} \begin{lstlisting} @@ -2533,7 +2532,7 @@ } \end{lstlisting} - Dies kann zu Problemen f�hren, sobald Berechnungen ins Spiel kommen. + Dies kann zu Problemen führen, sobald Berechnungen ins Spiel kommen. Beispiel: \file{higher-math-4.c} \begin{lstlisting} @@ -2548,12 +2547,12 @@ } \end{lstlisting} Hier z.\,B.\ sieht man mit \lstinline[style=cmd]{gcc -E rechnen.c}, - da� die Ersetzung des Makros \lstinline{VIER} wie folgt lautet: + daß die Ersetzung des Makros \lstinline{VIER} wie folgt lautet: \begin{lstlisting} printf ("2 + 3 * 4 = %d\n", 2 + 3 * 2 + 2); \end{lstlisting} Der C-Compiler wendet die Regel "`Punktrechnung geht vor Strichrechnung"' an - und erf�hrt �berhaupt nicht, da� das \lstinline{2 + 2} aus einem Makro enstanden ist. + und erfährt überhaupt nicht, daß das \lstinline{2 + 2} aus einem Makro enstanden ist. Um derartige Effekte zu vermeiden, setzt man arithmetische Operationen innerhalb von Makros in Klammern. @@ -2563,20 +2562,20 @@ #define VIER (2 + 2) \end{lstlisting} - (Es ist in den meisten Situationen �blich, Makros in \lstinline{GROSSBUCHSTABEN} zu benennen, - um darauf hinzuweisen, da� es sich eben um einen Makro handelt.) + (Es ist in den meisten Situationen üblich, Makros in \lstinline{GROSSBUCHSTABEN} zu benennen, + um darauf hinzuweisen, daß es sich eben um einen Makro handelt.) - Achtung: Hinter Makro-Deklaration kommt �blicherweise \emph{kein\/} Semikolon. + Achtung: Hinter Makro-Deklaration kommt üblicherweise \emph{kein\/} Semikolon. \begin{experts} - Wenn man ein Semikolon setzt, geh�rt dies mit zum Ersetzungstext des Makros. - Dies ist grunds�tzlich zul�ssig, f�hrt aber zu sehr seltsamen C-Quelltexten + Wenn man ein Semikolon setzt, gehört dies mit zum Ersetzungstext des Makros. + Dies ist grundsätzlich zulässig, führt aber zu sehr seltsamen C-Quelltexten -- siehe z.\,B.\ \file{higher-math-6.c}. \end{experts} \breath - Das n�chste Beispiel illustriert, wie man Bibliotheken schreibt und verwendet. + Das nächste Beispiel illustriert, wie man Bibliotheken schreibt und verwendet. Es besteht aus drei Quelltexten: @@ -2610,7 +2609,7 @@ Der "`normale"' Aufruf \begin{lstlisting}[style=terminal] - $ �gcc -Wall -O philosophy.c -o philosophy� + $ ¡gcc -Wall -O philosophy.c -o philosophy¿ \end{lstlisting} liefert die Fehlermeldung: \begin{lstlisting}[style=terminal] @@ -2619,49 +2618,49 @@ collect2: ld returned 1 exit status \end{lstlisting} Diese stammt nicht vom Compiler, sondern vom \newterm{Linker}. - Das Programm ist syntaktisch korrekt und wird auch korrekt in eine Bin�rdatei umgewandelt + Das Programm ist syntaktisch korrekt und wird auch korrekt in eine Binärdatei umgewandelt (hier: \file{/tmp/ccr4Njg7.o}). - Erst beim Zusammenbau ("`Linken"') der ausf�hrbaren Datei (\file{philosophy}) + Erst beim Zusammenbau ("`Linken"') der ausführbaren Datei (\file{philosophy}) tritt ein Fehler auf. - Tats�chlich wird die Funktion \lstinline{answer()} + Tatsächlich wird die Funktion \lstinline{answer()} nicht innerhalb von \file{philosophy.c}, sondern in einer separaten Datei \file{answer.c}, einer sog.\ \newterm{Bibliothek\/} definiert. - Es ist m�glich (und �blich), Bibliotheken separat vom Hauptprogramm zu compilieren. + Es ist möglich (und üblich), Bibliotheken separat vom Hauptprogramm zu compilieren. Dadurch spart man sich das Neucompilieren, - wenn im Hauptprogramm etwas ge�ndert wurde, nicht jedoch in der Bibliothek. + wenn im Hauptprogramm etwas geändert wurde, nicht jedoch in der Bibliothek. Mit der Option \lstinline[style=cmd]{-c} weisen wir \lstinline[style=cmd]{gcc} an, nur zu compilieren, jedoch nicht zu linken. Die Aufrufe \begin{lstlisting}[style=terminal] - $ �gcc -Wall -O -c philosophy.c� - $ �gcc -Wall -O -c answer.c� + $ ¡gcc -Wall -O -c philosophy.c¿ + $ ¡gcc -Wall -O -c answer.c¿ \end{lstlisting} - produzieren die Bin�rdateien \file{philosophy.o} und \file{answer.o}, + produzieren die Binärdateien \file{philosophy.o} und \file{answer.o}, die sogenannten \newterm{Objekt-Dateien} (daher die Endung \file{.o} oder \file{.obj}). Mit dem Aufruf \begin{lstlisting}[style=terminal] - $ �gcc philosophy.o answer.o -o philosophy� + $ ¡gcc philosophy.o answer.o -o philosophy¿ \end{lstlisting} bauen wir die beiden bereits compilierten Objekt-Dateien zu einer - ausf�hrbaren Datei \file{philosophy} (hier ohne Endung) zusammen. + ausführbaren Datei \file{philosophy} (hier ohne Endung) zusammen. - Es ist auch m�glich, im Compiler-Aufruf gleich beide C-Quelltexte zu - �bergeben: + Es ist auch möglich, im Compiler-Aufruf gleich beide C-Quelltexte zu + übergeben: \begin{lstlisting}[style=terminal] - $ �gcc -Wall -O philosophy.c answer.c -o philosophy� + $ ¡gcc -Wall -O philosophy.c answer.c -o philosophy¿ \end{lstlisting} In diesem Fall ruft \lstinline[style=cmd]{gcc} zweimal den Compiler auf - (f�r jede C-Datei einmal) und anschlie�end den Linker. + (für jede C-Datei einmal) und anschließend den Linker. \subsection{Bibliotheken verwenden (Beispiel: OpenGL)} Die \newterm{OpenGL\/}-Bibilothek dient dazu, - unter Verwendung von Hardware-Unterst�tzung dreidimensionale Grafik auszugeben. + unter Verwendung von Hardware-Unterstützung dreidimensionale Grafik auszugeben. Die einfachste Art und Weise, OpenGL in seinen Programmen einzusetzen, - erfolgt �ber eine weitere Bibliothek, das \newterm{OpenGL Utility Toolkit (GLUT)}. + erfolgt über eine weitere Bibliothek, das \newterm{OpenGL Utility Toolkit (GLUT)}. Die Verwendung von OpenGL und GLUT erfolgt durch Einbinden der Include-Dateien \begin{lstlisting} @@ -2669,16 +2668,16 @@ #include <GL/glu.h> #include <GL/glut.h> \end{lstlisting} - und die �bergabe der Bibliotheken \lstinline[style=cmd]{-lGL -lGLU -lglut} im Compiler-Aufruf: + und die Übergabe der Bibliotheken \lstinline[style=cmd]{-lGL -lGLU -lglut} im Compiler-Aufruf: \begin{lstlisting}[style=terminal] - $ �gcc -Wall -O cube.c -lGL -lGLU -lglut -o cube� + $ ¡gcc -Wall -O cube.c -lGL -lGLU -lglut -o cube¿ \end{lstlisting} (Dies ist der Aufruf unter Unix. Unter Microsoft Windows ist der Aufruf etwas anders - und h�ngt von der verwendeten Version der GLUT-Bibliothek ab. - F�r Details siehe die Dokumentation der GLUT-Bibliothek.) + und hängt von der verwendeten Version der GLUT-Bibliothek ab. + Für Details siehe die Dokumentation der GLUT-Bibliothek.) - Die Bibliothek stellt uns fertig geschriebene Programmfragmente zur Verf�gung, insbesondere: + Die Bibliothek stellt uns fertig geschriebene Programmfragmente zur Verfügung, insbesondere: \begin{itemize} \item Funktionen: z.\,B.\ \lstinline{glutInit (&argc, argv);} @@ -2696,7 +2695,7 @@ \end{lstlisting} Ein weiteres wichtiges allgemeines Konzept, - das in OpenGL eine Rolle spielt, ist die �bergabe einer Funktion an die Bibliothek. + das in OpenGL eine Rolle spielt, ist die Übergabe einer Funktion an die Bibliothek. Man nennt dies das \newterm{Installieren einer Callback-Funktion}. \begin{lstlisting} void draw (void) @@ -2704,31 +2703,31 @@ glutDisplayFunc (draw); \end{lstlisting} - Wir �bergeben die -- von uns geschriebene -- Funktion \lstinline{draw()} + Wir übergeben die -- von uns geschriebene -- Funktion \lstinline{draw()} an die OpenGL-Funktion \lstinline{glutDisplayFunc()}. - Dies bewirkt, da� OpenGL immer dann, wenn etwas gezeichnet werden soll, \lstinline{draw()} aufruft. - Innerhalb von \lstinline{draw()} k�nnen wir also unsere Zeichenbefehle unterbringen. + Dies bewirkt, daß OpenGL immer dann, wenn etwas gezeichnet werden soll, \lstinline{draw()} aufruft. + Innerhalb von \lstinline{draw()} können wir also unsere Zeichenbefehle unterbringen. \breath Die OpenGL-Bibliothek ist sehr umfangreich und kann im Rahmen dieser Vorlesung nicht im Detail behandelt werden. - Um trotzdem damit arbeiten zu k�nnen, + Um trotzdem damit arbeiten zu können, lagern wir bestimmte Teile -- Initialisierung und das Setzen von Farben -- in eine eigene Bibliothek \file{opengl-magic} aus, die wir als "`Black Box"' verwenden. Der Compiler-Aufruf lautet dann: \begin{lstlisting}[style=terminal] - $ �gcc -Wall -O cube.c -lGL -lGLU -lglut opengl-magic.c -o cube� + $ ¡gcc -Wall -O cube.c -lGL -lGLU -lglut opengl-magic.c -o cube¿ \end{lstlisting} - (Wer in eigenen Projekten mehr mit OpenGL machen m�chte, + (Wer in eigenen Projekten mehr mit OpenGL machen möchte, ist herzlich eingeladen, die Funktionsweise von \file{opengl-magic} zu studieren.) \begin{itemize} \item Das Beispielprogramm \file{cube-1.c} illustriert, - wie man grunds�tzlich �berhaupt ein geometrisches Objekt zeichnet. - In diesem Fall handelt es sich um einen W�rfel der Kantenl�nge \lstinline{0.5}, - von dem wir nur die Vorderfl�che sehen, also ein Quadrat. + wie man grundsätzlich überhaupt ein geometrisches Objekt zeichnet. + In diesem Fall handelt es sich um einen Würfel der Kantenlänge \lstinline{0.5}, + von dem wir nur die Vorderfläche sehen, also ein Quadrat. \begin{lstlisting}[gobble=8] #include <GL/gl.h> #include <GL/glu.h> @@ -2754,11 +2753,11 @@ \begin{picture}(0,0) \color{red} \put(12.5,6.0){\vector(-1,0){1}} - \put(12.6,6.0){\makebox(0,0)[l]{Bildschirm l�schen}} + \put(12.6,6.0){\makebox(0,0)[l]{Bildschirm löschen}} \put(7.5,5.55){\vector(-1,0){1}} - \put(7.6,5.55){\makebox(0,0)[l]{Rot- und Gr�nanteil 100\,\%, Blauanteil 0\,\%}} + \put(7.6,5.55){\makebox(0,0)[l]{Rot- und Grünanteil 100\,\%, Blauanteil 0\,\%}} \put(5.5,5.1){\vector(-1,0){1}} - \put(5.6,5.1){\makebox(0,0)[l]{W�rfel zeichnen}} + \put(5.6,5.1){\makebox(0,0)[l]{Würfel zeichnen}} \put(4.0,4.65){\vector(-1,0){1}} \put(4.1,4.65){\makebox(0,0)[l]{Zeichnung "`abschicken"'}} \put(6.0,2.15){\vector(-1,0){1}} @@ -2768,67 +2767,67 @@ \end{picture} \item In \file{cube-2.c} kommt eine Drehung um \lstinline{-30} Grad - um eine schr�ge Achse \lstinline{(0.5, 1.0, 0.0)} hinzu. - Der W�rfel ist jetzt als solcher zu erkennen. + um eine schräge Achse \lstinline{(0.5, 1.0, 0.0)} hinzu. + Der Würfel ist jetzt als solcher zu erkennen. Jeder Aufruf von \lstinline{glRotatef()} bewirkt, - da� alle nachfolgenden Zeichenoperationen gedreht ausgef�hrt werden. + daß alle nachfolgenden Zeichenoperationen gedreht ausgeführt werden. \item - In \file{cube-3.c} kommt als zus�tzliches Konzept eine weitere Callback-Funktion hinzu, - n�mlich ein \newterm{Timer-Handler}. + In \file{cube-3.c} kommt als zusätzliches Konzept eine weitere Callback-Funktion hinzu, + nämlich ein \newterm{Timer-Handler}. Durch den \lstinline{glutTimerFunc()}-Aufruf veranlassen wir OpenGL, die von uns geschriebene Funktion \lstinline{timer_handler()} aufzurufen, sobald \lstinline{50} Millisekunden vergangen sind. Innerhalb von \lstinline{timer_handler()} rufen wir \lstinline{glutTimerFunc()} erneut auf, - was insgesamt zur Folge hat, da� \lstinline{timer_handler()} periodisch alle 50 Millisekunden + was insgesamt zur Folge hat, daß \lstinline{timer_handler()} periodisch alle 50 Millisekunden aufgerufen wird. Die "`Nutzlast"' der Funktion \lstinline{timer_handler()} besteht darin, - eine Variable \lstinline{t} um den Wert \lstinline{0.05} zu erh�hen - und anschlie�end mittels \lstinline{glutPostRedisplay()} ein Neuzeichnen anzufordern. - Dies alles bewirkt, da� die Variable \lstinline{t} die aktuelle Zeit seit Programmbeginn - in Sekunden enth�lt und da� \lstinline{draw()} zwanzigmal pro Sekunde aufgerufen wird. + eine Variable \lstinline{t} um den Wert \lstinline{0.05} zu erhöhen + und anschließend mittels \lstinline{glutPostRedisplay()} ein Neuzeichnen anzufordern. + Dies alles bewirkt, daß die Variable \lstinline{t} die aktuelle Zeit seit Programmbeginn + in Sekunden enthält und daß \lstinline{draw()} zwanzigmal pro Sekunde aufgerufen wird. \item - Weil das Bild w�hrend des Neuzeichnens die ganze Zeit zu sehen ist, + Weil das Bild während des Neuzeichnens die ganze Zeit zu sehen ist, flackert in \file{cube-3.c} der Bildschirm. Dies wird in \file{cube-3a.c} dadurch behoben, - da� die Zeichnung zun�chst in einem unsichtbaren Pufferspeicher aufgebaut wird. + daß die Zeichnung zunächst in einem unsichtbaren Pufferspeicher aufgebaut wird. Erst die fertige Zeichnung wird mit dem Funktionsaufruf \lstinline{swapBuffers()} sichtbar gemacht. - Damit dies m�glich ist, mu� beim Initialisieren ein doppelter Puffer angefordert werden. + Damit dies möglich ist, muß beim Initialisieren ein doppelter Puffer angefordert werden. Zu diesem Zweck ersetzen wir die Bibliothek \file{opengl-magic.c} durch \file{opengl-magic-double.c}. Der Compiler-Aufruf lautet dann: \begin{lstlisting}[style=terminal,gobble=8] - $ �gcc -Wall -O cube.c -lGL -lGLU -lglut opengl-magic-double.c -o cube� + $ ¡gcc -Wall -O cube.c -lGL -lGLU -lglut opengl-magic-double.c -o cube¿ \end{lstlisting} - Unabh�ngig davon hei�t die Include-Datei weiterhin \file{opengl-magic.h}. - Dies illustriert, da� der Include-Mechanismus des Pr�prozessors - und der Zusammenbau-Mecha"-nismus des Linkers tats�chlich voneinander unabh�ngig sind. + Unabhängig davon heißt die Include-Datei weiterhin \file{opengl-magic.h}. + Dies illustriert, daß der Include-Mechanismus des Präprozessors + und der Zusammenbau-Mecha"-nismus des Linkers tatsächlich voneinander unabhängig sind. \begin{experts} (Durch das Austauschen von Bibliotheken, insbesondere bei dynamischen Bibliotheken (Endung \file{.so} unter Unix bzw.\ \file{.dll} unter Microsoft Windows) - ist es m�glich, das Verhalten bereits fertiger Programme zu beeinflussen, - ohne das Programm neu compilieren zu m�ssen. + ist es möglich, das Verhalten bereits fertiger Programme zu beeinflussen, + ohne das Programm neu compilieren zu müssen. Dies kann zu Testzwecken geschehen, zur Erweiterung des Funktionsumfangs oder auch zum Einschleusen von Schadfunktionen.) \end{experts} \item - In \file{cube-3a.c} dreht sich der W�rfel zun�chst langsam, dann immer schneller. - Dies liegt daran, da� sich jedes \lstinline{glRotatef()} + In \file{cube-3a.c} dreht sich der Würfel zunächst langsam, dann immer schneller. + Dies liegt daran, daß sich jedes \lstinline{glRotatef()} auf alle nachfolgenden Zeichenbefehle auswirkt, - so da� sich s�mtliche \lstinline{glRotatef()} aufaddieren. + so daß sich sämtliche \lstinline{glRotatef()} aufaddieren. - Eine M�glichkeit, stattdessen eine gleichm��ige Drehung zu erreichen, + Eine Möglichkeit, stattdessen eine gleichmäßige Drehung zu erreichen, besteht darin, den Wirkungsbereich des \lstinline{glRotatef()} zu begrenzen. - Dies geschieht durch Einschlie�en der Rotation in das Befehlspaar \lstinline{glPushMatrix()} + Dies geschieht durch Einschließen der Rotation in das Befehlspaar \lstinline{glPushMatrix()} und \lstinline{glPopMatrix()}: Durch \lstinline{glPopMatrix()} wird das System wieder in denjenigen Zustand versetzt, in dem es sich vor dem Aufruf von \lstinline{glPushMatrix()} befand. @@ -2839,10 +2838,10 @@ \subsubsection*{Aufgabe} - F�r welche elementaren geometrischen K�rper - stellt die GLUT-Bibliothek Zeichenroutinen zur Verf�gung? + Für welche elementaren geometrischen Körper + stellt die GLUT-Bibliothek Zeichenroutinen zur Verfügung? - \subsubsection*{L�sung} + \subsubsection*{Lösung} Ein Blick in die Include-Datei \file{glut.h} verweist uns auf eine andere Include-Datei: @@ -2863,7 +2862,7 @@ glutSolidTeapot (GLdouble size); \end{lstlisting} Zu jeder \lstinline{glutSolid}-Funktion gibt es auch eine \lstinline{glutWire}-Funktion, - beispielsweise \lstinline{glutWireCube()} als Gegenst�ck zu \lstinline{glutSolidCube()}. + beispielsweise \lstinline{glutWireCube()} als Gegenstück zu \lstinline{glutSolidCube()}. In demselben Verzeichnis finden wir auch eine Datei \file{freeglut\_ext.h} mit weiteren Funktionen dieses Typs: @@ -2873,7 +2872,7 @@ glutSolidCylinder (GLdouble radius, GLdouble height, GLint slices, GLint stacks); \end{lstlisting} - Die GLUT-Bibliothek kennt insbesondere standardm��ig eine Funktion zum Zeichnen einer Teekanne + Die GLUT-Bibliothek kennt insbesondere standardmäßig eine Funktion zum Zeichnen einer Teekanne und als Erweiterung eine Funktion zum Zeichnen eines Sierpinski-Schwamms. \breath @@ -2883,12 +2882,12 @@ \item Die Beispielprogramme \file{orbit-1.c} und \file{orbit-1a.c} illustrieren eine weitere Transformation der gezeichneten Objekte, - n�mlich die Translation (Verschiebung). + nämlich die Translation (Verschiebung). Jeder Transformationsbefehl wirkt sich jeweils auf die \emph{danach\/} erfolgenden Zeichenbefehle aus. Um sich zu veranschaulichen, welche Transformationen auf ein gezeichnetes Objekt wirken (hier z.\,B.\ auf \lstinline{glutSolidSphere()}), - mu� man die Transformationen in der Reihenfolge \emph{von unten nach oben\/} ausf�hren. + muß man die Transformationen in der Reihenfolge \emph{von unten nach oben\/} ausführen. \item Die Beispielprogramme \file{orbit-2.c} und \file{orbit-3.c} @@ -2897,9 +2896,9 @@ \begin{experts} \item - Das Beispielprogramm \file{orbit-x.c} schlie�lich versieht + Das Beispielprogramm \file{orbit-x.c} schließlich versieht die gezeichneten Objekte "`Mond"' und "`Erde"' mit realistischen Texturen (NASA-Fotos). - Die hierf�r notwendigen doch eher komplizierten Funktionsaufrufe + Die hierfür notwendigen doch eher komplizierten Funktionsaufrufe wurden wiederum in eine Bibliothek (\file{textured-spheres}) ausgelagert. \end{experts} @@ -2909,23 +2908,23 @@ \subsection{Standard-Pfade} - Wenn eine Bibliothek regelm��ig von vielen Programmierern benutzt - wird, wird sie �blicherweise an einem Standard-Ort abgelegt, z.\,B.\ in + Wenn eine Bibliothek regelmäßig von vielen Programmierern benutzt + wird, wird sie üblicherweise an einem Standard-Ort abgelegt, z.\,B.\ in dem Verzeichnis \file{/usr/lib}. - \verb|gcc| erwartet, da� die Namen von Bibliotheksdateien mit \file{lib} - beginnen und die Endung \file{.a} oder \file{.so} haben. (\file{.a} steht f�r - "`Archiv"', da eine \file{.a}-Datei mehrere \file{.o}-Dateien enth�lt. - \file{.so} steht f�r "`shared object"' und bezeichnet eine Bibliothek, die + \verb|gcc| erwartet, daß die Namen von Bibliotheksdateien mit \file{lib} + beginnen und die Endung \file{.a} oder \file{.so} haben. (\file{.a} steht für + "`Archiv"', da eine \file{.a}-Datei mehrere \file{.o}-Dateien enthält. + \file{.so} steht für "`shared object"' und bezeichnet eine Bibliothek, die erst zur Laufzeit eingebunden wird und von mehreren Programmen - gleichzeitig benutzt werden kann. Andere �bliche Bezeichnungen + gleichzeitig benutzt werden kann. Andere übliche Bezeichnungen sind \file{.lib} anstelle von \file{.a} und \file{.dll} anstelle von \file{.so}.) - Mit der Option \verb|-lfoo| teilen wir \verb|gcc| mit, da� wir eine Datei - \file{libfoo.a} aus einem der Standardverzeichnisse verwenden m�chten. - ("`foo"' ist eine metasyntaktische Variable und steht f�r ein + Mit der Option \verb|-lfoo| teilen wir \verb|gcc| mit, daß wir eine Datei + \file{libfoo.a} aus einem der Standardverzeichnisse verwenden möchten. + ("`foo"' ist eine metasyntaktische Variable und steht für ein beliebiges Wort.) Auch der Aufruf \verb|-lm| zum Einbinden der - Mathematik-Bibliothek ist nichts anderes. Tats�chlich gibt es + Mathematik-Bibliothek ist nichts anderes. Tatsächlich gibt es eine Datei \file{libm.a} im Verzeichnis \file{/usr/lib}. \begin{verbatim} gcc test.c -lm -o test\end{verbatim} @@ -2933,25 +2932,25 @@ \begin{verbatim} gcc test.c /usr/lib/libm.a -o test\end{verbatim} - Mit der Option \verb|-L /foo/bar| k�nnen wir ein Verzeichnis \file{/foo/bar} - dem Suchpfad hinzuf�gen. ("`bar"' ist eine weitere metasyntaktische + Mit der Option \verb|-L /foo/bar| können wir ein Verzeichnis \file{/foo/bar} + dem Suchpfad hinzufügen. ("`bar"' ist eine weitere metasyntaktische Variable.) \begin{verbatim} gcc test.c -L /home/joe/my_libs -lmy -o test\end{verbatim} compiliert \file{test.c} und linkt es mit einer Bibliothek \file{libmy.a}, nach der nicht nur in den Standardverzeichnissen (\file{/usr/lib}, - \file{/usr/local/lib} u.\,a.), sondern zus�tzlich im Verzeichnis + \file{/usr/local/lib} u.\,a.), sondern zusätzlich im Verzeichnis \file{/home/joe/my\_libs} gesucht wird. - Auf gleiche Weise kann man mit \verb|-I /foo/bar| Verzeichnisse f�r - Include-Dateien (s.\,o.)\ dem Standardsuchpfad hinzuf�gen. + Auf gleiche Weise kann man mit \verb|-I /foo/bar| Verzeichnisse für + Include-Dateien (s.\,o.)\ dem Standardsuchpfad hinzufügen. \fi \subsection{Projekt organisieren: make} - In gr��eren Projekten ruft man den Compiler (und Pr�prozessor und - Linker) nicht "`von Hand"' auf, sondern �berl��t dies einem weiteren + In größeren Projekten ruft man den Compiler (und Präprozessor und + Linker) nicht "`von Hand"' auf, sondern überläßt dies einem weiteren Programm namens \lstinline[style=cmd]{make}. \lstinline[style=cmd]{make} sucht im aktuellen Verzeichnis nach einer Datei \file{Makefile} @@ -2962,26 +2961,26 @@ \subsubsection{make-Regeln} - Ein Makefile enth�lt sog.\ Regeln, um Ziele zu erzeugen. + Ein Makefile enthält sog.\ Regeln, um Ziele zu erzeugen. Eine Regel beginnt mit der Angabe des Ziels, gefolgt von einem Doppelpunkt und den Dateien (oder anderen Zielen), von denen es - abh�ngt. Darunter steht, mit einem Tabulator-Zeichen einger�ckt, der - Programmaufruf, der n�tig ist, um das Ziel zu bauen. + abhängt. Darunter steht, mit einem Tabulator-Zeichen eingerückt, der + Programmaufruf, der nötig ist, um das Ziel zu bauen. \begin{lstlisting}[language=make] philosophy.o: philosophy.c answer.h gcc -c philosophy.c -o philosophy.o \end{lstlisting} - Achtung: Ein Tabulator-Zeichen l��t sich optisch h�ufig nicht von + Achtung: Ein Tabulator-Zeichen läßt sich optisch häufig nicht von mehreren Leerzeichen unterscheiden. \lstinline[style=cmd]{make} akzeptiert jedoch nur das Tabulator-Zeichen. - Die o.\,a.\ Regel bedeutet, da� jedesmal, wenn sich \file{philosophy.c} oder - \file{answer.h} ge�ndert hat, \lstinline[style=cmd]{make} + Die o.\,a.\ Regel bedeutet, daß jedesmal, wenn sich \file{philosophy.c} oder + \file{answer.h} geändert hat, \lstinline[style=cmd]{make} das Programm \lstinline[style=cmd]{gcc} in der beschriebenen Weise aufrufen soll. Durch die Kombination mehrerer Regeln lernt \lstinline[style=cmd]{make}, - welche Befehle in welcher Reihenfolge aufgerufen werden m�ssen, - je nachdem, welche Dateien ge�ndert wurden. + welche Befehle in welcher Reihenfolge aufgerufen werden müssen, + je nachdem, welche Dateien geändert wurden. \breath @@ -2989,24 +2988,24 @@ Der Aufruf \begin{lstlisting}[style=terminal] - $ �make -f Makefile.orbit-x1� + $ ¡make -f Makefile.orbit-x1¿ \end{lstlisting} bewirkt beim ersten Mal: \begin{lstlisting}[style=terminal] gcc -Wall -O orbit-x1.c opengl-magic-double.c textured-spheres.c \ -lGL -lGLU -lglut -o orbit-x1 \end{lstlisting} - Beim zweiten Aufruf stellt \lstinline[style=cmd]{make} fest, da� sich keine der Dateien - auf der rechten Seite der Regeln (rechts vom Doppelpunkt) ge�ndert + Beim zweiten Aufruf stellt \lstinline[style=cmd]{make} fest, daß sich keine der Dateien + auf der rechten Seite der Regeln (rechts vom Doppelpunkt) geändert hat und ruft keine Programme auf: \begin{lstlisting}[style=terminal] - make: �orbit-x1� ist bereits aktualisiert. + make: »orbit-x1« ist bereits aktualisiert. \end{lstlisting} \subsubsection{make-Macros} Um wiederkehrende Dinge (typischerweise: Listen von Dateinamen oder - Compiler-Optionen) nicht mehrfach eingeben zu m�ssen, kennt \lstinline[style=cmd]{make} + Compiler-Optionen) nicht mehrfach eingeben zu müssen, kennt \lstinline[style=cmd]{make} sog.\ Macros: \begin{lstlisting}[language=make] PHILOSOPHY_SOURCES = philosophy.c answer.h @@ -3017,7 +3016,7 @@ philosophy.o: $(PHILOSOPHY_SOURCES) gcc -c philosophy.c -o philosophy.o \end{lstlisting} - ist also nur eine andere Schreibweise f�r: + ist also nur eine andere Schreibweise für: \begin{lstlisting}[language=make] philosophy.o: philosophy.c answer.h gcc -c philosophy.c -o philosophy.o @@ -3027,62 +3026,62 @@ Beispiel: \file{Makefile.blink} - Die Beispielprogramme \file{blink-\lstinline{*}.c} sind daf�r gedacht, + Die Beispielprogramme \file{blink-\lstinline{*}.c} sind dafür gedacht, auf einem Mikro-Controller zu laufen. - Der Compiler-Aufruf erfordert zus�tzliche Optionen + Der Compiler-Aufruf erfordert zusätzliche Optionen (z.\,B.\ \lstinline[style=cmd]{-Os -mmcu=atmega32}), - und es m�ssen zus�tzliche Entwicklungswerkzeuge + und es müssen zusätzliche Entwicklungswerkzeuge (z.\,B.\ \lstinline[style=cmd]{avr-objcopy}) aufgerufen werden -- ebenfalls mit den richtigen Optionen. - Der Proze� des Zusammenbauens wird durch ein Makefile \file{Makefile.blink} verwaltet. + Der Prozeß des Zusammenbauens wird durch ein Makefile \file{Makefile.blink} verwaltet. \file{Makefile.blink} speichert den Namen des Quelltextes (ohne die Endung \file{.c}) in einem Macro. - Durch �ndern allein dieses Macros ist es daher m�glich, - das Makefile f�r ein anderes Projekt einzusetzen. + Durch Ändern allein dieses Macros ist es daher möglich, + das Makefile für ein anderes Projekt einzusetzen. - Zus�tzlich f�hrt \file{Makefile.blink} eine neue Regel \lstinline{clean} ein. - Diese bewirkt �blicherweise, da� alle automatisch erzeugten Dateien - gel�scht werden: + Zusätzlich führt \file{Makefile.blink} eine neue Regel \lstinline{clean} ein. + Diese bewirkt üblicherweise, daß alle automatisch erzeugten Dateien + gelöscht werden: \begin{lstlisting}[language=make] clean: rm -f $(TARGET).elf $(TARGET).hex \end{lstlisting} Rechts vom Doppelpunkt nach \lstinline[language=make]{clean} befinden sich keine - Abh�ngigkeitsdateien. Dies hat zur Folge, da� die Aktion + Abhängigkeitsdateien. Dies hat zur Folge, daß die Aktion (\lstinline{rm -f ...}) bei \lstinline[style=cmd]{make clean} - grunds�tzlich immer ausgef�hrt wird, also nicht nur, wenn sich irgendeine Datei ge�ndert hat. + grundsätzlich immer ausgeführt wird, also nicht nur, wenn sich irgendeine Datei geändert hat. \begin{experts} - Ebenfalls �blich ist eine weitere Regel \lstinline[language=make]{install}, - die bewirkt, da� die Zieldateien - (bei einem Programm typischerweise eine ausf�hrbare Datei, + Ebenfalls üblich ist eine weitere Regel \lstinline[language=make]{install}, + die bewirkt, daß die Zieldateien + (bei einem Programm typischerweise eine ausführbare Datei, bei einer Bibliothek typischerweise \file{.a}-, \file{.so}- sowie \file{.h}-Dateien) - an ihren endg�ltigen Bestimmungsort kopiert werden. + an ihren endgültigen Bestimmungsort kopiert werden. \end{experts} \subsubsection{Fazit: 3 Sprachen} - Um in C programmieren zu k�nnen, mu� man also tats�chlich drei + Um in C programmieren zu können, muß man also tatsächlich drei Sprachen lernen: \begin{itemize} \item C selbst, - \item die Pr�prozessor-Sprache + \item die Präprozessor-Sprache \item und die \lstinline[style=cmd]{make}-Sprache. \end{itemize} - Durch Entwicklungsumgebungen wie z.\,B.\ \file{Eclipse} l��t sich der + Durch Entwicklungsumgebungen wie z.\,B.\ \file{Eclipse} läßt sich der \lstinline[style=cmd]{make}-Anteil teilweise automatisieren. (\file{Eclipse} z.\,B.\ schreibt ein - Makefile; andere Umgebungen �bernehmen die Funktionalit�t von \lstinline[style=cmd]{make} - selbst.) Auch dort mu� man jedoch die zu einem Projekt geh�renden + Makefile; andere Umgebungen übernehmen die Funktionalität von \lstinline[style=cmd]{make} + selbst.) Auch dort muß man jedoch die zu einem Projekt gehörenden Dateien verwalten. Wenn sich dann eine Datei nicht an dem Ort befindet, - erh�lt man u.\,U.\ wenig aussagekr�ftige Fehlermeldungen, z.\,B.: + erhält man u.\,U.\ wenig aussagekräftige Fehlermeldungen, z.\,B.: \begin{lstlisting}[style=terminal] make: *** No rule to make target `MeinProgramm.elf', needed by `elf'. Stop. \end{lstlisting} - Wenn man dann um die Zusammenh�nge wei� ("`Welche Bibliotheken verwendet mein - Programm? Wo befinden sich diese? Und wie erf�hrt der Linker davon?"'), + Wenn man dann um die Zusammenhänge weiß ("`Welche Bibliotheken verwendet mein + Programm? Wo befinden sich diese? Und wie erfährt der Linker davon?"'), kann man das Problem systematisch angehen und ist nicht auf Herumraten angewiesen. @@ -3094,19 +3093,19 @@ \begin{displaymath} x + 2 = -x \end{displaymath} - l��t sich leicht nach der Unbekannten $x$ aufl�sen. - (In diesem Fall lautet die L�sung: $x = -1$.) + läßt sich leicht nach der Unbekannten $x$ auflösen. + (In diesem Fall lautet die Lösung: $x = -1$.) Wesentlich schwieriger ist es, - eine mathematische Gleichung mit einer gesuchten Funktion $x(t)$ zu l�sen, z.\,B.: + eine mathematische Gleichung mit einer gesuchten Funktion $x(t)$ zu lösen, z.\,B.: \begin{displaymath} x'(t) = -x(t)\qquad\mbox{mit}\qquad x(0) = 1 \end{displaymath} - Um hier auf die L�sung $x(t) = e^{-t}$ zu kommen, + Um hier auf die Lösung $x(t) = e^{-t}$ zu kommen, sind bereits weitreichende mathematische Kenntnisse erforderlich. Eine derartige Gleichung, die einen Zusammenhang zwischen der gesuchten Funktion - und ihren Ableitungen vorgibt, hei�t \newterm{Differentialgleichung}. + und ihren Ableitungen vorgibt, heißt \newterm{Differentialgleichung}. Viele physikalisch-technische Probleme werden durch Differentialgleichungen beschrieben. \goodbreak @@ -3122,21 +3121,21 @@ Wie aus anderen Veranstaltungen (Grundlagen der Physik, Mechanik) her bekannt sein sollte, wirkt auf ein Fadenpendel, das um den Winkel $\phi(t)$ ausgelenkt ist, die tangentiale Kraft $F = -m \cdot g \cdot \sin\phi(t)$. - Gem�� der Formel $F = m \cdot a$ bewirkt diese Kraft + Gemäß der Formel $F = m \cdot a$ bewirkt diese Kraft eine tangentiale Beschleunigung $a = -g \cdot \sin\phi(t)$. - (Das Minuszeichen kommt daher, da� die Kraft der Auslenkung entgegengesetzt wirkt.) + (Das Minuszeichen kommt daher, daß die Kraft der Auslenkung entgegengesetzt wirkt.) - Wenn das Pendel die L�nge $l$ hat, k�nnen wir dieselbe tangentiale Beschleunigung + Wenn das Pendel die Länge $l$ hat, können wir dieselbe tangentiale Beschleunigung mit Hilfe der zweiten Ableitung des Auslenkungswinkels $\phi(t)$ berechnen: - $a = l \cdot \phi''(t)$ (Winkel in Bogenma�). + $a = l \cdot \phi''(t)$ (Winkel in Bogenmaß). Durch Gleichsetzen erhalten wir eine Gleichung, - die nur noch eine Unbekannte enth�lt, n�mlich die Funktion $\phi(t)$. + die nur noch eine Unbekannte enthält, nämlich die Funktion $\phi(t)$. - Um $\phi(t)$ zu berechnen, m�ssen wir also die Differentialgleichung + Um $\phi(t)$ zu berechnen, müssen wir also die Differentialgleichung \begin{displaymath} \phi''(t) = -\frac{g}{l} \cdot \sin\phi(t) \end{displaymath} - l�sen. + lösen. \end{minipage}\hfill \begin{minipage}{5.5cm} \begin{center} @@ -3166,14 +3165,14 @@ \breath \begin{experts} - Diese Differentialgleichung l��t sich mit "`normalen"' Mitteln nicht l�sen, - daher verwendet man in der Praxis meistens die Kleinwinkeln�herung - $\sin\phi \approx \phi$ (f�r $\phi \ll 1$) - und l�st stattdessen die Differentialgleichung: + Diese Differentialgleichung läßt sich mit "`normalen"' Mitteln nicht lösen, + daher verwendet man in der Praxis meistens die Kleinwinkelnäherung + $\sin\phi \approx \phi$ (für $\phi \ll 1$) + und löst stattdessen die Differentialgleichung: \begin{displaymath} \phi''(t) = -\frac{g}{l} \cdot \phi(t) \end{displaymath} - F�r ein mit der Anfangsauslenkung $\phi(0)$ losgelassenes Pendel + Für ein mit der Anfangsauslenkung $\phi(0)$ losgelassenes Pendel lautet dann das Ergebnis: \begin{displaymath} \phi(t) = \phi(0)\cdot\cos(\omega t)\qquad\mbox{mit}\qquad\omega=\sqrt{\frac{g}{l}} @@ -3184,14 +3183,14 @@ \subsubsection{Das explizite Euler-Verfahren} - Um eine Differentialgleichung mit Hilfe eines Computers n�herungsweise \newterm{numerisch\/} zu l�sen, - stehen zahlreiche L�sungsverfahren zur Verf�gung. + Um eine Differentialgleichung mit Hilfe eines Computers näherungsweise \newterm{numerisch\/} zu lösen, + stehen zahlreiche Lösungsverfahren zur Verfügung. Im folgenden soll das einfachste dieser Verfahren, das \newterm{explizite Euler-Verfahren\/} (auch \newterm{Eulersches Polygonzugverfahren\/} genannt) vorgestellt werden. - Wir betrachten das System w�hrend eines kleinen Zeitintervalls $\Delta t$. - W�hrend dieses Zeitintervalls sind alle von der Zeit $t$ abh�ngigen Funktionen - -- z.\,B.\ Ort, Geschwindigkeit, Beschleunigung, Kraft -- n�herungsweise konstant. + Wir betrachten das System während eines kleinen Zeitintervalls $\Delta t$. + Während dieses Zeitintervalls sind alle von der Zeit $t$ abhängigen Funktionen + -- z.\,B.\ Ort, Geschwindigkeit, Beschleunigung, Kraft -- näherungsweise konstant. Bei konstanter Geschwindigkeit $v$ ist es einfach, aus dem Ort $x(t)$ zu Beginn des Zeitintervalls @@ -3208,33 +3207,33 @@ v(t + \Delta t) = v(t) + \Delta t \cdot a \end{displaymath} - Wenn wir dies in einer Schleife durchf�hren und jedesmal $t$ um $\Delta t$ erh�hen, - erhalten wir N�herungen f�r die Funktionen $x(t)$ und $v(t)$. + Wenn wir dies in einer Schleife durchführen und jedesmal $t$ um $\Delta t$ erhöhen, + erhalten wir Näherungen für die Funktionen $x(t)$ und $v(t)$. \breath - F�r das oben betrachtete Beispiel (Fadenpendel) - m�ssen wir in jedem Zeitintervall $\Delta t$ - zun�chst die tangentiale Beschleunigung $a(t)$ aus der tangentialen Kraft berechnen, + Für das oben betrachtete Beispiel (Fadenpendel) + müssen wir in jedem Zeitintervall $\Delta t$ + zunächst die tangentiale Beschleunigung $a(t)$ aus der tangentialen Kraft berechnen, die sich wiederum aus der momentanen Auslenkung $\phi(t)$ ergibt: \begin{displaymath} a = -g \cdot \sin\phi \end{displaymath} - Mit Hilfe dieser -- innerhalb des Zeitintervalls n�herungsweise konstanten -- Beschleunigung + Mit Hilfe dieser -- innerhalb des Zeitintervalls näherungsweise konstanten -- Beschleunigung berechnen wir die neue tangentiale Geschwindigkeit: \begin{displaymath} v(t + \Delta t) = v(t) + \Delta t \cdot a \end{displaymath} - Mit Hilfe dieser -- innerhalb des Zeitintervalls n�herungsweise konstanten -- Geschwindigkeit - berechnen wir schlie�lich die neue Winkelauslenkung $\phi$, - wobei wir einen kleinen Umweg �ber den Kreisbogen $x = l\cdot\phi$ machen: + Mit Hilfe dieser -- innerhalb des Zeitintervalls näherungsweise konstanten -- Geschwindigkeit + berechnen wir schließlich die neue Winkelauslenkung $\phi$, + wobei wir einen kleinen Umweg über den Kreisbogen $x = l\cdot\phi$ machen: \begin{displaymath} \phi(t + \Delta t) = \frac{x(t + \Delta t)}{l} = \frac{x(t) + \Delta t \cdot v}{l} = \phi(t) + \frac{\Delta t \cdot v}{l} \end{displaymath} - Ein C-Programm, das diese Berechnungen durchf�hrt (Datei: \file{pendulum-2.c}), enth�lt als Kernst�ck: + Ein C-Programm, das diese Berechnungen durchführt (Datei: \file{pendulum-2.c}), enthält als Kernstück: \goodbreak \begin{lstlisting} #define g 9.81 @@ -3257,30 +3256,30 @@ Jeder Aufruf der Funktion \lstinline{calc()} versetzt das Pendel um das Zeitintervall \lstinline{dt} in die Zukunft. - Es ist vom Verfahren her nicht notwendig, mit der Kleinwinkeln�herung $\sin\phi\approx\phi$ zu arbeiten. + Es ist vom Verfahren her nicht notwendig, mit der Kleinwinkelnäherung $\sin\phi\approx\phi$ zu arbeiten. Das Beispielprogramm \file{pendulum-3.c} illustriert, - welchen Unterschied die Kleinwinkeln�herung ausmacht. + welchen Unterschied die Kleinwinkelnäherung ausmacht. Wie gut arbeitet das explizite Euler-Verfahren? - Um dies zu untersuchen, l�sen wir eine Differentialgleichung, - deren exakte L�sung aus der Literatur bekannt ist, - n�mlich die Differentialgleichung mit Kleinwinkeln�herung. - Das Beispielprogramm \file{pendulum-4.c} vergleicht beide L�sungen miteinander. - F�r das betrachtete Beispiel ist die �bereinstimmung recht gut; - f�r Pr�zisionsberechnungen ist das explizite Euler-Verfahren jedoch nicht genau (und stabil) genug. - Hierf�r sei auf die Lehrveranstaltungen zur numerischen Mathematik verwiesen. + Um dies zu untersuchen, lösen wir eine Differentialgleichung, + deren exakte Lösung aus der Literatur bekannt ist, + nämlich die Differentialgleichung mit Kleinwinkelnäherung. + Das Beispielprogramm \file{pendulum-4.c} vergleicht beide Lösungen miteinander. + Für das betrachtete Beispiel ist die Übereinstimmung recht gut; + für Präzisionsberechnungen ist das explizite Euler-Verfahren jedoch nicht genau (und stabil) genug. + Hierfür sei auf die Lehrveranstaltungen zur numerischen Mathematik verwiesen. \subsubsection*{Bemerkung} - Das Beispielprogramm \file{pendulum-4.c} berechnet mit �berzeugender �bereinstimmung - dasselbe Ergebnis f�r die Auslenkung des Pendels auf zwei verschiedene Weisen: + Das Beispielprogramm \file{pendulum-4.c} berechnet mit überzeugender Übereinstimmung + dasselbe Ergebnis für die Auslenkung des Pendels auf zwei verschiedene Weisen: \begin{enumerate} \item - �ber eine Formel, die einen Cosinus enth�lt, + über eine Formel, die einen Cosinus enthält, \item mit Hilfe der Funktion \lstinline{calc()}, die nur Grundrechenarten verwendet. \end{enumerate} - Dies l��t die Natur der Verfahren erahnen, mit deren Hilfe es m�glich ist, + Dies läßt die Natur der Verfahren erahnen, mit deren Hilfe es möglich ist, Sinus, Cosinus und andere kompliziertere Funktionen nur unter Verwendung der Grundrechenarten zu berechnen. @@ -3288,31 +3287,31 @@ \subsection{Rekursion} - Aus der Mathematik ist das Beweisprinzip der \newterm{vollst�ndigen Induktion\/} bekannt: + Aus der Mathematik ist das Beweisprinzip der \newterm{vollständigen Induktion\/} bekannt: \begin{displaymath} \hspace*{4cm} \left. \begin{array}{r} - \mbox{Aussage gilt f�r $n = 1$}\\[2pt] - \mbox{Schlu� von $n - 1$ auf $n$} + \mbox{Aussage gilt für $n = 1$}\\[2pt] + \mbox{Schluß von $n - 1$ auf $n$} \end{array} \right\} - \mbox{Aussage gilt f�r alle $n\in\mathbb{N}$} + \mbox{Aussage gilt für alle $n\in\mathbb{N}$} \end{displaymath} - Wenn auf diese Weise die L�sbarkeit eines Problems bewiesen wurde, - ist es direkt m�glich, das Problem im Computer \emph{tats�chlich\/} zu l�sen, - n�mlich durch einen \newterm{rekursiven Algorithmus}. + Wenn auf diese Weise die Lösbarkeit eines Problems bewiesen wurde, + ist es direkt möglich, das Problem im Computer \emph{tatsächlich\/} zu lösen, + nämlich durch einen \newterm{rekursiven Algorithmus}. \breath - Ein klassisches Beispiel f�r ein rekursiv l�sbares Problem sind die T�rme von Hanoi: + Ein klassisches Beispiel für ein rekursiv lösbares Problem sind die Türme von Hanoi: \begin{itemize} \item - 64 Scheiben, 3 Pl�tze, immer 1 Scheibe verschieben + 64 Scheiben, 3 Plätze, immer 1 Scheibe verschieben \item Ziel: Turm verschieben \item - Es d�rfen nur kleinere Scheiben auf gr��eren liegen. + Es dürfen nur kleinere Scheiben auf größeren liegen. \end{itemize} \goodbreak @@ -3323,17 +3322,17 @@ Bildquelle: \url{http://commons.wikimedia.org/wiki/File:Tower\_of\_Hanoi.jpeg}\\ Urheber: \url{http://en.wikipedia.org/wiki/User:Evanherk}\\ - Lizenz: GNU FDL (Version 1.2 oder sp�ter) oder\\ + Lizenz: GNU FDL (Version 1.2 oder später) oder\\ Creative Commons Attribution-Share Alike (Version 3.0 Unported) \end{center} \goodbreak - Die rekursive L�sung des Problems lautet: + Die rekursive Lösung des Problems lautet: \begin{itemize} \item Wenn $n = 1$ ist, also nur eine Scheibe vorliegt, - l��t sich diese "`einfach so"' an den Zielplatz verschieben. + läßt sich diese "`einfach so"' an den Zielplatz verschieben. In diesem Fall sind wir direkt fertig. \item Wenn $n - 1$ Scheiben als verschiebbar vorausgesetzt werden, @@ -3344,7 +3343,7 @@ \end{itemize} \goodbreak - Dieser Algorithmus l��t sich unmittelbar in eine Programmiersprache �bersetzen: + Dieser Algorithmus läßt sich unmittelbar in eine Programmiersprache übersetzen: \begin{lstlisting} void verschiebe (int n, int start, int ziel) { @@ -3374,7 +3373,7 @@ \iffalse - \subsection{Wegfindungsalgorithmus f�r Roboterfahrzeug} + \subsection{Wegfindungsalgorithmus für Roboterfahrzeug} Siehe die Vortragsnotizen \file{ainf-20130117.txt},\\ die Beispielprogramme \file{text-parcour-\lstinline{*}.c}, @@ -3383,14 +3382,14 @@ \fi - \subsection{Aufwandsabsch�tzungen} + \subsection{Aufwandsabschätzungen} \subsubsection{Sortieralgorithmen} Am Beispiel von Sortieralgorithmen soll hier aufgezeigt werden, - wie man die L�sung eines Problems schrittweise effizienter gestalten kann. + wie man die Lösung eines Problems schrittweise effizienter gestalten kann. - Als Problem w�hlen wir das Sortieren eines Arrays (z.\,B.\ von Namen). + Als Problem wählen wir das Sortieren eines Arrays (z.\,B.\ von Namen). \begin{itemize} \item @@ -3400,21 +3399,21 @@ \item Bubblesort: \file{sort-5.c} \item - Bubblesort mit Abbruch in �u�erer Schleife: \file{sort-6.c} + Bubblesort mit Abbruch in äußerer Schleife: \file{sort-6.c} \item Bubblesort mit Abbruch in innerer Schleife: \file{sort-7.c}, \file{sort-7a.c}, \file{sort-7b.c} \item Vergleich mit Quicksort: \file{sort-8.c}, \file{sort-8a.c}, \file{sort-8b.c} \end{itemize} - Bei "`zuf�llig"' sortierten Ausgangsdaten arbeitet Quicksort schneller als Bubblesort. + Bei "`zufällig"' sortierten Ausgangsdaten arbeitet Quicksort schneller als Bubblesort. Wenn die Ausgangsdaten bereits nahezu sortiert sind, ist es umgekehrt. - Im jeweils ung�nstigsten Fall arbeiten beide Algorithmen gleich langsam. + Im jeweils ungünstigsten Fall arbeiten beide Algorithmen gleich langsam. \subsubsection{Landau-Symbole} Das Landau-Symbol $\mathcal{O}(g)$ mit einer Funktion $g(n)$ - steht f�r die \newterm{Ordnung\/} eines Algorithmus', + steht für die \newterm{Ordnung\/} eines Algorithmus', also die "`Geschwindigkeit"', mit der er arbeitet. Die Variable $n$ bezeichnet die Menge der Eingabedaten, hier also z.\,B.\ die Anzahl der Namen. @@ -3443,27 +3442,27 @@ \begin{itemize} \item - $\mathcal{O}(n)$ bedeutet, da� die Rechenzeit mit der Menge der Eingabedaten linear w�chst. - Um doppelt so viele Namen zu sortieren, ben�tigt das Programm doppelt so lange. + $\mathcal{O}(n)$ bedeutet, daß die Rechenzeit mit der Menge der Eingabedaten linear wächst. + Um doppelt so viele Namen zu sortieren, benötigt das Programm doppelt so lange. \item - $\mathcal{O}(n^2)$ bedeutet, da� die Rechenzeit mit der Menge der Eingabedaten quadratisch w�chst. - Um doppelt so viele Namen zu sortieren, ben�tigt das Programm viermal so lange. + $\mathcal{O}(n^2)$ bedeutet, daß die Rechenzeit mit der Menge der Eingabedaten quadratisch wächst. + Um doppelt so viele Namen zu sortieren, benötigt das Programm viermal so lange. \item - $\mathcal{O}(2^n)$ bedeutet, da� die Rechenzeit mit der Menge der Eingabedaten exponentiell w�chst. - F�r jeden Namen, der dazukommt, ben�tigt das Programm doppelt so lange. + $\mathcal{O}(2^n)$ bedeutet, daß die Rechenzeit mit der Menge der Eingabedaten exponentiell wächst. + Für jeden Namen, der dazukommt, benötigt das Programm doppelt so lange. Ein derartiges Programm gilt normalerweise als inakzeptabel langsam. \item - $\mathcal{O}(\log n)$ bedeutet, da� die Rechenzeit mit der Menge der Eingabedaten logarithmisch w�chst. - F�r jede Verdopplung der Namen ben�tigt das Programm nur einen Rechenschritt mehr. + $\mathcal{O}(\log n)$ bedeutet, daß die Rechenzeit mit der Menge der Eingabedaten logarithmisch wächst. + Für jede Verdopplung der Namen benötigt das Programm nur einen Rechenschritt mehr. Ein derartiges Programm gilt als "`traumhaft schnell"'. Dies wird jedoch nur selten erreicht. \item - $\mathcal{O}(1)$ bedeutet, da� die Rechenzeit von der Menge der Eingabedaten unabh�ngig ist: + $\mathcal{O}(1)$ bedeutet, daß die Rechenzeit von der Menge der Eingabedaten unabhängig ist: 1\,000\,000 Namen werden genau so schnell sortiert wie 10. - Dies ist nur in Ausnahmef�llen erreichbar. + Dies ist nur in Ausnahmefällen erreichbar. \item $\mathcal{O}(n \log n)$ liegt zwischen $\mathcal{O}(n)$ und $\mathcal{O}(n^2)$. @@ -3477,12 +3476,12 @@ \item Vorfaktoren interessieren nicht. - Wenn ein Code immer -- also unabh�ngig von den Eingabedaten -- zweimal ausgef�hrt wird, - beeinflu�t das die Ordnung des Algorithmus nicht. + Wenn ein Code immer -- also unabhängig von den Eingabedaten -- zweimal ausgeführt wird, + beeinflußt das die Ordnung des Algorithmus nicht. - Wenn ein Code immer -- also unabh�ngig von den Eingabedaten -- 1\,000\,000mal ausgef�hrt wird, - mag das Programm f�r kleine Datenmengen langsam erscheinen. - F�r die Ordnung interessiert jedoch nur das Verhalten f�r gro�e Datenmengen, + Wenn ein Code immer -- also unabhängig von den Eingabedaten -- 1\,000\,000mal ausgeführt wird, + mag das Programm für kleine Datenmengen langsam erscheinen. + Für die Ordnung interessiert jedoch nur das Verhalten für große Datenmengen, und dort kann dasselbe Programm durchaus schnell sein. \item Jede Schleife, die von $0$ bis $n$ geht, @@ -3491,7 +3490,7 @@ Eine Doppelschleife (Schleife innerhalb einer Schleife) hat demnach $\mathcal{O}(n^2)$. \goodbreak \item - Wenn sich die Grenzen einer Schleife st�ndig �ndern, nimmt man den Durschschnitt. + Wenn sich die Grenzen einer Schleife ständig ändern, nimmt man den Durschschnitt. Beispiel: \begin{lstlisting}[gobble=8] @@ -3499,22 +3498,22 @@ for (int j = 0; j < i; j++) ... \end{lstlisting} - Die �u�ere Schleife wird immer $n$-mal ausgef�hrt, + Die äußere Schleife wird immer $n$-mal ausgeführt, die innere \emph{im Durchschnitt\/} $\frac{n}{2}$-mal, was proportional zu $n$ ist. Zusammen ergibt sich $\mathcal{O}(n^2)$. \item - Bei Rekursionen mu� man mitz�hlen, wie viele Schleifen hinzukommen. + Bei Rekursionen muß man mitzählen, wie viele Schleifen hinzukommen. Bei Quicksort wird z.\,B.\ in jeder Rekursion - eine Schleife von $0$ bis $n$ (aufgeteilt) ausgef�hrt. + eine Schleife von $0$ bis $n$ (aufgeteilt) ausgeführt. Bei jeder Rekursion wird das Array "`normalerweise"' halbiert, d.\,h.\ die Rekursionstiefe ist proportional zum Logarithmus von $n$ (zur Basis 2). - Daraus ergibt sich die Ordnung $\mathcal{O}(n\log n)$ f�r den "`Normalfall"' des Quicksort. - (Im ung�nstigsten Fall kann sich auch $\mathcal{O}(n^2)$ ergeben.) + Daraus ergibt sich die Ordnung $\mathcal{O}(n\log n)$ für den "`Normalfall"' des Quicksort. + (Im ungünstigsten Fall kann sich auch $\mathcal{O}(n^2)$ ergeben.) \end{itemize} - F�r eine pr�zise Definition der Landau-Symbole siehe z.\,B.: + Für eine präzise Definition der Landau-Symbole siehe z.\,B.: \url{http://de.wikipedia.org/wiki/Landau-Symbole} \section{Hardwarenahe Programmierung} @@ -3530,7 +3529,7 @@ \item Basis: 10 \item - G�ltige Ziffern: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Gültige Ziffern: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 \end{itemize} \begin{verbatim} 137 137 @@ -3556,7 +3555,7 @@ \item Basis: 16 \item - G�ltige Ziffern: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F + Gültige Ziffern: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F \end{itemize} \begin{verbatim} 137 A380 @@ -3587,7 +3586,7 @@ \item Basis: 8 \item - G�ltige Ziffern: 0, 1, 2, 3, 4, 5, 6, 7 + Gültige Ziffern: 0, 1, 2, 3, 4, 5, 6, 7 \end{itemize} \begin{verbatim} 137 137 @@ -3618,14 +3617,14 @@ Schreibweise in C: \quad \texttt{0137} \end{itemize} - \subsubsection*{Rechner f�r beliebige Zahlensysteme: GNU bc} + \subsubsection*{Rechner für beliebige Zahlensysteme: GNU bc} \begin{lstlisting}[style=terminal] - $ �bc + $ ¡bc ibase=8 - 137� + 137¿ 95 - �obase=10 - 137 + 42� + ¡obase=10 + 137 + 42¿ 201 \end{lstlisting} \begin{picture}(0,0)(0.5,1.2) @@ -3641,12 +3640,12 @@ \end{picture}\vspace{-2ex} \goodbreak - \subsubsection*{Bin�rsystem} + \subsubsection*{Binärsystem} \begin{itemize} \item Basis: 2 \item - G�ltige Ziffern: 0, 1 + Gültige Ziffern: 0, 1 \end{itemize} \begin{verbatim} 110 110 @@ -3669,13 +3668,13 @@ \end{picture} \begin{itemize} \item - Bin�r-Zahlen erm�glichen es, elektronisch zu rechnen \dots + Binär-Zahlen ermöglichen es, elektronisch zu rechnen \dots \item und mehrere "`Ja/Nein"' (Bits) zu einer einzigen Zahl zusammenzufassen. \goodbreak \item \textbf{Oktal- und Hexadezimal-Zahlen lassen sich ziffernweise - in Bin�r-Zahlen umrechnen:} + in Binär-Zahlen umrechnen:} \end{itemize} \vspace*{-6mm} \begin{verbatim} @@ -3693,7 +3692,7 @@ \item[] Beispiel: $1101011_2 = 153_8 = 6{\rm B}_{16}$ \item[] - Anwendungsbeispiel: Oktal-Schreibweise f�r Unix-Zugriffsrechte\\ + Anwendungsbeispiel: Oktal-Schreibweise für Unix-Zugriffsrechte\\ \verb|-rw-r-----| $= 0\,110\,100\,000_2 = 640_8$ \qquad \verb|$ chmod 640 file.c|\\ \verb|-rwxr-x---| $= 0\,111\,101\,000_2 = 750_8$ \qquad \verb|$ chmod 750 subdir| \end{itemize} @@ -3704,9 +3703,9 @@ \item Basis: 256 \item - G�ltige Ziffern: 0 bis 255, getrennt durch Punkte + Gültige Ziffern: 0 bis 255, getrennt durch Punkte \item - Kompakte Schreibweise f�r Bin�rzahlen mit 32 Ziffern (Bits) + Kompakte Schreibweise für Binärzahlen mit 32 Ziffern (Bits) \end{itemize} \begin{verbatim} 192.168.0.1 @@ -3756,19 +3755,19 @@ \begin{picture}(0,0)(0,-0.25) \color{red} \put(2.5,1.0){\mbox{Bit gezielt setzen}} - \put(12.5,1.0){\mbox{Bit gezielt l�schen}} + \put(12.5,1.0){\mbox{Bit gezielt löschen}} \put(22.5,1.0){\mbox{Bit gezielt umklappen}} \end{picture} \begin{itemize} \item - Bits werden h�ufig von rechts und ab 0 numeriert (hier: 0 bis 7),\\ + Bits werden häufig von rechts und ab 0 numeriert (hier: 0 bis 7),\\ um die Maskenerzeugung mittels Schiebeoperatoren zu erleichtern. \item Die Bit-Operatoren (z.\,B.\ \verb|&| in C) wirken jeweils auf alle Bits der Zahlen. \hfill{\color{red}\verb|6 & 12 == 4|}\qquad\strut\\ Die logischen Operatoren (z.\,B.\ \verb|&&| in C) - pr�fen die Zahl insgesamt auf $\ne 0$. + prüfen die Zahl insgesamt auf $\ne 0$. \hfill{\color{red}\verb|6 && 12 == 1|}\qquad\strut\\ Nicht verwechseln! \end{itemize} @@ -3784,7 +3783,7 @@ \end{verbatim} \begin{picture}(0,0)(0,-0.25) \color{red} - \put(3.5,1.0){\mbox{Maske f�r Bit 2}} + \put(3.5,1.0){\mbox{Maske für Bit 2}} \put(12.5,1.0){\mbox{Bit gezielt setzen}} \end{picture}\vspace{-4ex} \begin{itemize} @@ -3804,8 +3803,8 @@ \end{verbatim} \begin{picture}(0,0)(0,-0.25) \color{red} - \put(3.5,1.0){\mbox{Maske zum L�schen von Bit 2 erzeugen}} - \put(22.5,1.0){\mbox{Bit gezielt l�schen}} + \put(3.5,1.0){\mbox{Maske zum Löschen von Bit 2 erzeugen}} + \put(22.5,1.0){\mbox{Bit gezielt löschen}} \end{picture}\vspace{-4ex} \begin{itemize} \item @@ -3824,7 +3823,7 @@ \end{verbatim} \begin{picture}(0,0)(0,-0.25) \color{red} - \put(2.5,1.0){\mbox{Maske f�r Bit 2}} + \put(2.5,1.0){\mbox{Maske für Bit 2}} \put(12.5,1.0){\mbox{Bit 2 isolieren}} \put(22.5,1.0){\mbox{in Zahl 0 oder 1 umwandeln}} \end{picture}\vspace{-4ex} @@ -3836,7 +3835,7 @@ \bigbreak - Beispiel: Netzmaske f�r 256 IP-Adressen + Beispiel: Netzmaske für 256 IP-Adressen \begin{verbatim} 192.168. 1.123 & 255.255.255. 0 @@ -3855,7 +3854,7 @@ \bigbreak - Beispiel: Netzmaske f�r 8 IP-Adressen + Beispiel: Netzmaske für 8 IP-Adressen \begin{verbatim} 192.168. 1.123 01111011 & 255.255.255.248 & 11111000 @@ -3874,15 +3873,15 @@ \subsection{I/O-Ports} - Es gibt drei grundlegende Mechanismen f�r die Kommunikation zwischen dem Prozessor - und einem externen Ger�t: + Es gibt drei grundlegende Mechanismen für die Kommunikation zwischen dem Prozessor + und einem externen Gerät: \begin{itemize} \item - �ber Output-Ports kann der Prozessor das Ger�t aktiv steuern, + Über Output-Ports kann der Prozessor das Gerät aktiv steuern, \item - �ber Input-Ports kann er es aktiv abfragen, + über Input-Ports kann er es aktiv abfragen, \item - und �ber Interrupts kann das externe Ger�t im Prozessor Aktivit�ten ausl�sen. + und über Interrupts kann das externe Gerät im Prozessor Aktivitäten auslösen. \end{itemize} \begin{center} @@ -3899,7 +3898,7 @@ \rput(2.12,1.4){\pnode{l0}} \rput(3.5,1.4){\pnode{m0}} \rput(8,0){\psframe[framearc=0.25](2,5)} - \rput(9,4.5){\makebox(0,0)[t]{\shortstack{externes\\Ger�t}}} + \rput(9,4.5){\makebox(0,0)[t]{\shortstack{externes\\Gerät}}} \rput(8.0,3.7){\pnode{p1}} \rput(7.88,3.3){\pnode{q1}} \rput(7.98,3.2){\pnode{r1}} @@ -3915,36 +3914,36 @@ \rput(2.2,3.8){\makebox(0,0)[lb]{Prozessor schreibt in Output-Port}} \rput(2.2,3.1){\makebox(0,0)[lt]{Prozessor liest Input-Port}} \ncline{->}{i1}{i0} - \rput(7.8,1.1){\makebox(0,0)[rb]{externes Ger�t ruft Interrupt auf}} + \rput(7.8,1.1){\makebox(0,0)[rb]{externes Gerät ruft Interrupt auf}} \end{pspicture} \end{pdfpic} \end{center} \setlength{\unitlength}{1cm} - Input- und Output-Ports, zusammengefa�t: I/O-Ports, - sind spezielle Speicherzellen, die mit einem externen Ger�t verbunden sind. + Input- und Output-Ports, zusammengefaßt: I/O-Ports, + sind spezielle Speicherzellen, die mit einem externen Gerät verbunden sind. \begin{itemize} \item - Ein in einen Output-Port geschriebener Wert bewirkt eine Spannungs�nderung in einer Leitung, - die zu einem externen Ger�t f�hrt. + Ein in einen Output-Port geschriebener Wert bewirkt eine Spannungsänderung in einer Leitung, + die zu einem externen Gerät führt. \item - Wenn ein externes Ger�t eine Spannung an eine Leitung anlegt, die zu einer Speicherzelle f�hrt, + Wenn ein externes Gerät eine Spannung an eine Leitung anlegt, die zu einer Speicherzelle führt, kann der Prozessor diese als Input-Port lesen. \end{itemize} Um z.\,B.\ auf einen Druck auf einen Taster zu warten, kann ein Program periodisch in einer Schleife einen Input-Port lesen - und die Schleife erst dann beenden, wenn der Wert f�r "`Taster gedr�ckt"' gelesen wurde. + und die Schleife erst dann beenden, wenn der Wert für "`Taster gedrückt"' gelesen wurde. - Diese Methode hei�t "`Busy Waiting"': Der Prozessor ist vollst�ndig mit Warten besch�ftigt. + Diese Methode heißt "`Busy Waiting"': Der Prozessor ist vollständig mit Warten beschäftigt. Wenn gleichzeitig noch andere Aktionen stattfinden sollen, - m�ssen diese in der Schleife mit ber�cksichtigt werden. + müssen diese in der Schleife mit berücksichtigt werden. \bigskip \goodbreak - Beispiel f�r die Verwendung eines Output-Ports: Roboter-Steuerung\\ + Beispiel für die Verwendung eines Output-Ports: Roboter-Steuerung\\ Datei: RP6Base/RP6Base\_Examples/RP6Examples\_20080915/RP6Lib/RP6base/RP6RobotBaseLib.c\\ Suchbegriff: setMotorDir \goodbreak @@ -3967,37 +3966,37 @@ Die Variable \verb|PORTC| ist ein Output-Port. Durch Manipulation einzelner Bits in dieser Variablen - �ndert sich die Spannung an den elektrischen "`Beinchen"' des Mikro-Controllers. + ändert sich die Spannung an den elektrischen "`Beinchen"' des Mikro-Controllers. Hierdurch wird die Beschaltung von Elektromotoren umgepolt. (Die Konstanten \verb|DIR_L| und \verb|DIR_R| sind "`Bitmasken"', - d.\,h.\ Zahlen, die in ihrer Bin�rdarstellung nur eine einzige $1$ und ansonsten Nullen haben. + d.\,h.\ Zahlen, die in ihrer Binärdarstellung nur eine einzige $1$ und ansonsten Nullen haben. Durch die Oder- und Und-Nicht-Operationen werden einzelne Bits in \verb|PORTC| auf $1$ bzw.\ $0$ gesetzt.) \bigskip - Die direkte Ansteuerung von I/O-Ports ist nur auf Mikro-Controllern �blich. - Auf Personal-Computern erfolgt die gesamte Ein- und Ausgabe �ber Betriebssystem-"`Treiber"'. + Die direkte Ansteuerung von I/O-Ports ist nur auf Mikro-Controllern üblich. + Auf Personal-Computern erfolgt die gesamte Ein- und Ausgabe über Betriebssystem-"`Treiber"'. Anwenderprogramme greifen dort i.\,d.\,R.\ nicht direkt auf I/O-Ports zu. \subsection{Interrupts} Ein Interrupt ist ein Unterprogramm, das nicht durch einen Befehl (\verb|call|), - sondern durch ein externes Ger�t (�ber ein Stromsignal) aufgerufen wird. + sondern durch ein externes Gerät (über ein Stromsignal) aufgerufen wird. - Damit dies funktionieret, mu� die Adresse, an der sich das Unterprogramm befindet, + Damit dies funktionieret, muß die Adresse, an der sich das Unterprogramm befindet, an einer jederzeit auffindbaren Stelle im Speicher hinterlegt sein. - Diese Stelle hei�t "`Interrupt-Vektor"'. + Diese Stelle heißt "`Interrupt-Vektor"'. Da ein Interrupt jederzeit erfolgen kann, hat das Hauptprogramm keine Chance, vor dem Aufruf die Registerinhalte zu sichern. - F�r Interrupt-Unterprogramme, sog.\ Interrupt-Handler, - ist es daher zwingend notwendig, s�mtliche Register vor Verwendung zu sichern - und hinterher zur�ckzuholen. + Für Interrupt-Unterprogramme, sog.\ Interrupt-Handler, + ist es daher zwingend notwendig, sämtliche Register vor Verwendung zu sichern + und hinterher zurückzuholen. \bigskip - Beispiel f�r die Verwendung eines Interrupts: Roboter-Steuerung\\ + Beispiel für die Verwendung eines Interrupts: Roboter-Steuerung\\ Datei: RP6Base/RP6Base\_Examples/RP6Examples\_20080915/RP6Lib/RP6base/RP6RobotBaseLib.c\\ Suchbegriff: ISR \begin{verbatim} @@ -4009,27 +4008,27 @@ }\end{verbatim} \begin{itemize} \item - Durch das Schl�sselwort \verb|ISR| anstelle von z.\,B.\ \verb|void| - teilen wir dem Compiler mit, da� es sich um einen Interrupt-Handler handelt, - so da� er entsprechenden Code zum Sichern der Registerinhalte einf�gt. + Durch das Schlüsselwort \verb|ISR| anstelle von z.\,B.\ \verb|void| + teilen wir dem Compiler mit, daß es sich um einen Interrupt-Handler handelt, + so daß er entsprechenden Code zum Sichern der Registerinhalte einfügt. \item Durch die Namensgebung \verb|INT0_vect| teilen wir dem Compiler mit, - da� er den Interrupt-Vektor Nr.\ 0 (also den ersten) + daß er den Interrupt-Vektor Nr.\ 0 (also den ersten) auf diesen Interrupt-Handler zeigen lassen soll. \end{itemize} - (Tats�chlich handelt es sich bei \verb|ISR| und \verb|INT0_vect| um Macros.) + (Tatsächlich handelt es sich bei \verb|ISR| und \verb|INT0_vect| um Macros.) - Die Schreibweise ist spezifisch f�r die Programmierung des Atmel AVR ATmega + Die Schreibweise ist spezifisch für die Programmierung des Atmel AVR ATmega unter Verwendung der GNU Compiler Collection (GCC). Bei Verwendung anderer Werkzeuge und/oder Prozessoren - kann dasselbe Programm v�llig anders aussehen. + kann dasselbe Programm völlig anders aussehen. Wie man Interrupt-Handler schreibt und wie man Interrupt-Vektoren setzt, ist ein wichtiger Bestandteil der Dokumentation der Entwicklungswerkzeuge. \bigskip Die so geschriebene Funktion wird immer dann aufgerufen, wenn die - Hardware den Interrupt Nr.\ 0 ausl�st. Wann das der Fall ist, h�ngt + Hardware den Interrupt Nr.\ 0 auslöst. Wann das der Fall ist, hängt von der Beschaltung ab. Im Falle des RP6 geschieht es dann, wenn ein Sensor an der linken Raupenkette einen schwarzen Streifen auf der Encoder-Scheibe registriert, also immer dann, wenn sich die @@ -4037,42 +4036,42 @@ hat. Jedesmal wenn sich die Raupenkette um einen Teilstrich weitergedreht hat, - werden also zwei Z�hler inkrementiert. - Wir k�nnen dies nutzen, um z.\,B.\ durch Auslesen des Z�hlers \verb|mleft_dist| - die zur�ckgelegte Entfernung zu messen. - (Die RP6-Bibliothek selbst stellt nur eine Zeit- und eine Geschwindigkeitsmessung zur Verf�gung.) + werden also zwei Zähler inkrementiert. + Wir können dies nutzen, um z.\,B.\ durch Auslesen des Zählers \verb|mleft_dist| + die zurückgelegte Entfernung zu messen. + (Die RP6-Bibliothek selbst stellt nur eine Zeit- und eine Geschwindigkeitsmessung zur Verfügung.) Wie dies konkret geschehen kann, sei im folgenden vorgestellt. \goodbreak - Methode 1: Ver�ndern des Interrupt-Handlers + Methode 1: Verändern des Interrupt-Handlers \begin{itemize} \item Da die Bibliothek \verb|RP6RobotBase| im Quelltext vorhanden ist, - k�nnen wir sie selbst �ndern und in den Interrupt-Handler - \verb|ISR (INT0_vect)| einen eigenen Z�hler f�r Sensor-Ticks einbauen. + können wir sie selbst ändern und in den Interrupt-Handler + \verb|ISR (INT0_vect)| einen eigenen Zähler für Sensor-Ticks einbauen. \item Wenn wir diesen zum Zeitpunkt A auf 0 setzen und zum Zeitpunkt B auslesen, erfahren wir, wieviele "`Ticks"' der Roboter dazwischen - zur�ckgelegt hat. + zurückgelegt hat. \end{itemize} - Methode 2: Verwenden eines vorhandenen Z�hlers + Methode 2: Verwenden eines vorhandenen Zählers \begin{itemize} \item - Tats�chlich enth�lt \verb|ISR (INT0_vect)| bereits zwei Z�hler, die - bei jedem Sensor-"`Tick"' hochgez�hlt werden: \verb|mleft_dist| und + Tatsächlich enthält \verb|ISR (INT0_vect)| bereits zwei Zähler, die + bei jedem Sensor-"`Tick"' hochgezählt werden: \verb|mleft_dist| und \verb|mleft_counter|. \item Einer davon (\verb|mleft_dist|) wird bei jedem \verb|move()| auf 0 - zur�ckgesetzt. F�r diesen Z�hler enth�lt \verb|RP6RobotBaseLib.h| + zurückgesetzt. Für diesen Zähler enthält \verb|RP6RobotBaseLib.h| einen "`undokumentierten"' Makro \verb|getLeftDistance()|, um ihn auszulesen. \item - Bei sorgf�ltiger Lekt�re von \verb|RP6RobotBaseLib.c| erkennt man, da� - es unproblematisch ist, den Z�hler vom Hauptprogramm aus auf 0 zu - setzen. (Dies ist jedoch mit Vorsicht zu genie�en: In einer - eventuellen Nachfolgeversion der Bibliothek mu� dies nicht mehr + Bei sorgfältiger Lektüre von \verb|RP6RobotBaseLib.c| erkennt man, daß + es unproblematisch ist, den Zähler vom Hauptprogramm aus auf 0 zu + setzen. (Dies ist jedoch mit Vorsicht zu genießen: In einer + eventuellen Nachfolgeversion der Bibliothek muß dies nicht mehr der Fall sein!) \end{itemize} @@ -4081,51 +4080,51 @@ \item Alternativ zur Verwendung des Interrupt-Handlers kann man auch von der eigenen Hauptschleife aus den Sensor periodisch abfragen - und bei jeder �nderung einen Z�hler hochz�hlen. + und bei jeder Änderung einen Zähler hochzählen. \item - Diese Methode hei�t "`Busy Waiting"'. Sie hat den Vorteil der - Einfachheit aber den Nachteil, da� der Prozessor "`in Vollzeit"' - damit besch�ftigt ist, einen Sensor abzufragen, und eventuelle + Diese Methode heißt "`Busy Waiting"'. Sie hat den Vorteil der + Einfachheit aber den Nachteil, daß der Prozessor "`in Vollzeit"' + damit beschäftigt ist, einen Sensor abzufragen, und eventuelle andere Aufgaben nur noch "`nebenher"' erledigen kann. \item - Wenn aus irgendwelchen Gr�nden der Interrupt-Mechanismus nicht - verwendet werden kann (z.B. weil der Prozessor �ber kein - Interrupt-Konzept verf�gt), k�nnten wir die Lichtschranke alternativ auch mit einem Input-Port + Wenn aus irgendwelchen Gründen der Interrupt-Mechanismus nicht + verwendet werden kann (z.B. weil der Prozessor über kein + Interrupt-Konzept verfügt), könnten wir die Lichtschranke alternativ auch mit einem Input-Port verdrahten und mittels Busy Waiting abfragen. - Dies funktioniert nur dann, wenn die Schleife wirklich regelm��ig den Sensor abfragt. - Sobald der Prozessor l�ngere Zeit mit anderen Dingen besch�ftigt ist, - k�nnen beim Busy Waiting Signale der Lichtschranke verlorengehen. + Dies funktioniert nur dann, wenn die Schleife wirklich regelmäßig den Sensor abfragt. + Sobald der Prozessor längere Zeit mit anderen Dingen beschäftigt ist, + können beim Busy Waiting Signale der Lichtschranke verlorengehen. Dieses Problem besteht nicht bei Verwendung von Interrupts. \end{itemize} \subsection{volatile-Variable} - Im C-Quelltext f�llt auf, da� die Z�hler-Variablen \verb|mleft_dist| und \verb|mleft_counter| + Im C-Quelltext fällt auf, daß die Zähler-Variablen \verb|mleft_dist| und \verb|mleft_counter| als \verb|volatile|\break\verb|uint16_t mleft_counter| bzw.\ \verb|volatile uint16_t mleft_dist| deklariert sind anstatt einfach nur als \verb|uint16_t mleft_counter| und \verb|uint16_t mleft_dist|. - Das Schl�sselwort \verb|volatile| teilt dem C-Compiler mit, - da� eine Variable immer im Speicher (RAM) aufbewahrt werden mu� + Das Schlüsselwort \verb|volatile| teilt dem C-Compiler mit, + daß eine Variable immer im Speicher (RAM) aufbewahrt werden muß und nicht in einem Prozessorregister zwischengespeichert werden darf. Dies ist deswegen wichtig, weil jederzeit ein Interrupt erfolgen - kann, der den Wert der Variablen im Speicher ver�ndert. Wenn im - Hauptprogramm alle "`�berfl�ssigen"' Speicherzugriffe wegoptimiert - wurden, erf�hrt es nichts von der �nderung. + kann, der den Wert der Variablen im Speicher verändert. Wenn im + Hauptprogramm alle "`überflüssigen"' Speicherzugriffe wegoptimiert + wurden, erfährt es nichts von der Änderung. - Entsprechendes gilt f�r I/O-Ports: + Entsprechendes gilt für I/O-Ports: Wenn ein Programm einen Wert in einen Output-Port schreiben oder aus einem Input-Port lesen soll, - ist es wichtig, da� der Speicherzugriff auch tats�chlich stattfindet. + ist es wichtig, daß der Speicherzugriff auch tatsächlich stattfindet. \subsection{Software-Interrupts} - Manche Prozessoren verf�gen �ber einen Befehl, um Interrupts "`k�nstlich"' auszul�sen. + Manche Prozessoren verfügen über einen Befehl, um Interrupts "`künstlich"' auszulösen. Das Betriebssystem MS-DOS verwendet derartige Aufrufe anstelle von "`normalen"' Unterprogrammaufrufen, - um Programmen Funktionen zur Verf�gung zu stellen. + um Programmen Funktionen zur Verfügung zu stellen. \bigskip \goodbreak @@ -4134,7 +4133,7 @@ \medskip - \verb| |MS-DOS-Version f�r FASM (gek�rzt)\hspace{3cm} Unix-Version f�r GCC (gek�rzt) + \verb| |MS-DOS-Version für FASM (gekürzt)\hspace{3cm} Unix-Version für GCC (gekürzt) \begin{verbatim} hello db 'Hello, world', 10, 13, '$' hello: .string "Hello, world!\n" @@ -4147,27 +4146,27 @@ Die MS-DOS-Version ruft den Interrupt Nr.\ 33 (hexadezimal: 21) auf: \verb| int 21h|.\\ Die Unix-Version verwendet stattdessen einen normalen Unterprogrammaufruf: \verb| call printf|. \item - Die MS-DOS-Version �bergibt Parameter in Prozessorregistern:\\ - Die Konstante \verb|09h| im \verb|ah|-Register w�hlt die Funktion "`Textausgabe"' aus;\\ - das \verb|dx|-Register enth�lt einen Zeiger auf den Text. + Die MS-DOS-Version übergibt Parameter in Prozessorregistern:\\ + Die Konstante \verb|09h| im \verb|ah|-Register wählt die Funktion "`Textausgabe"' aus;\\ + das \verb|dx|-Register enthält einen Zeiger auf den Text. - Die Unix-Version benutzt den Stack zur �bergabe des Parameters: \verb| pushl $hello|.\\ + Die Unix-Version benutzt den Stack zur Übergabe des Parameters: \verb| pushl $hello|.\\ (\verb|$hello| ist ein Zeiger auf den Text.) \item Obwohl beide Programme auf demselben Prozessor laufen, unterscheiden sich die Sprachdialekte der beiden Assember FASM und GCC erheblich voneinander.\\ - (Reihenfolge der Operanden umgekehrt, Suffix \verb|l| f�r "`long"', Pr�fix \verb|$| f�r Konstanten, \dots) + (Reihenfolge der Operanden umgekehrt, Suffix \verb|l| für "`long"', Präfix \verb|$| für Konstanten, \dots) \end{itemize} Derartige "`Software-Interrupts"' verursachen Probleme, - sobald ein Ger�t den Interrupt f�r seinen eigentlichen Zweck verwendet. - MS-Windows verwendet -- au�er zur Emulation von MS-DOS -- keine Software-Interrupts mehr. + sobald ein Gerät den Interrupt für seinen eigentlichen Zweck verwendet. + MS-Windows verwendet -- außer zur Emulation von MS-DOS -- keine Software-Interrupts mehr. \bigskip - (Ein sehr �hnlicher Mechanismus wird von modernen Betriebssystemen weiterhin f�r Systemaufrufe genutzt. - Hier geht es darum, den �bergang von potentiell unsicherem Code in Anwenderprogrammen - zum vertrauensw�rdigen Code des Betriebssystems zu kontrollieren. F�r Details siehe:\\ + (Ein sehr ähnlicher Mechanismus wird von modernen Betriebssystemen weiterhin für Systemaufrufe genutzt. + Hier geht es darum, den Übergang von potentiell unsicherem Code in Anwenderprogrammen + zum vertrauenswürdigen Code des Betriebssystems zu kontrollieren. Für Details siehe:\\ http://de.wikipedia.org/wiki/Software-Interrupt, http://de.wikipedia.org/wiki/Systemaufruf) \subsection{Byte-Reihenfolge -- Endianness} @@ -4175,8 +4174,8 @@ \subsubsection{Konzept} Beim Speichern von Werten, - die gr��er sind als die kleinste adressierbare Einheit\\ - (= Speicherzelle oder Speicherwort, h�ufig 1 Byte), werden mehrere Speicherworte belegt. + die größer sind als die kleinste adressierbare Einheit\\ + (= Speicherzelle oder Speicherwort, häufig 1 Byte), werden mehrere Speicherworte belegt. Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen \begin{displaymath} @@ -4187,8 +4186,8 @@ in zwei 8-Bit-Speicherzellen gespeichert werden: \begin{center} \begin{tabular}{|c|c|l}\cline{1-2} - \raisebox{-1pt}{04} & \raisebox{-1pt}{03} & \strut Big-Endian, "`gro�es Ende zuerst"', \\\cline{1-2} - \multicolumn{2}{c}{} & f�r Menschen leichter lesbar \\ + \raisebox{-1pt}{04} & \raisebox{-1pt}{03} & \strut Big-Endian, "`großes Ende zuerst"', \\\cline{1-2} + \multicolumn{2}{c}{} & für Menschen leichter lesbar \\ \multicolumn{3}{c}{} \\[-5pt]\cline{1-2} \raisebox{-1pt}{03} & \raisebox{-1pt}{04} & \strut Little-Endian, "`kleines Ende zuerst"', \\\cline{1-2} \multicolumn{2}{c}{} & bei Additionen effizienter \\ @@ -4196,23 +4195,23 @@ \end{tabular} \end{center} Welche Konvention man verwendet, ist letztlich Geschmackssache - und h�ngt von der verwendeten Hardware (Prozessor) und Software ab. + und hängt von der verwendeten Hardware (Prozessor) und Software ab. Man spricht hier von der "`Endianness"' (Byte-Reihenfolge) der Hardware bzw.\ der Software. Im Kontext des Datenaustausches ist es wichtig, - sich auf eine einheitliche Endianness zu verst�ndigen. - Dies gilt insbesondere f�r: + sich auf eine einheitliche Endianness zu verständigen. + Dies gilt insbesondere für: \begin{itemize} \item Dateiformate \item - Daten�bertragung + Datenübertragung \end{itemize} \goodbreak \subsubsection{Dateiformate} - Als Beispiel f�r Dateiformate, in denen die Reihenfolge der Bytes + Als Beispiel für Dateiformate, in denen die Reihenfolge der Bytes in 16- und 32-Bit-Zahlen spezifiziert ist, seien hier Audio-Formate genannt: \begin{itemize} \item @@ -4221,46 +4220,46 @@ Au-Dateien (\verb|.au|): Big-Endian \goodbreak \item - �ltere AIFF-Dateien (\verb|.aiff|): Big-Endian + ältere AIFF-Dateien (\verb|.aiff|): Big-Endian \item neuere AIFF-Dateien (\verb|.aiff|): Little-Endian \end{itemize} - Insbesondere ist es bei AIFF-Dateien wichtig, zu pr�fen, + Insbesondere ist es bei AIFF-Dateien wichtig, zu prüfen, um welche Variante es sich handelt, anstatt sich auf eine bestimmte Byte-Reihenfolge zu verlassen. - Bei Dateiformaten mit variabler Endianness ist es sinnvoll und �blich, + Bei Dateiformaten mit variabler Endianness ist es sinnvoll und üblich, die Endianness durch eine Kennung anzuzeigen. - Dies geschieht h�ufig am Anfang der Datei (im "`Vorspann"' -- "`Header"'). + Dies geschieht häufig am Anfang der Datei (im "`Vorspann"' -- "`Header"'). \bigbreak Als weiteres Beispiel seien zwei Monochrom-Grafik-Formate genannt. - Hier steht jedes Bit f�r einen schwarzen bzw.\ wei�en Bildpunkt, + Hier steht jedes Bit für einen schwarzen bzw.\ weißen Bildpunkt, daher spielt die Reihenfolge der Bits in den Bytes eine entscheidende Rolle. (Diese Grafik-Formate sind Ihnen bereits aus der Vorlesung "`Angewandte Informatik"' bekannt.) \begin{itemize} \item - PBM-Dateien: Big-Endian, MSB first -- die h�chstwertige Bin�rziffer ist im Bild links + PBM-Dateien: Big-Endian, MSB first -- die höchstwertige Binärziffer ist im Bild links \item - XBM-Dateien: Little-Endian, LSB first -- die h�chstwertige Bin�rziffer ist im Bild rechts + XBM-Dateien: Little-Endian, LSB first -- die höchstwertige Binärziffer ist im Bild rechts \end{itemize} MSB/LSB = most/least significant bit - Achtung: Die Abk�rzungen "`MSB/LSB"' werden manchmal auch f�r "`most/least significant \emph{byte}"' verwendet. + Achtung: Die Abkürzungen "`MSB/LSB"' werden manchmal auch für "`most/least significant \emph{byte}"' verwendet. Im konkreten Fall ist es ratsam, die verwendete Byte- und Bit-Reihenfolge genau zu recherchieren - bzw.\ pr�zise zu dokumentieren. + bzw.\ präzise zu dokumentieren. % \bigbreak % % Weiteres Beispiel: Textdateien im Format "`UTF-16"'. -% Hier stehen jeweils zwei aufeinanderfolgende Bytes f�r eine 16-Bit-Zahl. +% Hier stehen jeweils zwei aufeinanderfolgende Bytes für eine 16-Bit-Zahl. % Am Dateianfang steht stets der Wert $65279 = \verb|FEFF|_{16}$ \dots - \subsubsection{Daten�bertragung} + \subsubsection{Datenübertragung} - Bei der �bertragung von Daten �ber Leitungen + Bei der Übertragung von Daten über Leitungen spielt sowohl die Reihenfolge der Bits in den Bytes ("`MSB first"' bzw.\ "`LSB first"') - als auch die Reihenfolge der Bytes in den �bertragenen Zahlen ("`Big-/Little-Endian"') eine Rolle. + als auch die Reihenfolge der Bytes in den übertragenen Zahlen ("`Big-/Little-Endian"') eine Rolle. Als Beispiele seien genannt: \begin{itemize} @@ -4271,36 +4270,36 @@ \item USB: beides - Um �bertragungsfehler erkennen zu k�nnen, werden im USB-Protokoll - bestimmte Werte einmal gem�� der MSB-first- und einmal gem�� der LSB-first-Konvention - �bertragen und anschlie�end auf Gleichheit gepr�ft. + Um Übertragungsfehler erkennen zu können, werden im USB-Protokoll + bestimmte Werte einmal gemäß der MSB-first- und einmal gemäß der LSB-first-Konvention + übertragen und anschließend auf Gleichheit geprüft. \medskip \item Ethernet: LSB first \item TCP/IP (Internet): Big-Endian \end{itemize} - Insbesondere gilt f�r die �bertragung z.\,B.\ einer 32-Bit-Zahl �ber das Internet, - da� die vier Bytes von links nach rechts (Big-Endian) �bertragen werden, + Insbesondere gilt für die Übertragung z.\,B.\ einer 32-Bit-Zahl über das Internet, + daß die vier Bytes von links nach rechts (Big-Endian) übertragen werden, die acht Bits innerhalb jedes Bytes hingegen von rechts nach links (LSB first). \subsection{Speicherausrichtung -- Alignment} Ein 32-Bit-Prozessor kann auf eine 32-Bit-Variable effizienter zugreifen, wenn die Speicheradresse der Variablen ein Vielfaches von 32 Bits, also 4 Bytes ist. - Eine Variable, auf die dies zutrifft, hei�t "`korrekt im Speicher ausgerichtet"' ("`aligned"'). + Eine Variable, auf die dies zutrifft, heißt "`korrekt im Speicher ausgerichtet"' ("`aligned"'). "`Effizienter"' kann bedeuten, - da� Maschinenbefehle zum Arbeiten mit den Variablen schneller abgearbeitet werden. + daß Maschinenbefehle zum Arbeiten mit den Variablen schneller abgearbeitet werden. Es kann aber auch bedeuten, - da� der Prozessor gar keine direkte Bearbeitung von inkorrekt ausgerichteten Variablen erlaubt. + daß der Prozessor gar keine direkte Bearbeitung von inkorrekt ausgerichteten Variablen erlaubt. In diesem Fall bedeutet eine inkorrekte Speicherausrichtung, - da� f�r jede Operation mit der Variablen anstelle eines einzelnen Maschinenbefehls - ein kleines Programm aufgerufen werden mu�. + daß für jede Operation mit der Variablen anstelle eines einzelnen Maschinenbefehls + ein kleines Programm aufgerufen werden muß. \bigskip - Um zu verstehen, welche Konsequenzen dies f�r die Arbeit mit Rechnern hat, + Um zu verstehen, welche Konsequenzen dies für die Arbeit mit Rechnern hat, betrachten wir die folgenden Variablen (in C-Schreibweise): \begin{verbatim} @@ -4308,7 +4307,7 @@ uint16_t b; uint8_t c;\end{verbatim} - Die Anordnung dieser Variablen im Speicher k�nnte z.\,B.\ folgenderma�en aussehen: + Die Anordnung dieser Variablen im Speicher könnte z.\,B.\ folgendermaßen aussehen: \begin{quote} \newcommand{\bup}{\begin{picture}(0,0)\put(-0.1,0.2){\mbox{b}}\end{picture}} @@ -4325,8 +4324,8 @@ \end{tabular} \end{quote} - Ein optimierender Compiler wird f�r eine korrekte Ausrichtung der Variablen \verb|b| sorgen, - beispielsweise durch Auff�llen mit unbenutzten Speicherzellen: + Ein optimierender Compiler wird für eine korrekte Ausrichtung der Variablen \verb|b| sorgen, + beispielsweise durch Auffüllen mit unbenutzten Speicherzellen: \begin{quote} \newcommand{\bup}{\begin{picture}(0,0)\put(-0.1,0.2){\mbox{b}}\end{picture}} @@ -4343,9 +4342,9 @@ \end{tabular} \end{quote} - Alternativ ist es dem Compiler auch m�glich, + Alternativ ist es dem Compiler auch möglich, die korrekte Ausrichtung durch "`Umsortieren"' der Variablen herzustellen - und dadurch "`L�cher"' zu vermeiden: + und dadurch "`Löcher"' zu vermeiden: \begin{quote} \newcommand{\bup}{\begin{picture}(0,0)\put(-0.1,0.2){\mbox{b}}\end{picture}} @@ -4363,19 +4362,19 @@ \end{quote} Fazit: Man kann sich als Programmierer nicht immer darauf verlassen, - da� die Variablen im Speicher in einer spezifischen Weise angeordnet sind. + daß die Variablen im Speicher in einer spezifischen Weise angeordnet sind. In vielen existierenden Programmen geschieht dies dennoch. Diese Programme sind fehlerhaft. - Dort kann es z.\,B.\ passieren, da� nach einem Upgrade des Compilers + Dort kann es z.\,B.\ passieren, daß nach einem Upgrade des Compilers schwer lokalisierbare Fehler auftreten. \bigskip \goodbreak - Entsprechende �berlegungen gelten f�r 64-Bit- und 16-Bit-Prozessoren. - Die Gr��e der Variablen, aufgerundet auf die n�chste Zweierpotenz, gibt eine Ausrichtung vor. - Die Registerbreite des Prozessors markiert die gr��te Ausrichtung, die noch ber�cksichtigt werden mu�. + Entsprechende Überlegungen gelten für 64-Bit- und 16-Bit-Prozessoren. + Die Größe der Variablen, aufgerundet auf die nächste Zweierpotenz, gibt eine Ausrichtung vor. + Die Registerbreite des Prozessors markiert die größte Ausrichtung, die noch berücksichtigt werden muß. Bei 8-Bit-Prozessoren stellt sich die Frage nach der Speicherausrichtung normalerweise nicht, weil die kleinste adressierbare Einheit eines Speichers selten kleiner als 8 Bits ist. @@ -4383,7 +4382,7 @@ Beispiele: \begin{itemize} \item - Eine 64-Bit-Variable auf einem 64-Bit-Prozessor mu� auf 64 Bits ausgerichtet sein. + Eine 64-Bit-Variable auf einem 64-Bit-Prozessor muß auf 64 Bits ausgerichtet sein. \item Eine 32-Bit-Variable auf einem 64-Bit-Prozessor braucht nur auf 32 Bits ausgerichtet zu sein. \item @@ -4393,28 +4392,28 @@ \end{itemize} Bei der Definition von Datenformaten tut man gut daran, - die Ausrichtung der Daten von vorneherein zu ber�cksichtigen, - um auf m�glichst vielen -- auch zuk�nftigen -- Prozessoren - eine m�glichst effiziente Bearbeitung zu erm�glichen. + die Ausrichtung der Daten von vorneherein zu berücksichtigen, + um auf möglichst vielen -- auch zukünftigen -- Prozessoren + eine möglichst effiziente Bearbeitung zu ermöglichen. Wenn ich beispielsweise ein Dateiformat definiere, in dem 128-Bit-Werte vorkommen, ist es sinnvoll, diese innerhalb der Datei auf 128 Bits (16 Bytes) auszurichten, - auch wenn mein eigener Rechner nur �ber einen 64-Bit-Prozessor verf�gt. + auch wenn mein eigener Rechner nur über einen 64-Bit-Prozessor verfügt. - \section{Erg�nzungen und Ausblicke} + \section{Ergänzungen und Ausblicke} \subsection{String-Operationen} - Die Include-Datei \file{string.h} deklariert eine Sammlung n�tzlicher Funktionen - f�r den Umgang mit Strings (\lstinline{char *}). + Die Include-Datei \file{string.h} deklariert eine Sammlung nützlicher Funktionen + für den Umgang mit Strings (\lstinline{char *}). In den Sortierprogrammen \file{sort-\lstinline{*}.c} wurde davon bereits die Funktion \lstinline{strcmp()} verwendet. - \lstinline{strcmp (foo, bar)} liefert den Wert \lstinline{-1} zur�ck, + \lstinline{strcmp (foo, bar)} liefert den Wert \lstinline{-1} zurück, wenn der String \lstinline{foo} alphabetisch kleiner ist als der String \lstinline{bar}, - sie liefert \lstinline{0} zur�ck, wenn beide Strings gleich sind, - und sie liefert \lstinline{1} zur�ck, wenn \lstinline{foo} alphabetisch gr��er ist als \lstinline{bar}. + sie liefert \lstinline{0} zurück, wenn beide Strings gleich sind, + und sie liefert \lstinline{1} zurück, wenn \lstinline{foo} alphabetisch größer ist als \lstinline{bar}. \subsection{Dateien} @@ -4424,79 +4423,79 @@ die in eine Datei \file{hello.txt} anstelle der Standardausgabe schreibt. \begin{experts} - Auch die Standardausgabe ist �brigens eine "`normale"' Datei. - \lstinline{printf (foo)} ist nur eine Abk�rzung f�r \lstinline{fprintf (stdout, foo)}. + Auch die Standardausgabe ist übrigens eine "`normale"' Datei. + \lstinline{printf (foo)} ist nur eine Abkürzung für \lstinline{fprintf (stdout, foo)}. \end{experts} \item \file{fread-1.c} zeigt, wie man zeilenweise aus einer Textdatei liest. - Dieses Programm pr�ft nicht, ob die Datei tats�chlich - erfolgreich ge�ffnet werden konnte. - Dies hat zur Folge, da� im Fehlerfall versucht wird, + Dieses Programm prüft nicht, ob die Datei tatsächlich + erfolgreich geöffnet werden konnte. + Dies hat zur Folge, daß im Fehlerfall versucht wird, auf einen \lstinline{NULL}-Pointer zuzugreifen -- also einen Absturz. Das Programm ist somit grob fehlerhaft. \item \file{fread-2.c} zeigt, wie es besser geht: - Wenn die Datei nicht ge�ffnet werden kann, + Wenn die Datei nicht geöffnet werden kann, wird eine Fehlermeldung ausgegeben und das Programm kontrolliert beendet. Es besteht aber weiterhin ein Problem: Die Fehlerursache "`Datei nicht gefunden"' wurde lediglich geraten. Sie kann falsch sein und somit, anstatt hilfreich zu sein, - den Benutzer in die Irre f�hren. + den Benutzer in die Irre führen. Auch dieses Programm ist also noch grob fehlerhaft. \item \file{fread-3.c} zeigt die korrekte Vorgehensweise: Mit Hilfe der Systemvariablen \lstinline{errno} (deklariert in \file{errno.h}) und der Funktion \lstinline{strerror()} (deklariert in \file{string.h}) - wird gepr�ft, welcher Fehler vorliegt. + wird geprüft, welcher Fehler vorliegt. Anhand dieser Information wird dann die vom Betriebssystem - f�r diesen Fall vorgesehene Fehlermeldung ausgegeben. + für diesen Fall vorgesehene Fehlermeldung ausgegeben. \end{itemize} - Dieselben �berlegungen zur Fehlerbehandlung gelten nat�rlich auch - f�r das �ffnen einer Datei zum Schreiben, hier also auch f�r \file{fhello.c}. + Dieselben Überlegungen zur Fehlerbehandlung gelten natürlich auch + für das Öffnen einer Datei zum Schreiben, hier also auch für \file{fhello.c}. \subsection{Objektorientierte Programmierung} In Abschnitt \ref{Strukturen} haben wir Funktionen geschrieben, die eine \lstinline{struct}-Variable bearbeiten. - Das Konzept, Funktionen m�glichst eng mit den Daten zu b�ndeln, + Das Konzept, Funktionen möglichst eng mit den Daten zu bündeln, die sie bearbeiten, ist ein wichtiger Aspekt der \newterm{objektorientierten Programmierung}. Das Beispielprogramm \file{dates-1.c} illustriert einen Satz von Funktionen zur Bearbeitung von \file{date}-Objekten, sog.\ \newterm{Methoden}. Methoden erwarten als "`standardisierten"' ersten Parameter das Objekt: einen Zeiger \lstinline{this} auf ein C-\lstinline{struct}. - Wenn der Satz von Funktionen vollst�ndig ist, ist es nicht mehr n�tig, + Wenn der Satz von Funktionen vollständig ist, ist es nicht mehr nötig, direkt auf die Datenfelder des \lstinline{struct}s zuzugreifen. Dies nennt man \newterm{Kapselung}. Viele Sprachen (z.\,B.\ C++ als Weiterentwicklung von C) - unterst�tzen objektorientierte Programmierung durch Sprachelemente. + unterstützen objektorientierte Programmierung durch Sprachelemente. In diesen Sprachen ist der \lstinline{this}-Parameter i.\,d.\,R.\ nicht sichtbar, sondern implizit. Das Beispielprogramm \file{dates-2.c} geht noch einen Schritt weiter und verankert im Objekt Zeiger auf Methoden -- sog.\ \newterm{virtuelle Methoden}. - Dieses mit den Callback-Funktionen vergleichbare Konzept erm�glicht es, + Dieses mit den Callback-Funktionen vergleichbare Konzept ermöglicht es, verschiedenen, miteinander "`verwandten"' Objekten Methoden mit gleichen Namen zuzuordnen, die sich aber unterschiedlich verhalten. Dies nennt man \newterm{Polymorphie}. Wenn die o.\,a.\ "`Verwandschaft"' von Objekten darin besteht, - da� das eine Objekt ein anderes erweitert (zus�tzliche Datenfelder und Methoden, - evtl.\ ver�nderte, \newterm{�berschriebene\/} virtuelle Methoden), + daß das eine Objekt ein anderes erweitert (zusätzliche Datenfelder und Methoden, + evtl.\ veränderte, \newterm{überschriebene\/} virtuelle Methoden), spricht man von \newterm{Vererbung}. Das Objekt, das erweitert wird, ist der \newterm{Vorfahre\/} des anderen Objekts. - In Sprachen wie C, die keine Sprachelemente f�r objektorientierte Programmierung - zur Verf�gung stellen, kann dennoch Objektorientierung "`zu Fu�"' erreicht werden. + In Sprachen wie C, die keine Sprachelemente für objektorientierte Programmierung + zur Verfügung stellen, kann dennoch Objektorientierung "`zu Fuß"' erreicht werden. Die GUI-Bibliothek GTK+, - die urspr�nglich f�r das Bildverarbeitungsprogramm GIMP entwickelt wurde, + die ursprünglich für das Bildverarbeitungsprogramm GIMP entwickelt wurde, inzwischen aber in zahlreichen Programmen (z.\,B.\ Mozilla Firefox) ihren Dienst tut, funktioniert auf diese Weise.