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

Vorbereitung 14.12.2023

parent d48edcd3
No related branches found
No related tags found
No related merge requests found
Showing
with 2301 additions and 0 deletions
#include <stdio.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct animal
{
int type;
char *name;
} animal;
typedef struct with_wings
{
int wings;
} with_wings;
typedef struct with_legs
{
int legs;
} with_legs;
int main (void)
{
animal *a[2];
animal duck;
a[0] = &duck;
a[0]->type = WITH_WINGS;
a[0]->name = "duck";
a[0]->wings = 2;
animal cow;
a[1] = &cow;
a[1]->type = WITH_LEGS;
a[1]->name = "cow";
a[1]->legs = 4;
for (int i = 0; i < 2; i++)
if (a[i]->type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->name,
((with_legs *) a[i])-> legs);
else if (a[i]->type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->name,
((with_wings *) a[i])-> wings);
else
printf ("Error in animal: %s\n", a[i]->name);
return 0;
}
#include <stdio.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct animal
{
int type;
char *name;
} animal;
typedef struct with_wings
{
int wings;
} with_wings;
typedef struct with_legs
{
int legs;
} with_legs;
int main (void)
{
animal *a[2];
animal duck;
a[0] = &duck;
a[0]->type = WITH_WINGS;
a[0]->name = "duck";
((with_wings *) a[0])->wings = 2;
animal cow;
a[1] = &cow;
a[1]->type = WITH_LEGS;
a[1]->name = "cow";
((with_legs *) a[1])->legs = 4;
for (int i = 0; i < 2; i++)
if (a[i]->type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->name,
((with_legs *) a[i])-> legs);
else if (a[i]->type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->name,
((with_wings *) a[i])-> wings);
else
printf ("Error in animal: %s\n", a[i]->name);
return 0;
}
File added
This diff is collapsed.
File added
This diff is collapsed.
File added
% hp-uebung-20231214.pdf - Exercises on Low-Level Programming / Applied Computer Sciences
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 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: dynamisches Bit-Array, objektorientierte Tier-Datenbank
\documentclass[a4paper]{article}
\usepackage{pgscript}
\usepackage{gensymb}
\newcommand{\ItwoC}{I\raisebox{0.5ex}{\footnotesize 2}C}
\newcommand{\ITWOC}{I\raisebox{0.5ex}{\normalsize 2}C}
\begin{document}
\thispagestyle{empty}
\section*{Hardwarenahe Programmierung\\
Übungsaufgaben -- 14.\ Dezember 2023}
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{Dynamisches Bit-Array}
Schreiben Sie die folgenden Funktionen zur Verwaltung eines dynamischen Bit-Arrays:
\begin{itemize}
\item
\lstinline{void bit_array_init (int n)}\\
Das Array initialisieren, so daß man \lstinline{n} Bits darin speichern kann.\\
Die Array-Größe \lstinline{n} ist keine Konstante, sondern erst im laufenden Programm bekannt.\\
Die Bits sollen auf den Anfangswert 0 initialisiert werden.
\item
\lstinline{void bit_array_set (int i, int value)}\\
Das Bit mit dem Index \lstinline{i} auf den Wert \lstinline{value} setzen.\\
Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen;
der Wert \lstinline{value} darf 1 oder 0 sein.
\item
\lstinline{void bit_array_flip (int i)}\\
Das Bit mit dem Index \lstinline{i} auf den entgegengesetzten Wert setzen,\\
also auf 1, wenn er vorher 0 ist, bzw.\ auf 0, wenn er vorher 1 ist.\\
Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen.
\item
\lstinline{int bit_array_get (int i)}\\
Den Wert des Bit mit dem Index \lstinline{i} zurückliefern.\\
Der Index \lstinline{i} darf von \lstinline{0} bis \lstinline{n - 1} gehen.
\item
\lstinline{void bit_array_resize (int new_n)}\\
Die Größe des Arrays auf \lstinline{new_n} Bits ändern.\\
Dabei soll der Inhalt des Arrays, soweit er in die neue Größe paßt, erhalten bleiben.\\
Neu hinzukommende Bits sollen auf 0 initialisiert werden.
\item
\lstinline{void bit_array_done (void)}\\
Den vom Array belegten Speicherplatz wieder freigeben.
\end{itemize}
Bei Bedarf dürfen Sie den Funktionen zusätzliche Parameter mitgeben,
beispielsweise um mehrere Arrays parallel verwalten zu können.
(In der objektorientierten Programmierung wäre dies der implizite Parameter \lstinline{this},
der auf die Objekt-Struktur zeigt.)
Die Bits sollen möglichst effizient gespeichert werden,
z.\,B.\ jeweils 8 Bits in einer \lstinline{uint8_t}-Variablen.
Die Funktionen sollen möglichst robust sein,
d.\,h.\ das Programm darf auch bei unsinnigen Parameterwerten nicht abstürzen,
sondern soll eine Fehlermeldung ausgeben.
\medskip
Die folgenden \textbf{Hinweise} beschreiben
einen möglichen Weg, die Aufgabe zu lösen.
Es seht Ihnen frei, die Aufgabe auch auf andere Weise zu lösen.
\begin{itemize}
\item
Setzen Sie zunächst voraus, daß das Array die konstante Länge 8 hat,
und schreiben Sie zunächst nur die Funktionen
\lstinline{bit_array_set()}, \lstinline{bit_array_flip()} und
\lstinline{bit_array_get()}.
\item
Verallgemeinern Sie nun auf eine konstante Länge,
bei der es sich um ein Vielfaches von 8 handelt.
\item
Implementieren Sie nun die Überprüfung auf unsinnige Parameterwerte.
Damit können Sie sich gleichzeitig von der Bedingung lösen,
daß die Länge des Arrays ein Vielfaches von 8 sein muß.
\item
Gehen Sie nun von einem statischen zu einem dynamischen Array über,
und implementieren Sie die Funktionen \lstinline{bit_array_init()},
\lstinline{bit_array_done()} und \lstinline{bit_array_resize()}.
\end{itemize}
\points{14}
\medskip
(Hinweis für die Klausur:
Abgabe in digitaler Form ist erwünscht, aber nicht zwingend.)
\clearpage
\exercise{Objektorientierte Tier-Datenbank}
Das unten dargestellte Programm (Datei: \gitfile{hp}{2023ws/20231214}{aufgabe-2a.c})
soll Daten von Tieren verwalten.
Beim Compilieren erscheinen die folgende Fehlermeldungen:
\begin{lstlisting}[style=terminal]
$ ¡gcc -std=c99 -Wall -O aufgabe-2a.c -o aufgabe-2a¿
aufgabe-2a.c: In function 'main':
aufgabe-2a.c:31: error: 'animal' has no member named 'wings'
aufgabe-2a.c:37: error: 'animal' has no member named 'legs'
\end{lstlisting}
Der Programmierer nimmt die in Rot dargestellten Ersetzungen vor
(Datei: \gitfile{hp}{2023ws/20231214}{aufgabe-2b.c}).
Daraufhin gelingt das Compilieren, und die Ausgabe des Programms lautet:
\begin{lstlisting}[style=terminal]
$ ¡gcc -std=c99 -Wall -O aufgabe-2b.c -o aufgabe-2b¿
$ ¡./aufgabe-2b¿
A duck has 2 legs.
Error in animal: cow
\end{lstlisting}
\begin{itemize}
\item[(a)]
Erklären Sie die o.\,a.\ Compiler-Fehlermeldungen.
\points{2}
\item[(b)]
Wieso verschwinden die Fehlermeldungen nach den o.\,a.\ Ersetzungen?
\points{3}
\item[(c)]
Erklären Sie die Ausgabe des Programms.
\points{5}
\item[(d)]
Beschreiben Sie -- in Worten und/oder als C-Quelltext -- einen Weg,
das Programm so zu berichtigen, daß es die Eingabedaten
(``A duck has 2 wings. A cow has 4 legs.'') korrekt speichert und ausgibt.\\
\points{4}
% \item[(e)]
% Schreiben Sie das Programm so um,
% daß es keine expliziten Typumwandlungen mehr benötigt.\par
% Hinweis: Verwenden Sie \lstinline{union}.
% \points{4}
% \item[(f)]
% Schreiben Sie das Programm weiter um,
% so daß es die Objektinstanzen \lstinline{duck} und \lstinline{cow}
% dynamisch erzeugt.\par
% Hinweis: Verwenden Sie \lstinline{malloc()} und schreiben Sie Konstruktoren.
% \points{4}
% \item[(g)]
% Schreiben Sie das Programm weiter um,
% so daß die Ausgabe nicht mehr direkt im Hauptprogramm erfolgt,
% sondern stattdessen eine virtuelle Methode \lstinline{print()}
% aufgerufen wird.\par
% Hinweis: Verwenden Sie in den Objekten Zeiger auf Funktionen,
% und initialisieren Sie diese in den Konstruktoren.
% \points{4}
\end{itemize}
\begin{minipage}[t]{0.34\textwidth}
\begin{lstlisting}[gobble=6,xleftmargin=0pt]
#include <stdio.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct animal
{
int type;
char *name;
} animal;
typedef struct with_wings
{
int wings;
} with_wings;
typedef struct with_legs
{
int legs;
} with_legs;
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}[t]{0.65\textwidth}
\begin{lstlisting}[gobble=6,xleftmargin=0pt]
int main (void)
{
animal *a[2];
animal duck;
a[0] = &duck;
a[0]->type = WITH_WINGS;
a[0]->name = "duck";
a[0]->wings = 2;
animal cow;
a[1] = &cow;
a[1]->type = WITH_LEGS;
a[1]->name = "cow";
a[1]->legs = 4;
for (int i = 0; i < 2; i++)
if (a[i]->type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->name,
((with_legs *) a[i])-> legs);
else if (a[i]->type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->name,
((with_wings *) a[i])-> wings);
else
printf ("Error in animal: %s\n", a[i]->name);
return 0;
}
\end{lstlisting}
\begin{picture}(0,0)
\color{red}
\put(3.7,6.207){\vector(-1,0){0.7}}
\put(3.8,6.207){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_legs *) a[1])->legs = 4;}}}
\put(4.0,8.735){\vector(-1,0){0.7}}
\put(4.1,8.735){\makebox(0,0)[l]{\lstinline[basicstyle=\color{red}]{((with_wings *) a[0])->wings = 2;}}}
\end{picture}
\end{minipage}
\begin{flushright}
\textit{Viel Erfolg!}
\end{flushright}
\makeatletter
\immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}}
\makeatother
\end{document}
../common/landau-symbols-2.pdf
\ No newline at end of file
../common/landau-symbols-3.pdf
\ No newline at end of file
../common/landau-symbols.pdf
\ No newline at end of file
#include <stdio.h>
#include <stdint.h>
uint8_t buffer = 0;
void bit_array_set (int i, int value)
{
uint8_t mask = 1 << i;
if (value)
buffer |= mask;
else
buffer &= ~mask;
}
void bit_array_flip (int i)
{
uint8_t mask = 1 << i;
buffer ^= mask;
}
int bit_array_get (int i)
{
uint8_t mask = 1 << i;
if (buffer & mask)
return 1;
else
return 0;
}
void output (void)
{
for (int i = 0; i < 8; i++)
{
if (i % 4 == 0)
printf (" ");
printf ("%d", bit_array_get (i));
}
printf ("\n");
}
int main (void)
{
output ();
bit_array_set (2, 1);
output ();
bit_array_flip (7);
output ();
bit_array_set (2, 0);
output ();
}
#include <stdio.h>
#include <stdint.h>
#define LENGTH 32
uint8_t buffer[LENGTH / 8] = { 0, 0, 0, 0 };
void bit_array_set (int i, int value)
{
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
if (value)
buffer[byte_index] |= mask;
else
buffer[byte_index] &= ~mask;
}
void bit_array_flip (int i)
{
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
buffer[byte_index] ^= mask;
}
int bit_array_get (int i)
{
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
if (buffer[byte_index] & mask)
return 1;
else
return 0;
}
void output (void)
{
for (int i = 0; i < LENGTH; i++)
{
if (i % 4 == 0)
printf (" ");
printf ("%d", bit_array_get (i));
}
printf ("\n");
}
int main (void)
{
output ();
bit_array_set (12, 1);
output ();
bit_array_flip (31);
output ();
bit_array_set (12, 0);
output ();
}
#include <stdio.h>
#include <stdint.h>
#include <error.h>
#define LENGTH 29
#define BYTES ((LENGTH + 7) / 8)
uint8_t buffer[BYTES] = { 0, 0, 0, 0 };
void check_index (int i)
{
if (i < 0 || i >= LENGTH)
error (1, 0, "index %d out of range (0, ..., %d)", i, LENGTH - 1);
}
void bit_array_set (int i, int value)
{
check_index (i);
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
if (value)
buffer[byte_index] |= mask;
else
buffer[byte_index] &= ~mask;
}
void bit_array_flip (int i)
{
check_index (i);
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
buffer[byte_index] ^= mask;
}
int bit_array_get (int i)
{
check_index (i);
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
if (buffer[byte_index] & mask)
return 1;
else
return 0;
}
void output (void)
{
for (int i = 0; i < LENGTH; i++)
{
if (i % 4 == 0)
printf (" ");
printf ("%d", bit_array_get (i));
}
printf ("\n");
}
int main (void)
{
output ();
bit_array_set (12, 1);
output ();
bit_array_flip (28);
output ();
bit_array_set (12, 0);
output ();
bit_array_flip (31);
output ();
}
#include <stdio.h>
#include <stdint.h>
#include <error.h>
#include <stdlib.h>
int length = 0;
int bytes = 0;
uint8_t *buffer = NULL;
void bit_array_init (int n)
{
length = n;
bytes = (length + 7) / 8;
if (buffer)
free (buffer);
buffer = malloc (bytes * sizeof (uint8_t));
for (int i = 0; i < bytes; i++)
buffer[i] = 0;
}
void bit_array_resize (int new_n)
{
length = new_n;
bytes = (length + 7) / 8;
buffer = realloc (buffer, bytes * sizeof (uint8_t));
}
void bit_array_done (void)
{
free (buffer);
buffer = NULL;
length = 0;
bytes = 0;
}
void check_index (int i)
{
if (!buffer)
error (1, 0, "array not initialised");
if (i < 0 || i >= length)
error (1, 0, "index %d out of range (0, ..., %d)", i, length - 1);
}
void bit_array_set (int i, int value)
{
check_index (i);
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
if (value)
buffer[byte_index] |= mask;
else
buffer[byte_index] &= ~mask;
}
void bit_array_flip (int i)
{
check_index (i);
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
buffer[byte_index] ^= mask;
}
int bit_array_get (int i)
{
check_index (i);
int byte_index = i / 8;
int bit_index = i % 8;
uint8_t mask = 1 << bit_index;
if (buffer[byte_index] & mask)
return 1;
else
return 0;
}
void output (void)
{
for (int i = 0; i < length; i++)
{
if (i % 4 == 0)
printf (" ");
printf ("%d", bit_array_get (i));
}
printf ("\n");
}
int main (void)
{
bit_array_init (29);
output ();
bit_array_set (12, 1);
output ();
bit_array_flip (28);
output ();
bit_array_set (12, 0);
output ();
bit_array_flip (31);
output ();
bit_array_done ();
}
#include <stdio.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct animal
{
int type;
char *name;
} animal;
typedef struct with_wings
{
int type;
char *name;
int wings;
} with_wings;
typedef struct with_legs
{
int type;
char *name;
int legs;
} with_legs;
int main (void)
{
animal *a[2];
animal duck;
a[0] = &duck;
a[0]->type = WITH_WINGS;
a[0]->name = "duck";
((with_wings *) a[0])->wings = 2;
animal cow;
a[1] = &cow;
a[1]->type = WITH_LEGS;
a[1]->name = "cow";
((with_legs *) a[1])->legs = 4;
for (int i = 0; i < 2; i++)
if (a[i]->type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->name,
((with_legs *) a[i])-> legs);
else if (a[i]->type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->name,
((with_wings *) a[i])-> wings);
else
printf ("Error in animal: %s\n", a[i]->name);
return 0;
}
#include <stdio.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct animal
{
int type;
char *name;
} animal;
typedef struct with_wings
{
int type;
char *name;
int wings;
} with_wings;
typedef struct with_legs
{
int type;
char *name;
int legs;
} with_legs;
int main (void)
{
animal *a[2];
with_wings duck;
a[0] = (animal *) &duck;
a[0]->type = WITH_WINGS;
a[0]->name = "duck";
((with_wings *) a[0])->wings = 2;
with_legs cow;
a[1] = (animal *) &cow;
a[1]->type = WITH_LEGS;
a[1]->name = "cow";
((with_legs *) a[1])->legs = 4;
for (int i = 0; i < 2; i++)
if (a[i]->type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->name,
((with_legs *) a[i])-> legs);
else if (a[i]->type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->name,
((with_wings *) a[i])-> wings);
else
printf ("Error in animal: %s\n", a[i]->name);
return 0;
}
#include <stdio.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct animal
{
int type;
char *name;
} animal;
typedef struct with_wings
{
int type;
char *name;
int wings;
} with_wings;
typedef struct with_legs
{
int type;
char *name;
int legs;
} with_legs;
int main (void)
{
animal *a[2];
with_wings duck;
a[0] = (animal *) &duck;
duck.type = WITH_WINGS;
duck.name = "duck";
duck.wings = 2;
with_legs cow;
a[1] = (animal *) &cow;
cow.type = WITH_LEGS;
cow.name = "cow";
cow.legs = 4;
for (int i = 0; i < 2; i++)
if (a[i]->type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->name,
((with_legs *) a[i])-> legs);
else if (a[i]->type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->name,
((with_wings *) a[i])-> wings);
else
printf ("Error in animal: %s\n", a[i]->name);
return 0;
}
#include <stdio.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct
{
int type;
char *name;
} base;
typedef struct
{
int type;
char *name;
int wings;
} with_wings;
typedef struct
{
int type;
char *name;
int legs;
} with_legs;
typedef union
{
base b;
with_wings w;
with_legs l;
} animal;
int main (void)
{
animal *a[2];
animal duck;
a[0] = &duck;
duck.b.type = WITH_WINGS;
duck.b.name = "duck";
duck.w.wings = 2;
animal cow;
a[1] = &cow;
cow.b.type = WITH_LEGS;
cow.b.name = "cow";
cow.l.legs = 4;
for (int i = 0; i < 2; i++)
if (a[i]->b.type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->b.name,
a[i]->l.legs);
else if (a[i]->b.type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->b.name,
a[i]->w.wings);
else
printf ("Error in animal: %s\n", a[i]->b.name);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define ANIMAL 0
#define WITH_WINGS 1
#define WITH_LEGS 2
typedef struct
{
int type;
char *name;
} base;
typedef struct
{
int type;
char *name;
int wings;
} with_wings;
typedef struct
{
int type;
char *name;
int legs;
} with_legs;
typedef union
{
base b;
with_wings w;
with_legs l;
} animal;
animal *new_with_wings (char *name, int wings)
{
animal *a = malloc (sizeof (with_wings));
a->b.type = WITH_WINGS;
a->b.name = name;
a->w.wings = wings;
return a;
}
animal *new_with_legs (char *name, int legs)
{
animal *a = malloc (sizeof (with_legs));
a->b.type = WITH_LEGS;
a->b.name = name;
a->l.legs = legs;
return a;
}
int main (void)
{
animal *a[2] = { new_with_wings ("duck", 2),
new_with_legs ("cow", 4) };
for (int i = 0; i < 2; i++)
if (a[i]->b.type == WITH_LEGS)
printf ("A %s has %d legs.\n", a[i]->b.name,
a[i]->l.legs);
else if (a[i]->b.type == WITH_WINGS)
printf ("A %s has %d wings.\n", a[i]->b.name,
a[i]->w.wings);
else
printf ("Error in animal: %s\n", a[i]->b.name);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment