diff --git a/20191114/hp-musterloesung-20191114.pdf b/20191114/hp-musterloesung-20191114.pdf new file mode 100644 index 0000000000000000000000000000000000000000..56e26478154782d25e90cb76d3c6c03a6ac2e093 Binary files /dev/null and b/20191114/hp-musterloesung-20191114.pdf differ diff --git a/20191114/hp-musterloesung-20191114.tex b/20191114/hp-musterloesung-20191114.tex new file mode 100644 index 0000000000000000000000000000000000000000..8d68b836769f3a62a0cb95d0873d2461a1445bae --- /dev/null +++ b/20191114/hp-musterloesung-20191114.tex @@ -0,0 +1,458 @@ +% hp-musterloesung-20191114.pdf - Solutions to the Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019 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 -- 14.\ November 2019} + + \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}{20191114}{loesung-1-1.c} setzt diesen Zwischenschritt um. + + Die Ausgabe der Ziffern erfolgt in \gitfile{hp}{20191114}{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}{20191114}{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}{20191114}{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}{20191114}{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}{20191114}{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}{20191114}{loesung-1-5.c} ist eine in dieser Weise abgewandelte Variante + von \gitfile{hp}{20191114}{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}{20191114}{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}{20191114}{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}{20191114}{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}{20191114}{loesung-2.c}): + \begin{lstlisting}{gobble=8} + for (int i = len; i > pos; i++) + target[i] = target[i - 1]; + \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 Variablen 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}{20191114}{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}{20191114}{loesung-3c-1.c} (mit Array-Index) + und \gitfile{hp}{20191114}{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}{20191114}{loesung-3d-1.c} und \gitfile{hp}{20191114}{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}{20191114}{loesung-3e-1.c} + realisiert dies mit einem Array-Index, + Die Funktion \lstinline{fun_4()} in der Datei \gitfile{hp}{20191114}{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} diff --git a/20191114/loesung-1-1.c b/20191114/loesung-1-1.c new file mode 100644 index 0000000000000000000000000000000000000000..98b2f03f19d21aa2a794fef1f3f98feff95f5142 --- /dev/null +++ b/20191114/loesung-1-1.c @@ -0,0 +1,22 @@ +#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; +} diff --git a/20191114/loesung-1-2.c b/20191114/loesung-1-2.c new file mode 100644 index 0000000000000000000000000000000000000000..35aa3b3aea6fc8faaa55c7d5382f0a8de9282aee --- /dev/null +++ b/20191114/loesung-1-2.c @@ -0,0 +1,26 @@ +#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; +} diff --git a/20191114/loesung-1-3.c b/20191114/loesung-1-3.c new file mode 100644 index 0000000000000000000000000000000000000000..2462f2b537896722d8d1774a5d47f374ee5ef7fa --- /dev/null +++ b/20191114/loesung-1-3.c @@ -0,0 +1,29 @@ +#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; +} diff --git a/20191114/loesung-1-4.c b/20191114/loesung-1-4.c new file mode 100644 index 0000000000000000000000000000000000000000..5083dcb865c86beafd43ce3e8837510b13cbe850 --- /dev/null +++ b/20191114/loesung-1-4.c @@ -0,0 +1,31 @@ +#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; +} diff --git a/20191114/loesung-1-5.c b/20191114/loesung-1-5.c new file mode 100644 index 0000000000000000000000000000000000000000..e3446edb4a40348ac14da420f344c208f8916f7e --- /dev/null +++ b/20191114/loesung-1-5.c @@ -0,0 +1,29 @@ +#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; +} diff --git a/20191114/loesung-1-6.c b/20191114/loesung-1-6.c new file mode 100644 index 0000000000000000000000000000000000000000..7b8e8e1a9d7285b8a1e02ff1a91310f1dc02ed5b --- /dev/null +++ b/20191114/loesung-1-6.c @@ -0,0 +1,23 @@ +#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; +} diff --git a/20191114/loesung-2.c b/20191114/loesung-2.c new file mode 100644 index 0000000000000000000000000000000000000000..e4151901aaff375907ba0e8c1c4f449f2f6f5743 --- /dev/null +++ b/20191114/loesung-2.c @@ -0,0 +1,18 @@ +#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] = target[i - 1]; + target[pos] = src; +} + +int main (void) +{ + char test[100] = "Hochshule Bochum"; + insert_into_string ('c', test, 5); + printf ("%s\n", test); + return 0; +} diff --git a/20191114/loesung-3c-1.c b/20191114/loesung-3c-1.c new file mode 100644 index 0000000000000000000000000000000000000000..69ddd0e4e749f6ca31bfa3d4f929c333648ef6ea --- /dev/null +++ b/20191114/loesung-3c-1.c @@ -0,0 +1,15 @@ +#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; +} diff --git a/20191114/loesung-3c-2.c b/20191114/loesung-3c-2.c new file mode 100644 index 0000000000000000000000000000000000000000..e783c474e485e80d08a6e86f8ae6e179f5a294f4 --- /dev/null +++ b/20191114/loesung-3c-2.c @@ -0,0 +1,15 @@ +#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; +} diff --git a/20191114/loesung-3d-1.c b/20191114/loesung-3d-1.c new file mode 100644 index 0000000000000000000000000000000000000000..57521382c21fb743c6f5f5c65320bc4ac9360b1a --- /dev/null +++ b/20191114/loesung-3d-1.c @@ -0,0 +1,34 @@ + +#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; +} diff --git a/20191114/loesung-3d-2.c b/20191114/loesung-3d-2.c new file mode 100644 index 0000000000000000000000000000000000000000..5f3f0961129aa16fc9c4510ae21bb77b69913b12 --- /dev/null +++ b/20191114/loesung-3d-2.c @@ -0,0 +1,34 @@ + +#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; +} diff --git a/20191114/loesung-3e-1.c b/20191114/loesung-3e-1.c new file mode 100644 index 0000000000000000000000000000000000000000..74f5add0c5f62cccb8f817d40f860893f496db11 --- /dev/null +++ b/20191114/loesung-3e-1.c @@ -0,0 +1,15 @@ +#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; +} diff --git a/20191114/loesung-3e-2.c b/20191114/loesung-3e-2.c new file mode 100644 index 0000000000000000000000000000000000000000..b223d2d17c261d7cf1373a8379def8911a45ccb7 --- /dev/null +++ b/20191114/loesung-3e-2.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int fun_4 (char *s) +{ + int x = 0; + while (*s) + x += *s++; + return x; +} + +int main (void) +{ + printf ("%d\n", fun_4 ("Hello, world!\n")); + return 0; +}