Skip to content
Snippets Groups Projects
Commit 1d299a6f authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Vorbereitung 10.12.2020

parent f9b9b263
Branches
No related tags found
No related merge requests found
Showing
with 2435 additions and 0 deletions
#include <stdio.h>
#include <string.h>
void insert_into_string (char src, char *target, int pos)
{
int len = strlen (target);
for (int i = pos; i < len; i++)
target[i+1] = target[i];
target[pos] = src;
}
int main (void)
{
char test[100] = "Hochshule Bochum";
insert_into_string ('c', test, 5);
printf ("%s\n", test);
return 0;
}
#include <string.h>
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
File added
% hp-20201210.pdf - Lecture Slides on Low-Level Programming
% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020 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/>.
% README: Parameter des Hauptprogramms, String-Operationen
\documentclass[10pt,t]{beamer}
\usepackage{pgslides}
\usepackage{pdftricks}
\usepackage{tikz}
\begin{psinputs}
\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage[T1]{fontenc}
\usepackage{helvet}
\renewcommand*\familydefault{\sfdefault}
\usepackage{pstricks,pst-grad}
\end{psinputs}
\title{Hardwarenahe Programmierung}
\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski}
\date{10.\ Dezember 2020}
\begin{document}
\maketitleframe
\nosectionnonumber{\inserttitle}
\begin{frame}
\shownosectionnonumber
\begin{itemize}
\item[\textbf{1}] \textbf{Einführung}
\hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
\item[\textbf{2}] \textbf{Einführung in C}
\begin{itemize}
\vspace*{-\smallskipamount}
\item[\dots]
\item[2.12] Strukturen
\item[2.13] Dateien und Fehlerbehandlung
\color{medgreen}
\item[2.14] Parameter des Hauptprogramms
\item[2.15] String-Operationen
\end{itemize}
\item[\textbf{3}] \textbf{Bibliotheken}
\item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
\item[\textbf{5}] \textbf{Algorithmen}
\vspace*{-\smallskipamount}
\item[\textbf{\dots}]
\end{itemize}
\end{frame}
\setcounter{section}{1}
\section{Einführung in C}
\setcounter{subsection}{12}
\subsection{Strukturen}
\begin{frame}[fragile]
\showsubsection
\begin{minipage}[b]{6cm}
\begin{lstlisting}[gobble=6]
¡#include <stdio.h>
typedef struct
{
char day, month;
int year;
}
date;
int main (void)
{
date today = { 3, 12, 2020 };
printf ("%d.%d.%d\n", today.day, today.month, today.year);
return 0;
}¿
\end{lstlisting}
\end{minipage}
\end{frame}
\begin{frame}[fragile]
\showsubsection
% \vspace*{0.9mm}
\begin{minipage}[b]{6cm}
\begin{lstlisting}[gobble=6]
¡#include <stdio.h>
typedef struct
{
char day, month;
int year;
}
date;
void set_date (date *d)
{
(*d).day = 3;
(*d).month = 12;
(*d).year = 2020;
}¿
\end{lstlisting}
\end{minipage}%
\begin{minipage}[b]{6cm}
\begin{lstlisting}[gobble=6]
¡int main (void)
{
date today;
set_date (&today);
printf ("%d.%d.%d\n", today.day,
today.month, today.year);
return 0;
}¿
\end{lstlisting}
\end{minipage}
\end{frame}
\begin{frame}[fragile]
\showsubsection
% \vspace*{0.9mm}
\begin{minipage}[b]{6cm}
\begin{lstlisting}[gobble=6]
¡#include <stdio.h>
typedef struct
{
char day, month;
int year;
}
date;
void set_date (date *d)
{
d->day = 3;
d->month = 12;
d->year = 2020;
}¿
\end{lstlisting}
\end{minipage}%
\begin{minipage}[b]{6cm}
\hspace*{-1cm}%
\lstinline{foo->bar}
ist Abkürzung für
\lstinline{(*foo).bar}
\bigskip
\visible<2->{%
\hspace*{-1cm}%
Eine Funktion, die mit einem \lstinline{struct} arbeitet,\\
\hspace*{-1cm}%
kann man eine \newterm{Methode\/} des \lstinline{struct} nennen.}
\bigskip
\bigskip
\begin{lstlisting}[gobble=6]
¡int main (void)
{
date today;
set_date (&today);
printf ("%d.%d.%d\n", today.day,
today.month, today.year);
return 0;
}¿
\end{lstlisting}
\end{minipage}
\end{frame}
\subsection{Dateien und Fehlerbehandlung}
\begin{frame}[fragile]
\showsubsection
\vspace*{-0.2925cm}
\begin{minipage}[t]{6cm}
\begin{onlyenv}<1>
\begin{lstlisting}[gobble=8]
¡#include <stdio.h>
int main (void)
{
FILE *f = fopen ("fhello.txt", "w");
fprintf (f, "Hello, world!\n");
fclose (f);
return 0;
}¿
\end{lstlisting}
\end{onlyenv}
\begin{onlyenv}<2>
\begin{lstlisting}[gobble=8]
¡#include <stdio.h>
int main (void)
{
FILE *f = fopen ("fhello.txt", "w");
if (f)
{
fprintf (f, "Hello, world!\n");
fclose (f);
}
return 0;
}¿
\end{lstlisting}
\end{onlyenv}
\begin{onlyenv}<3>
\begin{lstlisting}[gobble=8]
¡#include <stdio.h>
#include <errno.h>
int main (void)
{
FILE *f = fopen ("fhello.txt", "w");
if (f)
{
fprintf (f, "Hello, world!\n");
fclose (f);
}
else
fprintf (stderr, "error #%d\n", errno);
return 0;
}¿
\end{lstlisting}
\end{onlyenv}
\begin{onlyenv}<4>
\begin{lstlisting}[gobble=8]
¡#include <stdio.h>
#include <errno.h>
#include <string.h>
int main (void)
{
FILE *f = fopen ("fhello.txt", "w");
if (f)
{
fprintf (f, "Hello, world!\n");
fclose (f);
}
else
{
char *msg = strerror (errno);
fprintf (stderr, "%s\n", msg);
}
return 0;
}¿
\end{lstlisting}
\vspace*{-1cm}
\end{onlyenv}
\begin{onlyenv}<5->
\begin{lstlisting}[gobble=8]
¡#include <stdio.h>
#include <errno.h>
#include <er¡ror.h>
int main (void)
{
FILE *f = fopen ("fhello.txt", "w");
if (!f)
error (1, errno, "cannot open file");
fprintf (f, "Hello, world!\n");
fclose (f);
return 0;
}
\end{lstlisting}
\end{onlyenv}
\end{minipage}\pause\hspace*{-1.5cm}%
\begin{minipage}[t]{8.5cm}
\bigskip
\only<3->{\bigskip}
\begin{itemize}
\item
Wenn die Datei nicht geöffnet werden kann,\\
gibt \lstinline{fopen()} den Wert \lstinline{NULL} zurück.
\pause
\medskip
\item
\addtolength{\leftskip}{1cm}
Die globale Variable \lstinline{int errno}\\
enthält dann die Nummer des Fehlers.\\
Benötigt: \lstinline{#include <errno.h>}
\pause
\medskip
\only<5->{\bigskip}
\item
Die Funktion \lstinline{strerror()} wandelt \lstinline{errno}\\
in einen Fehlermeldungstext um.\\
Benötigt: \lstinline{#include <string.h>}
\pause
\medskip
\item
\addtolength{\leftskip}{-1.5cm}
Die Funktion \lstinline{error()} gibt eine Fehlermeldung aus\\
und beendet das Programm.\\
Benötigt: \lstinline{#include <er¡¿ror.h>}
\pause
\medskip
\item
\textbf{Niemals Fehler einfach ignorieren!}
\end{itemize}
\addtolength{\leftskip}{0.5cm}
\end{minipage}
\end{frame}
\subsection{Parameter des Hauptprogramms}
\begin{frame}[fragile]
\showsubsection
\begin{lstlisting}
#include <stdio.h>
int main (int argc, char **argv)
{
printf ("argc = %d\n", argc);
for (int i = 0; i < argc; i++)
printf ("argv[%d] = \"%s\"\n", i, argv[i]);
return 0;
}
\end{lstlisting}
\end{frame}
\begin{frame}[fragile]
\showsubsection
\begin{lstlisting}
#include <stdio.h>
int main (int argc, char **argv)
{
printf ("argc = %d\n", argc);
for (int i = 0; *argv; i++, argv++)
printf ("argv[%d] = \"%s\"\n", i, *argv);
return 0;
}
\end{lstlisting}
\end{frame}
\subsection{String-Operationen}
\begin{frame}[fragile]
\showsubsection
\vspace*{-0.4cm}
\begin{lstlisting}
#include <stdio.h>
#include <string.h>
int main (void)
{
char hello[] = "Hello, world!\n";
printf ("%s\n", hello);
printf ("%zd\n", strlen (hello));
printf ("%s\n", hello + 7);
printf ("%zd\n", strlen (hello + 7));
hello[5] = 0;
printf ("%s\n", hello);
printf ("%zd\n", strlen (hello));
return 0;
}
\end{lstlisting}
\vspace*{-1cm}
\end{frame}
\begin{frame}[fragile]
\showsubsection
\vspace*{-0.4cm}
\begin{lstlisting}
#include <stdio.h>
#include <string.h>
int main (void)
{
char *anton = "Anton";
char *zacharias = "Zacharias";
printf ("%d\n", strcmp (anton, zacharias));
printf ("%d\n", strcmp (zacharias, anton));
printf ("%d\n", strcmp (anton, anton));
char buffer[100] = "Huber ";
strcat (buffer, anton);
printf ("%s\n", buffer);
return 0;
}
\end{lstlisting}
\vspace*{-1cm}
\end{frame}
\begin{frame}[fragile]
\showsubsection
\vspace*{-0.4cm}
\begin{lstlisting}
#include <stdio.h>
#include <string.h>
int main (void)
{
char buffer[100] = "";
sprintf (buffer, "Die Antwort lautet: %d", 42);
printf ("%s\n", buffer);
char *answer = strstr (buffer, "Antwort");
printf ("%s\n", answer);
printf ("found at: %zd\n", answer - buffer);
return 0;
}
\end{lstlisting}
\vspace*{-1cm}
\end{frame}
\begin{frame}[fragile]
\showsubsection
\vspace*{-0.4cm}
\begin{lstlisting}
#include <stdio.h>
#include <string.h>
int main (void)
{
char buffer[100] = "";
snprintf (buffer, 100, "Die Antwort lautet: %d", 42);
printf ("%s\n", buffer);
char *answer = strstr (buffer, "Antwort");
printf ("%s\n", answer);
printf ("found at: %zd\n", answer - buffer);
return 0;
}
\end{lstlisting}
\end{frame}
\begin{frame}
\showsection
Sprachelemente weitgehend komplett
\bigskip
Es fehlen:
\begin{itemize}
\item
Ergänzungen (z.\,B.\ ternärer Operator, \lstinline{union}, \lstinline{unsigned}, \lstinline{volatile})
\item
Bibliotheksfunktionen (z.\,B.\ \lstinline{malloc()})
\arrowitem
werden eingeführt, wenn wir sie brauchen
\bigskip
\item
Konzepte (z.\,B.\ rekursive Datenstrukturen, Klassen selbst bauen)
\arrowitem
werden eingeführt, wenn wir sie brauchen, oder:
\arrowitem
Literatur\\[\smallskipamount]
(z.\,B.\ Wikibooks: C-Programmierung,\\
Dokumentation zu Compiler und Bibliotheken)
\bigskip
\item
Praxiserfahrung
\arrowitem
Übung und Praktikum: nur Einstieg
\arrowitem
selbständig arbeiten
\end{itemize}
\end{frame}
\nosectionnonumber{\inserttitle}
\begin{frame}
\shownosectionnonumber
\begin{itemize}
\item[\textbf{1}] \textbf{Einführung}
\hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
\item[\textbf{2}] \textbf{Einführung in C}
\begin{itemize}
\vspace*{-\smallskipamount}
\item[\dots]
\item[2.12] Strukturen
\item[2.13] Dateien und Fehlerbehandlung
\color{medgreen}
\item[2.14] Parameter des Hauptprogramms
\item[2.15] String-Operationen
\end{itemize}
\item[\textbf{3}] \textbf{Bibliotheken}
\begin{itemize}
\color{red}
\item[3.1] Der Präprozessor
\item[3.2] Bibliotheken einbinden
\item[3.3] Bibliotheken verwenden
\item[3.4] Projekt organisieren: make
\vspace*{-\smallskipamount}
\item[\dots]
\end{itemize}
\vspace*{-\smallskipamount}
\item[\textbf{4}] \textbf{Algorithmen}
\item[\textbf{5}] \textbf{Hardwarenahe Programmierung}
\vspace*{-\smallskipamount}
\item[\textbf{\dots}]
\end{itemize}
\end{frame}
\section{Bibliotheken}
\subsection{Der Präprozessor}
\begin{frame}[fragile]
\showsection
\showsubsection
\lstinline{#include}: %\pause:
Text einbinden
\begin{itemize}
% \pause
\item
\lstinline{#include <stdio.h>}: Standard-Verzeichnisse -- Standard-Header
% \pause
\item
\lstinline{#include "answer.h"}: auch aktuelles Verzeichnis -- eigene Header
\end{itemize}
\pause
\bigskip
\lstinline{#define VIER 4}: Text ersetzen lassen -- Konstante definieren
\begin{itemize}
\pause
\item
Kein Semikolon!
\pause
\item
Berechnungen in Klammern setzen:\\
\lstinline{#define VIER (2 + 2)}
\pause
\item
Konvention: Großbuchstaben
\end{itemize}
\end{frame}
\subsection{Bibliotheken einbinden}
\begin{frame}[fragile]
\showsection
\showsubsection
Inhalt der Header-Datei: externe Deklarationen
% \pause
\smallskip
\lstinline{extern int answer (void);}
% \pause
\smallskip
\lstinline{extern int printf (__const char *__restrict __format, ...);}
% \pause
\bigskip
Funktion wird "`anderswo"' definiert
\begin{itemize}
% \pause
\item
separater C-Quelltext: mit an \lstinline[style=terminal]{gcc} übergeben
% \pause
\item
Zusammenfügen zu ausführbarem Programm durch den \newterm{Linker}
% \pause
\item
vorcompilierte Bibliothek: \lstinline[style=terminal]{-lfoo}\\
% \pause
= Datei \file{libfoo.a} in Standard-Verzeichnis
\end{itemize}
\end{frame}
\subsection{Bibliothek verwenden (Beispiel: GTK+)}
\begin{frame}[fragile]
\showsubsection
\begin{itemize}
\item
\lstinline{#include <gtk/gtk.h>}
\pause
\smallskip
\item
Mit \lstinline[style=cmd]{pkg-config --cflags --libs} erfährt man,\\
welche Optionen und Bibliotheken man an \lstinline[style=cmd]{gcc}
übergeben muß\alt<4->{.}{:}
\pause
\begin{onlyenv}<3>
\begin{lstlisting}[style=terminal,gobble=10]
$ ¡pkg-config --cflags --libs gtk+-3.0¿
-pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-
atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1
.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/
include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/inc
lude/cairo -I/usr/include/pango-1.0 -I/usr/include/harf
buzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I
/usr/include/cairo -I/usr/include/pixman-1 -I/usr/inclu
de/freetype2 -I/usr/include/libpng16 -I/usr/include/gdk
-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/glib
-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lgtk
-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcai
ro-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject
-2.0 -lglib-2.0
\end{lstlisting}
\vspace*{-3cm}
\end{onlyenv}
\pause
\arrowitem
Compiler-Aufruf:
\begin{onlyenv}<4>
\begin{lstlisting}[style=terminal,gobble=10]
$ ¡gcc -Wall -O hello-gtk.c -pthread -I/usr/include/gtk-
3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-sp
i-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-g
nu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/inclu
de/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pa
ngo-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.
0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/in
clude/pixman-1 -I/usr/include/freetype2 -I/usr/include/
libpng16 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/l
ibpng16 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux
-gnu/glib-2.0/include -lgtk-3 -lgdk-3 -lpangocairo-1.0
-lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pix
buf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0-o hello-gtk¿
\end{lstlisting}
\vspace*{-2cm}
\end{onlyenv}
\begin{onlyenv}<5->
\begin{lstlisting}[style=terminal,gobble=10]
$ ¡gcc -Wall -O hello-gtk.c $(pkg-config --cflags --libs)
-o hello-gtk¿
\end{lstlisting}
\end{onlyenv}
\begin{onlyenv}<5>
\begin{picture}(0,0)(0.3,0.3)
\color{red}
\put(6.6,-0.6){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(3,1.5);}}}
\put(6.3,-0.7){\makebox(0,0)[t]{\shortstack{\strut Optionen:\\
\strut u.\,a.\ viele Include-Verzeichnisse:\\
\lstinline[style=cmd]{-I/usr/include/gtk-3.0}}}}
\put(10.0,-2.1){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(1.5,3);}}}
\put(10.3,-2.2){\makebox(0,0)[t]{\shortstack{\strut Bibliotheken:\\
\strut u.\,a.\ \lstinline[style=cmd]{-lgtk-3 -lcairo}}}}
\end{picture}
\end{onlyenv}
\pause
\pause
\item
Auf manchen Plattformen kommt es auf die Reihenfolge an:
\begin{lstlisting}[style=terminal,gobble=8]
$ ¡gcc -Wall -O $(pkg-config --cflags) \
hello-gtk.c $(pkg-config --libs) \
-o hello-gtk¿
\end{lstlisting}
(Backslash = "`Es geht in der nächsten Zeile weiter."')
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\showsubsection
Selbst geschriebene Funktion übergeben: \newterm{Callback}
\bigskip
\begin{lstlisting}[xleftmargin=1em]
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
/* Zeichenbefehle */
...
return FALSE;
}
...
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
\end{lstlisting}
\medskip
\begin{itemize}
\arrowitem
GTK+ ruft immer dann, wenn es etwas zu zeichnen gibt,\\
die Funktion \lstinline{draw} auf.
\end{itemize}
\pause
\begin{picture}(0,0)(-0.07,0.2)
\color{red}
\put(5.3,4.8){\makebox(0,0)[bl]{\tikz{\draw[-latex](0,0)--(1.90,1.15);}}}
\put(5.0,4.7){\makebox(0,0)[t]{\shortstack{\strut repräsentiert den\\
\strut Bildschirm, auf den\\
\strut gezeichnet werden soll}}}
\pause
\put(9.7,5.1){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-0.2,0.85);}}}
\put(9.7,5.0){\makebox(0,0)[t]{\shortstack{\strut optionale Zusatzinformationen\\
\strut für draw(), typischerweise\\
\strut ein Zeiger auf ein struct}}}
\put(10.0,3.5){\makebox(0,0)[tl]{\tikz{\draw[-latex](0,0)--(0.6,-1.25);}}}
\end{picture}
\end{frame}
\begin{frame}[fragile]
\showsubsection
Selbst geschriebene Funktion übergeben: \newterm{Callback}
\bigskip
\begin{lstlisting}[xleftmargin=1em]
gboolean timer (GtkWidget *widget)
{
/* Rechenbefehle */
...
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
...
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
\end{lstlisting}
\medskip
\begin{itemize}
\arrowitem
GTK+ ruft nach 50 Millisekunden
die Funktion \lstinline{timer} auf.
\end{itemize}
\pause
\begin{picture}(0,0)(-0.07,0.2)
\color{red}
\put(9.7,6.7){\makebox(0,0)[t]{\shortstack{\strut Dieser Bereich soll\\
\strut neu gezeichnet werden.}}}
\put(9.7,5.7){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.6,-0.8);}}}
\pause
\put(4.3,3.2){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-0.7,0.6);}}}
\put(4.3,3.1){\makebox(0,0)[t]{\shortstack{\strut In weiteren 50 Millisekunden soll\\
\strut die Funktion erneut aufgerufen werden.}}}
\pause
\put(9.3,2.9){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-3.3,0.9);}}}
\put(9.8,2.8){\makebox(0,0)[t]{\shortstack{\strut Explizite Typumwandlung\\
\strut eines Zeigers (später)}}}
\end{picture}
\end{frame}
\section{Algorithmen}
\subsection{Differentialgleichungen}
%\begin{frame}[fragile]
%
% \showsection
% \showsubsection
%
% \textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung}
%
% \begin{center}
% \includegraphics[width=\textwidth,trim={0cm 7cm 0cm 0cm},clip]{../20181112/photo-20181112-173737.jpg}
% \end{center}
%
%\end{frame}
\begin{frame}[fragile]
\showsection
\showsubsection
\textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung}
\strut\hfill
\begin{minipage}{2.5cm}
\vspace*{0.6cm}
\begin{align*}
x'(t) &= v_x(t) \\[0.65cm]
y'(t) &= v_y(t) \\[0.75cm]
v_x'(t) &= 0 \\[0.65cm]
v_y'(t) &= -g
\end{align*}
\vspace*{0.0cm}
\end{minipage}%
\only<1>{\hspace*{9.49cm}}\strut
\only<2->{\hfill$\Rightarrow$\hfill}%
\begin{onlyenv}<2-8>
\begin{minipage}{8.3cm}
\begin{align*}
x(t) &= \int v_x(t)\,dt
\visible<4->{= \int v_{0x}\,dt}
\visible<5->{= x_0 + v_{0x}\cdot t}\\[\medskipamount]
y(t) &= \int v_y(t)\,dt
\visible<7->{= \int v_{0y} - g\cdot t\,dt}
\visible<8->{= y_0 + v_{0y}\cdot t
- {\textstyle\frac12}gt^2}\\[\bigskipamount]
v_x(t) &= \int 0\,dt
\visible<3->{= v_{0x}} \\[\medskipamount]
v_y(t) &= \int -g\,dt
\visible<6->{= v_{0y} - g\cdot t}
\end{align*}
\end{minipage}%
\end{onlyenv}%
\begin{onlyenv}<9->
\begin{minipage}{3.5cm}
\vspace*{0.5cm}
\begin{lstlisting}[gobble=8,xleftmargin=0.5em]
¡x += vx * dt;¿
\end{lstlisting}
\vspace{0.75cm}
\begin{lstlisting}[gobble=8,xleftmargin=0.5em]
¡y += vy * dt;¿
\end{lstlisting}
\vspace{0.90cm}
\begin{lstlisting}[gobble=8,xleftmargin=0.5em]
¡vx += 0 * dt;¿
\end{lstlisting}
\vspace{0.75cm}
\begin{lstlisting}[gobble=8,xleftmargin=0.5em]
¡vy += -g * dt;¿
\end{lstlisting}
\end{minipage}%
\begin{minipage}{5.13cm}
Siehe: \file{gtk-13.c}
\end{minipage}
\end{onlyenv}%
\hfill\strut
\end{frame}
\begin{frame}[fragile]
\showsection
\showsubsection
\textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung}
\medskip
\textbf{Beispiel 2: Mathematisches Pendel}
\vspace*{-2\bigskipamount}
\begin{picture}(0,0)
\put(8,-6.5){\includegraphics{pendulum.pdf}}
\end{picture}
\begin{eqnarray*}
\varphi'(t) &=& \omega(t) \\[\smallskipamount]
\omega'(t) &=& -\frac{g}{l}\cdot\sin\varphi(t)\hspace*{7.1cm}
\end{eqnarray*}
\vspace*{-1.5\medskipamount}
\begin{itemize}
\item
Von Hand (analytisch):\\
Lösung raten (Ansatz), Parameter berechnen
\item
Mit Computer (numerisch):\\
Eulersches Polygonzugverfahren
\end{itemize}
\smallskip
\begin{lstlisting}[gobble=0]
phi += dt * omega;
omega += - dt * g / l * sin (phi);
\end{lstlisting}
\pause
\bigskip
\textbf{Beispiel 3: Weltraum-Simulation}
Praktikumsaufgabe
\vspace*{-1cm}
\end{frame}
\setcounter{section}{2}
\section{Bibliotheken}
\setcounter{subsection}{3}
\subsection{Projekt organisieren: make}
\begin{frame}[fragile]
\showsubsection
\begin{itemize}
\item
\only<4->{explizite und implizite} Regeln
\begin{onlyenv}<2>
\smallskip
\begin{lstlisting}[language=make,gobble=10]
philosophy: philosophy.o answer.o
gcc philosophy.o answer.o -o philosophy
answer.o: answer.c answer.h
gcc -Wall -O answer.c -c
philosophy.o: philosophy.c answer.h
gcc -Wall -O philosophy.c -c
\end{lstlisting}
\end{onlyenv}
\begin{onlyenv}<4>
\smallskip
\begin{lstlisting}[language=make,gobble=10]
TARGET = philosophy
OBJECTS = philosophy.o answer.o
HEADERS = answer.h
CFLAGS = -Wall -O
$(TARGET): $(OBJECTS)
gcc $(OBJECTS) -o $(TARGET)
%.o: %.c $(HEADERS)
gcc $(CFLAGS) $< -c
clean:
rm -f $(OBJECTS) $(TARGET)
\end{lstlisting}
\end{onlyenv}
\item
Makros
\begin{onlyenv}<3>
\smallskip
\begin{lstlisting}[language=make,gobble=10]
TARGET = philosophy
OBJECTS = philosophy.o answer.o
HEADERS = answer.h
CFLAGS = -Wall -O
$(TARGET): $(OBJECTS)
gcc $(OBJECTS) -o $(TARGET)
answer.o: answer.c $(HEADERS)
gcc $(CFLAGS) answer.c -c
philosophy.o: philosophy.c $(HEADERS)
gcc $(CFLAGS) philosophy.c -c
clean:
rm -f $(OBJECTS) $(TARGET)
\end{lstlisting}
\vspace*{-1cm}
\end{onlyenv}
\begin{onlyenv}<5->
\smallskip
\arrowitem
3 Sprachen: C, Präprozessor, make
\end{onlyenv}
\end{itemize}
\end{frame}
\iffalse
\nosectionnonumber{\inserttitle}
\begin{frame}
\shownosectionnonumber
\begin{itemize}
\item[\textbf{1}] \textbf{Einführung}
\hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp.git}}}
\item[\textbf{2}] \textbf{Einführung in C}
\item[\textbf{3}] \textbf{Bibliotheken}
\begin{itemize}
\color{medgreen}
\item[3.1] Der Präprozessor
\item[3.2] Bibliotheken einbinden
\item[3.3] Bibliotheken verwenden
\color{red}
\item[3.4] Projekt organisieren: make
\end{itemize}
\item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
\begin{itemize}
\color{red}
\item[4.1] Bit-Operationen
\item[4.2] I/O-Ports
\item[4.3] Interrupts
\vspace*{-0.1cm}
\item[\dots]
\end{itemize}
\item[\textbf{5}] \textbf{Algorithmen}
\begin{itemize}
\color{medgreen}
\item[5.1] Differentialgleichungen
\color{black}
\vspace*{-0.1cm}
\item[\dots]
\end{itemize}
\item[\textbf{\dots}]
% \item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
% \item[\textbf{5}] \textbf{Algorithmen}
% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke}
\end{itemize}
\vspace*{-1cm}
\end{frame}
\nosectionnonumber{\inserttitle}
\begin{frame}
\shownosectionnonumber
\begin{itemize}
\item[\textbf{1}] \textbf{Einführung}
\hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
\item[\textbf{2}] \textbf{Einführung in C}
\begin{itemize}
\vspace*{-\smallskipamount}
\item[\dots]
\item[2.10] Zeiger
\color{medgreen}
\item[2.11] Arrays und Strings
\item[2.12] Strukturen
\item[2.13] Dateien und Fehlerbehandlung
\color{red}
\item[2.14] Parameter des Hauptprogramms
\item[2.15] String-Operationen
\end{itemize}
\item[\textbf{3}] \textbf{Bibliotheken}
% \begin{itemize}
% \color{red}
% \item[3.1] Der Präprozessor
% \item[3.2] Bibliotheken einbinden
% \item[3.3] Bibliotheken verwenden
% \vspace*{-\smallskipamount}
% \item[\dots]
%% \item[3.4] Projekt organisieren: make
% \end{itemize}
% \vspace*{-\smallskipamount}
\item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
\begin{itemize}
\color{red}
\item[4.1] Bit-Operationen
\item[4.2] I/O-Ports
\color{black}
\item[4.3] Interrupts
\vspace*{-0.1cm}
\item[\dots]
\end{itemize}
\item[\textbf{5}] \textbf{Algorithmen}
\item[\textbf{\dots}]
\end{itemize}
\end{frame}
\setcounter{section}{3}
\section{Hardwarenahe Programmierung}
\subsection{Bit-Operationen}
\subsubsection{Zahlensysteme}
\begin{frame}[fragile]
\showsection
\vspace*{-\smallskipamount}
\showsubsection
\vspace*{-\medskipamount}
\showsubsubsection
\begin{tabular}{rlrl}
Basis & Name & Beispiel & Anwendung \\[\smallskipamount]
2 & Binärsystem & 1\,0000\,0011 & Bit-Operationen \\
8 & Oktalsystem & \lstinline,0403, & Dateizugriffsrechte (Unix) \\
10 & Dezimalsystem & \lstinline,259, & Alltag \\
16 & Hexadezimalsystem & \lstinline,0x103, & Bit-Operationen \\
256 & (keiner gebräuchlich) & 0.0.1.3 & IP-Adressen (IPv4)
\end{tabular}
\bigskip
\begin{itemize}
\item
Computer rechnen im Binärsystem.
\item
Für viele Anwendungen (z.\,B.\ I/O-Ports, Grafik, \dots) ist es notwendig,\\
Bits in Zahlen einzeln ansprechen zu können.
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\showsubsubsection
\begin{tabular}{rlrlrc}
\qquad 000 & \bf 0 \hspace*{1.5cm} & 0000 & \bf 0 & \quad 1000 & \bf 8\\
001 & \bf 1 & 0001 & \bf 1 & 1001 & \bf 9\\
010 & \bf 2 & 0010 & \bf 2 & 1010 & \bf A\\
011 & \bf 3 & 0011 & \bf 3 & 1011 & \bf B\\[\smallskipamount]
100 & \bf 4 & 0100 & \bf 4 & 1100 & \bf C\\
101 & \bf 5 & 0101 & \bf 5 & 1101 & \bf D\\
110 & \bf 6 & 0110 & \bf 6 & 1110 & \bf E\\
111 & \bf 7 & 0111 & \bf 7 & 1111 & \bf F\\
\end{tabular}
\medskip
\begin{itemize}
\item
Oktal- und Hexadezimalzahlen lassen sich ziffernweise\\
in Binär-Zahlen umrechnen.
\item
Hexadezimalzahlen sind eine Kurzschreibweise für Binärzahlen,\\
gruppiert zu jeweils 4 Bits.
\item
Oktalzahlen sind eine Kurzschreibweise für Binärzahlen,\\
gruppiert zu jeweils 3 Bits.
\item
Trotz Taschenrechner u.\,ä.\ lohnt es sich,\\
die o.\,a.\ Umrechnungstabelle \textbf{auswendig} zu kennen.
\end{itemize}
\end{frame}
\subsubsection{Bit-Operationen in C}
\begin{frame}[fragile]
\showsubsubsection
\begin{tabular}{lll}
C-Operator & Verknüpfung & Anwendung \\[\smallskipamount]
\lstinline,&, & Und & Bits gezielt löschen \\
\lstinline,|, & Oder & Bits gezielt setzen \\
\lstinline,^, & Exklusiv-Oder & Bits gezielt invertieren \\
\lstinline,~, & Nicht & Alle Bits invertieren \\[\smallskipamount]
\lstinline,<<, & Verschiebung nach links & Maske generieren \\
\lstinline,>>, & Verschiebung nach rechts & Bits isolieren
\end{tabular}
\bigskip
Numerierung der Bits: von rechts ab 0
\medskip
\begin{tabular}{ll}
Bit Nr.\ 3 auf 1 setzen: &
\lstinline,a |= 1 << 3;, \\
Bit Nr.\ 4 auf 0 setzen: &
\lstinline,a &= ~(1 << 4);, \\
Bit Nr.\ 0 invertieren: &
\lstinline,a ^= 1 << 0;,
\end{tabular}
\smallskip
~~Abfrage, ob Bit Nr.\ 1 gesetzt ist:\quad
\lstinline{if (a & (1 << 1))}
\end{frame}
\begin{frame}[fragile]
\showsubsubsection
C-Datentypen für Bit-Operationen:
\smallskip\par
\lstinline{#include <stdint.h>}
\medskip\par
\begin{tabular}{lllll}
& 8 Bit & 16 Bit & 32 Bit & 64 Bit \\
mit Vorzeichen & \lstinline,int8_t,
& \lstinline,int16_t,
& \lstinline,int32_t,
& \lstinline,int64_t, \\
ohne Vorzeichen & \lstinline,uint8_t,
& \lstinline,uint16_t,
& \lstinline,uint32_t,
& \lstinline,uint64_t,
\end{tabular}
\bigskip
\bigskip
Ausgabe:
\smallskip\par
\begin{lstlisting}
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
...
uint64_t x = 42;
printf ("Die Antwort lautet: %" PRIu64 "\n", x);
\end{lstlisting}
\bigskip
Aufgabe: Schreiben Sie C-Funktionen, die ein "`Array von Bits"' realisieren, z.\,B.
\smallskip
\begin{tabular}[t]{ll}
\lstinline|void set_bit (int i);| & Bei Index $i$ auf 1 setzen \\
\lstinline|void clear_bit (int i);| & Bei Index $i$ auf 0 setzen \\
\lstinline|int get_bit (int i);| & Bei Index $i$ lesen
\end{tabular}
\medskip
Hinweise:
\begin{itemize}
\item
Die Größe des Bit-"`Arrays"' (z.\,B.\ 1000) dürfen Sie als \emph{vorher bekannt\/} voraussetzen.
\item
Sie benötigen ein Array, z.\,B.\ von \lstinline|char|- oder \lstinline|int|-Variablen.
\item
Sie benötigen eine Division (\lstinline|/|) sowie den Divisionsrest (Modulo: \lstinline|%|).
\end{itemize}
\end{frame}
\subsection{I/O-Ports}
\begin{frame}[fragile]
% \showsection
\showsubsection
\vspace*{-1.5\medskipamount}
{\large\textbf{\color{structure}4.3\quad Interrupts}}
\bigskip
Kommunikation mit externen Geräten
\bigskip
\begin{center}
\includegraphics{io-ports-and-interrupts.pdf}
\end{center}
\end{frame}
\begin{frame}[fragile]
\showsubsection
In Output-Port schreiben = Aktoren ansteuern
Beispiel: LED
\medskip
\begin{lstlisting}
#include <avr/io.h>
...
DDRC = 0x70;
PORTC = 0x40;
\end{lstlisting}
\begin{picture}(0,0)
\put(3,0.67){\begin{minipage}{3cm}
\color{red}%
binär: 0111\,0000\\
binär: 0100\,0000
\end{minipage}}
\put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}}
\end{picture}
\bigskip
\lstinline{DDR} = Data Direction Register\\
Bit = 1 für Output-Port\\
Bit = 0 für Input-Port
\bigskip
\emph{Details: siehe Datenblatt und Schaltplan}
\end{frame}
\begin{frame}[fragile]
\showsubsection
Aus Input-Port lesen = Sensoren abfragen
Beispiel: Taster
\medskip
\begin{lstlisting}
#include <avr/io.h>
...
DDRC = 0xfd;
while ((PINC & 0x02) == 0)
; /* just wait */
\end{lstlisting}
\begin{picture}(0,0)(-1.5,-0.42)
\put(3,0.67){\begin{minipage}{3cm}
\color{red}%
binär: 1111\,1101\\
binär: 0000\,0010
\end{minipage}}
\put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}}
\end{picture}
\bigskip
\lstinline{DDR} = Data Direction Register\\
Bit = 1 für Output-Port\\
Bit = 0 für Input-Port
\bigskip
\emph{Details: siehe Datenblatt und Schaltplan}
\bigskip
Praktikumsaufgabe: Druckknopfampel
\end{frame}
\nosectionnonumber{\inserttitle}
\begin{frame}
\shownosectionnonumber
\begin{itemize}
\item[\textbf{1}] \textbf{Einführung}
\hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
\item[\textbf{2}] \textbf{Einführung in C}
\begin{itemize}
\vspace*{-\smallskipamount}
\item[\dots]
\item[2.10] Zeiger
\item[2.11] Arrays und Strings
\item[2.12] Strukturen
\item[2.13] Dateien und Fehlerbehandlung
\color{medgreen}
\item[2.14] Parameter des Hauptprogramms
\item[2.15] String-Operationen
\end{itemize}
\item[\textbf{3}] \textbf{Bibliotheken}
% \begin{itemize}
% \color{red}
% \item[3.1] Der Präprozessor
% \item[3.2] Bibliotheken einbinden
% \item[3.3] Bibliotheken verwenden
% \vspace*{-\smallskipamount}
% \item[\dots]
%% \item[3.4] Projekt organisieren: make
% \end{itemize}
% \vspace*{-\smallskipamount}
\item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
\begin{itemize}
\color{medgreen}
\item[4.1] Bit-Operationen
\item[4.2] I/O-Ports
\color{red}
\item[4.3] Interrupts
\vspace*{-0.1cm}
\item[\dots]
\end{itemize}
\item[\textbf{5}] \textbf{Algorithmen}
\item[\textbf{\dots}]
\end{itemize}
\end{frame}
\fi
\end{document}
File added
% hp-musterloesung-20201114.pdf - Solutions to the Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020 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/>.
% README: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, Länge von Strings
\documentclass[a4paper]{article}
\usepackage{pgscript}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Musterlösung zu den Übungsaufgaben -- 10.\ Dezember 2020}
\exercise{Ausgabe von Hexadezimalzahlen}
Schreiben Sie eine Funktion \lstinline{void print_hex (uint32_t x)},
die eine gegebene vorzeichenlose 32-Bit-Ganzzahl \lstinline{x}
als Hexadezimalzahl ausgibt.
(Der Datentyp \lstinline{uint32_t} ist mit \lstinline{#include <stdint.h>} verfügbar.)
Verwenden Sie dafür \emph{nicht\/} \lstinline{printf()} mit
der Formatspezifikation \lstinline{%x} als fertige Lösung,
sondern programmieren Sie die nötige Ausgabe selbst.
(Für Tests ist \lstinline{%x} hingegen erlaubt und sicherlich nützlich.)
Die Verwendung von \lstinline{printf()}
mit anderen Formatspezifikationen wie z.\,B.\ \lstinline{%d}
oder \lstinline{%c} oder \lstinline{%s} ist hingegen zulässig.
\points{8}
(Hinweis für die Klausur: Abgabe auf Datenträger ist erlaubt und erwünscht,
aber nicht zwingend.)
\solution
Um die Ziffern von \lstinline{x} zur Basis 16 zu isolieren,
berechnen wir \lstinline{x % 16} (modulo 16 = Rest bei Division durch 16)
und dividieren anschließend \lstinline{x} durch 16,
solange bis \lstinline{x} den Wert 0 erreicht.
Wenn wir die auf diese Weise ermittelten Ziffern direkt ausgeben,
sind sie \emph{Little-Endian}, erscheinen also in umgekehrter Reihenfolge.
Die Datei \gitfile{hp}{20201210}{loesung-1-1.c} setzt diesen Zwischenschritt um.
Die Ausgabe der Ziffern erfolgt in \gitfile{hp}{20201210}{loesung-1-1.c}
über \lstinline{printf ("%d")}
für die Ziffern 0 bis 9. Für die darüberliegenden Ziffern
wird der Buchstabe \lstinline{a} um die Ziffer abzüglich 10 inkrementiert
und der erhaltene Wert mit \lstinline{printf ("%c")} als Zeichen ausgegeben.
Um die umgekehrte Reihenfolge zu beheben,
speichern wir die Ziffern von \lstinline{x}
in einem Array \lstinline{digits[]} zwischen
und geben sie anschließend in einer zweiten Schleife
in umgekehrter Reihenfolge aus (siehe \gitfile{hp}{20201210}{loesung-1-2.c}).
Da wir wissen, daß \lstinline{x} eine 32-Bit-Zahl ist
und daher höchstens 8 Hexadezimalziffern haben kann,
ist 8 eine sinnvolle Länge für das Ziffern-Array \lstinline{digits[8]}.
Nun sind die Ziffern in der richtigen Reihenfolge,
aber wir erhalten zusätzlich zu den eigentlichen Ziffern führende Nullen.
Da in der Aufgabenstellung nicht von führenden Nullen die Rede war,
sind diese nicht verboten; \gitfile{hp}{20201210}{loesung-1-2.c} ist daher
eine richtige Lösung der Aufgabe.
\breath
Wenn wir die führenden Nullen vermeiden wollen,
können wir die \lstinline{for}-Schleifen durch \lstinline{while}-Schleifen ersetzen.
Die erste Schleife zählt hoch, solange \lstinline{x} ungleich 0 ist;
die zweite zählt von dem erreichten Wert aus wieder herunter
-- siehe \gitfile{hp}{20201210}{loesung-1-3.c}.
Da wir wissen, daß die Zahl \lstinline{x} höchstens 32 Bit,
also höchstens 8 Hexadezimalziffern hat,
wissen wir, daß \lstinline{i} höchstens den Wert 8 erreichen kann,
das Array also nicht überlaufen wird.
Man beachte, daß der Array-Index nach der ersten Schleife "`um einen zu hoch"' ist.
In der zweiten Schleife muß daher \emph{zuerst\/} der Index dekrementiert werden.
Erst danach darf ein Zugriff auf \lstinline{digit[i]} erfolgen.
\breath
Alternativ können wir auch mitschreiben,
ob bereits eine Ziffer ungleich Null ausgegeben wurde,
und andernfalls die Ausgabe von Null-Ziffern unterdrücken
-- siehe \gitfile{hp}{20201210}{loesung-1-4.c}.
\breath
Weitere Möglichkeiten ergeben sich, wenn man bedenkt,
daß eine Hexadezimalziffer genau einer Gruppe von vier Binärziffern entspricht.
Eine Bitverschiebung um 4 nach rechts
ist daher dasselbe wie eine Division durch 16,
und eine Und-Verknüpfung mit 15$_{10}$ = f$_{16}$ = 1111$_2$
ist dasselbe wie die Operation Modulo 16.
Die Datei \gitfile{hp}{20201210}{loesung-1-5.c} ist eine in dieser Weise abgewandelte Variante
von \gitfile{hp}{20201210}{loesung-1-3.c}.
Mit dieser Methode kann man nicht nur auf die jeweils unterste Ziffer,
sondern auf alle Ziffern direkt zugreifen.
Damit ist kein Array als zusätzlicher Speicher mehr nötig.
Die Datei \gitfile{hp}{20201210}{loesung-1-6.c} setzt dies auf einfache Weise um.
Sie gibt wieder führende Nullen mit aus,
ist aber trotzdem eine weitere richtige Lösung der Aufgabe.
Die führenden Nullen ließen sich auf die gleiche Weise vermeiden
wie in \gitfile{hp}{20201210}{loesung-1-4.c}.
Die Bitverschiebungsmethode hat den Vorteil,
daß kein zusätzliches Array benötigt wird.
Auch wird die als Parameter übergebene Zahl \lstinline{x} nicht verändert,
was bei größeren Zahlen, die über Zeiger übergeben werden, von Vorteil sein kann.
Demgegenüber steht der Nachteil,
daß diese Methode nur für eine ganze Anzahl von Bits funktioniert,
also für Basen, die Zweierpotenzen sind (z.\,B.\ 2, 8, 16, 256).
Für alle anderen Basen (z.\,B.\ 10) eignet sich nur die Methode
mit Division und Modulo-Operation.
\exercise{Einfügen in Strings}
Wir betrachten das folgende Programm (\gitfile{hp}{20201210}{aufgabe-2.c}):
% \begin{lstlisting}[style=numbered]
\begin{lstlisting}
#include <stdio.h>
#include <string.h>
void insert_into_string (char src, char *target, int pos)
{
int len = strlen (target);
for (int i = pos; i < len; i++)
target[i+1] = target[i];
target[pos] = src;
}
int main (void)
{
char test[100] = "Hochshule Bochum";
insert_into_string ('c', test, 5);
printf ("%s\n", test);
return 0;
}
\end{lstlisting}
Die Ausgabe des Programms lautet:
\lstinline[style=terminal]{Hochschhhhhhhhhhh}
\begin{enumerate}[\quad(a)]
\item
Erklären Sie, wie die Ausgabe zustandekommt.
\points{3}
% \workspace{12}
\item
Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos}
in den String \lstinline{target} einfügt.\par
Die Ausgabe des Programms müßte dann
\lstinline[style=terminal]{Hochschule Bochum} lauten.
\points{2}
% \workspace{13}
\item
Was kann passieren, wenn Sie die Zeile
\lstinline{char test[100] = "Hochshule Bochum";}\\
durch
\lstinline{char test[] = "Hochshule Bochum";} ersetzen?
Begründen Sie Ihre Antwort.
\points{2}
% \workspace{10}
\item
Was kann passieren, wenn Sie die Zeile
\lstinline{char test[100] = "Hochshule Bochum";}\\
durch
\lstinline{char *test = "Hochshule Bochum";} ersetzen?
Begründen Sie Ihre Antwort.
\points{2}
% \workspace{10}
% \item
% Schreiben Sie eine Funktion
% \lstinline{void insert_into_string_sorted (char src, char *target)},
% die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist
% und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle
% einfügt. Diese Funktion darf die bereits vorhandene Funktion
% \lstinline|insert_into_string()| aufrufen.\\
% \points{4}\par
% Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm:
% \begin{lstlisting}[gobble=8]
% char test[100] = "";
% insert_into_string_sorted ('c', test);
% insert_into_string_sorted ('a', test);
% insert_into_string_sorted ('d', test);
% insert_into_string_sorted ('b', test);
% \end{lstlisting}
% Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten.
% \workspace{14}
% \item
% Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings)
% arbeitet Ihre Funktion
% \lstinline{void insert_into_string_sorted (char src, char *target)}
% und warum?
% \points{1}
% \workspace{10}
% \item
% Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\
% \lstinline{void insert_into_string_sorted (char src, char *target)}
% so gestalten kann,\\
% daß sie in $\mathcal{O}(\log n)$ arbeitet.
% \points{3}
% \workspace{35}
\end{enumerate}
\solution
\begin{enumerate}[\quad(a)]
\item
\textbf{Erklären Sie, wie die Ausgabe zustandekommt.}
In der Schleife wird \emph{zuerst\/} der nächste Buchstabe \lstinline{target[i + 1]}
gleich dem aktuellen gesetzt
und \emph{danach\/} der Zähler \lstinline{i} erhöht.
Dadurch wird im nächsten Schleifendurchlauf der bereits verschobene Buchstabe
noch weiter geschoben und letztlich alle Buchstaben in \lstinline{target[]}
durch den an der Stelle \lstinline{pos} ersetzt.
\item
\textbf{Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
daß sie den Buchstben \lstinline{src} an der Stelle \lstinline{pos}
in den String \lstinline{target} einfügt.}\par
\textbf{Die Ausgabe des Programms müßte dann
\lstinline[style=terminal]{Hochschule Bochum} lauten.}
Um im String "`Platz zu schaffen"', muß man von hinten beginnen,
also die Schleife umdrehen\\
(siehe: \gitfile{hp}{20201210}{loesung-2.c}):
\begin{lstlisting}{gobble=8}
for (int i = len; i >= pos; i--)
target[i + 1] = target[i];
\end{lstlisting}
\item
\textbf{Was kann passieren, wenn Sie die Zeile
\lstinline{char test[100] = "Hochshule Bochum";}\\
durch
\lstinline{char test[] = "Hochshule Bochum";}
ersetzen und warum?}
Die Schreibweise \lstinline{test[]} bedeutet,
daß der Compiler selbst zählt, wieviel Speicherplatz der String benötigt,
un dann genau die richtige Menge Speicher reserviert
(anstatt, wie wir es manuell getan haben, pauschal Platz für 100 Zeichen).
Wenn wir nun in den String ein zusätzliches Zeichen einfügen,
ist dafür kein Speicherplatz reserviert worden,
und wir \textbf{überschreiben} dann Speicher, an dem sich andere Variable befinden,
was zu einem \textbf{Absturz} führen kann.
Da wir hier nur ein einziges Zeichen schreiben,
wird dieser Fehler nicht sofort auffallen.
Dies ist schlimmer, als wenn das Programm direkt beim ersten Test abstürzt,
denn dadurch entsteht bei uns der Eindruck, es sei in Ordnung.
Wenn danach der Fehler in einer Produktivumgebung auftritt,
kann dadurch Schaden entstehen -- je nach Einsatzgebiet der Software
u.\,U.\ erheblicher Vermögens-, Sach- und/oder Personenschaden
(z.\,B.\ Absturz eines Raumflugkörpers).
\item
\textbf{Was kann passieren, wenn Sie
\lstinline{char test[100] = "Hochshule Bochum";}\\
durch
\lstinline{char *test = "Hochshule Bochum";}
ersetzen und warum?}
In diesem Fall wird der Speicher für den eigentlichen String
in einem unbenannten, \textbf{nicht schreibbaren} Teil des Speichers reserviert.
Unser Versuch, dorthin ein zusätzliches Zeichen zu schreiben,
fürt dann normalerweise zu einem \textbf{Absturz}.
In manchen Systemen (Betriebssystem, Compiler, \dots)
ist der Speicherbereich tatsächlich sehr wohl schreibbar.
In diesem Fall tritt der Absturz nicht immer und nicht immer sofort auf --
genau wie in Aufgabenteil (c).
\end{enumerate}
\exercise{Länge von Strings}
Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert.
Beispiel: \lstinline{char *hello_world = "Hello, world!\n"}
Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\
zur Verfügung (\lstinline{#include <string.h>}).
\begin{itemize}
\item[(a)]
Auf welche Weise ist die Länge eines Strings gekennzeichnet?
\points{1}
\item[(b)]
Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"},
und wieviel Speicherplatz belegt sie?\\
\points{2}
\item[(c)]
Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)},
die die Länge eines Strings zurückgibt.\\
\points{3}
\end{itemize}
Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{20201210}{aufgabe-3.c}):
\begin{center}
\begin{minipage}{8cm}
\begin{lstlisting}[gobble=8]
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
\end{lstlisting}
\end{minipage}%
\begin{minipage}{6cm}
\vspace*{-1cm}
\begin{lstlisting}[gobble=8]
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
\end{lstlisting}
\vspace*{-1cm}
\end{minipage}
\end{center}
\begin{itemize}
\item[(d)]
Was bewirken die beiden Funktionen?
\points{2}
\item[(e)]
% Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen
% hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String -- und warum?
% Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.
% \points 3
% \item[(f)]
Schreiben Sie eine eigene Funktion,
die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\
nur effizienter.
\points{4}
\end{itemize}
\solution
\begin{itemize}
\item[(a)]
\textbf{Auf welche Weise ist die Länge eines Strings gekennzeichnet?}
Ein String ist ein Array von \lstinline{char}s.
Nach den eigentlichen Zeichen des Strings enthält das Array
\textbf{ein Null-Symbol} (Zeichen mit Zahlenwert 0,
nicht zu verwechseln mit der Ziffer \lstinline{'0'}) als Ende-Markierung.
Die Länge eines Strings ist die Anzahl der Zeichen
\emph{vor\/} diesem Symbol.
\item[(b)]
{\bf Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"},
und wieviel Speicherplatz belegt sie?}
Sie ist 14 Zeichen lang (\lstinline{'\n'} ist nur 1 Zeichen;
das Null-Symbol, das das Ende markiert, zählt hier nicht mit)
und belegt Speicherplatz für 15 Zeichen
(15 Bytes -- einschließlich Null-Symbol / Ende-Markierung).
\item[(c)]
\textbf{Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)},
die die Länge eines Strings zurückgibt.}
Siehe die Dateien \gitfile{hp}{20201210}{loesung-3c-1.c} (mit Array-Index)
und \gitfile{hp}{20201210}{loesung-3c-2.c} (mit Zeiger-Arithmetik).
Beide Lösungen sind korrekt und arbeiten gleich schnell.
Die Warnung \lstinline[style=terminal]{conflicting types for built-in function "strlen"}
kann normalerweise ignoriert werden;
auf manchen Systemen (z.\,B.\ MinGW) hat jedoch die eingebaute Funktion \lstinline{strlen()}
beim Linken Vorrang vor der selbstgeschriebenen,
so daß die selbstgeschriebene Funktion nie aufgerufen wird.
In solchen Fällen ist es zulässig, die selbstgeschriebene Funktion
anders zu nennen (z.\,B.\ \lstinline{my_strlen()}).
\item[(d)]
\textbf{Was bewirken die beiden Funktionen?}
Beide addieren die Zahlenwerte der im String enthaltenen Zeichen
und geben die Summe als Funktionsergebnis zurück.
Im Falle des Test-Strings \lstinline{"Hello, world!\n"}
lautet der Rückgabewert 1171 (siehe \gitfile{hp}{20201210}{loesung-3d-1.c} und \gitfile{hp}{20201210}{loesung-3d-2.c}).
\item[(e)]
% \textbf{Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen
% hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String -- und warum?
% Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.}
%
% Vorüberlegung: \lstinline{strlen()} greift in einer Schleife
% auf alle Zeichen des Strings der Länge $n$ zu,
% hat also $\mathcal{O}(n)$.
%
% \lstinline{fun_1()} ruft in jedem Schleifendurchlauf
% (zum Prüfen der \lstinline{while}-Bedingung) einmal \lstinline{strlen()} auf
% und greift anschließend auf ein Zeichen des Strings zu,
% hat also $\mathcal{O}\bigl(n\cdot(n+1)\bigr) = \mathcal{O}(n^2)$.
%
% \lstinline{fun_2()} ruft einmalig \lstinline{strlen()} auf
% und greift anschließend in einer Schleife auf alle Zeichen des Strings zu,
% hat also $\mathcal{O}(n+n) = \mathcal{O}(n)$.
%
% \item[(f)]
\textbf{Schreiben Sie eine eigene Funktion,
die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},
nur effizienter.}
Die Funktion wird effizienter,
wenn man auf den Aufruf von \lstinline{strlen()} verzichtet
und stattdessen die Ende-Prüfung in derselben Schleife vornimmt,
in der man auch die Zahlenwerte der Zeichen des Strings aufsummiert.
Die Funktion \lstinline{fun_3()} in der Datei \gitfile{hp}{20201210}{loesung-3e-1.c}
realisiert dies mit einem Array-Index,
Die Funktion \lstinline{fun_4()} in der Datei \gitfile{hp}{20201210}{loesung-3e-2.c}
mit Zeiger-Arithmetik.
Beide Lösungen sind korrekt und arbeiten gleich schnell.
% \textbf{Bemerkung:} Die effizientere Version der Funktion
% arbeitet doppelt so schnell wie die ursprüngliche,
% hat aber ebenfalls die Ordnung $\mathcal{O}(n)$.
\end{itemize}
\end{document}
File added
% hp-uebung-20201210.pdf - Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020 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/>.
% README: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, Länge von Strings
\documentclass[a4paper]{article}
\usepackage{pgscript}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Übungsaufgaben -- 10.\ Dezember 2020}
Diese Übung enthält Punkteangaben wie in einer Klausur.
Um zu "`bestehen"', müssen Sie innerhalb von 80 Minuten
unter Verwendung ausschließlich zugelassener Hilfsmittel
14 Punkte (von insgesamt \totalpoints) erreichen.
\exercise{Ausgabe von Hexadezimalzahlen}
Schreiben Sie eine Funktion \lstinline{void print_hex (uint32_t x)},
die eine gegebene vorzeichenlose 32-Bit-Ganzzahl \lstinline{x}
als Hexadezimalzahl ausgibt.
(Der Datentyp \lstinline{uint32_t} ist mit \lstinline{#include <stdint.h>} verfügbar.)
Verwenden Sie dafür \emph{nicht\/} \lstinline{printf()} mit
der Formatspezifikation \lstinline{%x} als fertige Lösung,
sondern programmieren Sie die nötige Ausgabe selbst.
(Für Tests ist \lstinline{%x} hingegen erlaubt und sicherlich nützlich.)
Die Verwendung von \lstinline{printf()}
mit anderen Formatspezifikationen wie z.\,B.\ \lstinline{%d}
oder \lstinline{%c} oder \lstinline{%s} ist hingegen zulässig.
\points{8}
(Hinweis für die Klausur: Abgabe auf Datenträger ist erlaubt und erwünscht,
aber nicht zwingend.)
\exercise{Einfügen in Strings}
Wir betrachten das folgende Programm (\gitfile{hp}{20201210}{aufgabe-2.c}):
% \begin{lstlisting}[style=numbered]
\begin{lstlisting}
#include <stdio.h>
#include <string.h>
void insert_into_string (char src, char *target, int pos)
{
int len = strlen (target);
for (int i = pos; i < len; i++)
target[i+1] = target[i];
target[pos] = src;
}
int main (void)
{
char test[100] = "Hochshule Bochum";
insert_into_string ('c', test, 5);
printf ("%s\n", test);
return 0;
}
\end{lstlisting}
Die Ausgabe des Programms lautet:
\lstinline[style=terminal]{Hochschhhhhhhhhhh}
\begin{enumerate}[\quad(a)]
\item
Erklären Sie, wie die Ausgabe zustandekommt.
\points{3}
% \workspace{12}
\item
Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos}
in den String \lstinline{target} einfügt.\par
Die Ausgabe des Programms müßte dann
\lstinline[style=terminal]{Hochschule Bochum} lauten.
\points{2}
% \workspace{13}
\item
Was kann passieren, wenn Sie die Zeile
\lstinline{char test[100] = "Hochshule Bochum";}\\
durch
\lstinline{char test[] = "Hochshule Bochum";} ersetzen?
Begründen Sie Ihre Antwort.
\points{2}
% \workspace{10}
\item
Was kann passieren, wenn Sie die Zeile
\lstinline{char test[100] = "Hochshule Bochum";}\\
durch
\lstinline{char *test = "Hochshule Bochum";} ersetzen?
Begründen Sie Ihre Antwort.
\points{2}
% \workspace{10}
% \item
% Schreiben Sie eine Funktion
% \lstinline{void insert_into_string_sorted (char src, char *target)},
% die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist
% und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle
% einfügt. Diese Funktion darf die bereits vorhandene Funktion
% \lstinline|insert_into_string()| aufrufen.\\
% \points{4}\par
% Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm:
% \begin{lstlisting}[gobble=8]
% char test[100] = "";
% insert_into_string_sorted ('c', test);
% insert_into_string_sorted ('a', test);
% insert_into_string_sorted ('d', test);
% insert_into_string_sorted ('b', test);
% \end{lstlisting}
% Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten.
% \workspace{14}
% \item
% Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings)
% arbeitet Ihre Funktion
% \lstinline{void insert_into_string_sorted (char src, char *target)}
% und warum?
% \points{1}
% \workspace{10}
% \item
% Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\
% \lstinline{void insert_into_string_sorted (char src, char *target)}
% so gestalten kann,\\
% daß sie in $\mathcal{O}(\log n)$ arbeitet.
% \points{3}
% \workspace{35}
\end{enumerate}
\exercise{Länge von Strings}
Strings werden in der Programmiersprache C durch Zeiger auf \lstinline{char}-Variable realisiert.
Beispiel: \lstinline{char *hello_world = "Hello, world!\n"}
Die Systembibliothek stellt eine Funktion \lstinline{strlen()} zur Ermittlung der Länge von Strings\\
zur Verfügung (\lstinline{#include <string.h>}).
\begin{itemize}
\item[(a)]
Auf welche Weise ist die Länge eines Strings gekennzeichnet?
\points{1}
\item[(b)]
Wie lang ist die Beispiel-String-Konstante \lstinline{"Hello, world!\n"},
und wieviel Speicherplatz belegt sie?\\
\points{2}
\item[(c)]
Schreiben Sie eine eigene Funktion \lstinline{int strlen (char *s)},
die die Länge eines Strings zurückgibt.\\
\points{3}
\end{itemize}
Wir betrachten nun die folgenden Funktionen (Datei: \gitfile{hp}{20201210}{aufgabe-3.c}):
\begin{center}
\begin{minipage}{8cm}
\begin{lstlisting}[gobble=8]
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
\end{lstlisting}
\end{minipage}%
\begin{minipage}{6cm}
\vspace*{-1cm}
\begin{lstlisting}[gobble=8]
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
\end{lstlisting}
\vspace*{-1cm}
\end{minipage}
\end{center}
\begin{itemize}
\item[(d)]
Was bewirken die beiden Funktionen?
\points{2}
\item[(e)]
% Von welcher Ordnung (Landau-Symbol) sind die beiden Funktionen
% hinsichtlich der Anzahl ihrer Zugriffe auf die Zeichen im String -- und warum?
% Sie dürfen für \lstinline{strlen()} Ihre eigene Version der Funktion voraussetzen.
% \points 3
% \item[(f)]
Schreiben Sie eine eigene Funktion,
die dieselbe Aufgabe erledigt wie \lstinline{fun_2()},\\
nur effizienter.
\points{4}
\end{itemize}
\bigskip
\begin{flushright}
\textit{Viel Erfolg!}
\end{flushright}
\makeatletter
\immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}}
\makeatother
\end{document}
#include <stdio.h>
#include <stdint.h>
void print_hex (uint32_t x)
{
while (x)
{
int digit = x % 16;
if (digit < 10)
printf ("%d", digit);
else
printf ("%c", 'a' + digit - 10);
x /= 16;
}
}
int main (void)
{
print_hex (0xcafe42);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
void print_hex (uint32_t x)
{
char digit[8];
for (int i = 0; i < 8; i++)
{
digit[i] = x % 16;
x /= 16;
}
for (int i = 7; i >= 0; i--)
{
if (digit[i] < 10)
printf ("%d", digit[i]);
else
printf ("%c", 'a' + digit[i] - 10);
}
}
int main (void)
{
print_hex (0xcafe42);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
void print_hex (uint32_t x)
{
char digit[8];
int i = 0;
while (x)
{
digit[i] = x % 16;
x /= 16;
i++;
}
while (i > 0)
{
i--;
if (digit[i] < 10)
printf ("%d", digit[i]);
else
printf ("%c", 'a' + digit[i] - 10);
}
}
int main (void)
{
print_hex (0xcafe42);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
void print_hex (uint32_t x)
{
char digit[8];
for (int i = 0; i < 8; i++)
{
digit[i] = x % 16;
x /= 16;
}
int printing = 0;
for (int i = 7; i >= 0; i--)
{
if (printing || digit[i] != 0)
{
printing = 1;
if (digit[i] < 10)
printf ("%d", digit[i]);
else
printf ("%c", 'a' + digit[i] - 10);
}
}
}
int main (void)
{
print_hex (0xcafe42);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
void print_hex (uint32_t x)
{
char digit[8];
int i = 0;
while (x)
{
digit[i] = x & 0x0000000f;
x >>= 4;
i++;
}
while (i > 0)
{
i--;
if (digit[i] < 10)
printf ("%d", digit[i]);
else
printf ("%c", 'a' + digit[i] - 10);
}
}
int main (void)
{
print_hex (0xcafe42);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
void print_hex (uint32_t x)
{
int i = 32;
while (i > 0)
{
i -= 4;
int digit = (x >> i) & 0x0000000f;
if (digit < 10)
printf ("%d", digit);
else
printf ("%c", 'a' + digit - 10);
}
}
int main (void)
{
print_hex (0xcafe42);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <string.h>
void insert_into_string (char src, char *target, int pos)
{
int len = strlen (target);
for (int i = len; i >= pos; i--)
target[i + 1] = target[i];
target[pos] = src;
}
int main (void)
{
char test[100] = "Hochshule Bochum";
insert_into_string ('c', test, 5);
printf ("%s\n", test);
return 0;
}
#include <stdio.h>
int strlen (char *s)
{
int l = 0;
while (s[l])
l++;
return l;
}
int main (void)
{
printf ("%d\n", strlen ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int strlen (char *s)
{
char *s0 = s;
while (*s)
s++;
return s - s0;
}
int main (void)
{
printf ("%d\n", strlen ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int strlen (char *s)
{
int l = 0;
while (s[l])
l++;
return l;
}
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
int main (void)
{
printf ("%d\n", fun_1 ("Hello, world!\n"));
printf ("%d\n", fun_2 ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int strlen (char *s)
{
char *s0 = s;
while (*s)
s++;
return s - s0;
}
int fun_1 (char *s)
{
int x = 0;
for (int i = 0; i < strlen (s); i++)
x += s[i];
return x;
}
int fun_2 (char *s)
{
int i = 0, x = 0;
int len = strlen (s);
while (i < len)
x += s[i++];
return x;
}
int main (void)
{
printf ("%d\n", fun_1 ("Hello, world!\n"));
printf ("%d\n", fun_2 ("Hello, world!\n"));
return 0;
}
#include <stdio.h>
int fun_3 (char *s)
{
int i = 0, x = 0;
while (s[i])
x += s[i++];
return x;
}
int main (void)
{
printf ("%d\n", fun_3 ("Hello, world!\n"));
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment