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

Musterlösung 7.11.2019

parent f3693cc4
No related branches found
No related tags found
No related merge requests found
File added
% hp-musterloesung-20191107.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: Arrays mit Zahlen, Datum-Bibliothek
\documentclass[a4paper]{article}
\usepackage{pgscript}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Musterlösung zu den Übungsaufgaben -- 7.\ November 2019}
\exercise{Arrays mit Zahlen}
\begin{minipage}[t]{0.4\textwidth}
Wir betrachten das folgende Programm\\
(Datei: \gitfile{hp}{20191107}{aufgabe-1.c}):
\begin{lstlisting}[gobble=6]
#include <stdio.h>
void f (int *s0, int *s1)
{
while (*s0 >= 0)
{
int *s = s1;
while (*s >= 0)
if (*s0 == *s++)
printf ("%d ", *s0);
s0++;
}
printf ("\n");
}
int main (void)
{
int a[] = { 10, 4, 3, 7, 12, 0, 1, -1 };
int b[] = { 7, 14, 0, 8, 9, 22, 10, -1 };
f (a, b);
return 0;
}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}[t]{0.55\textwidth}
\vspace*{-\bigskipamount}
\begin{enumerate}[\quad(a)]
\item
Was bewirkt die Funktion \lstinline{f},\\
und wie funktioniert sie?
\points{4}
% \item
% Von welcher Ordnung (Landau-Symbol) ist die Funktion?
% Begründen Sie Ihre Antwort.
%
% Wir beziehen uns hierbei auf die Anzahl der Vergleiche
% in Abhängigkeit von der Länge der Eingabedaten \lstinline{s0} und \lstinline{s1}.
% Für die Rechnung dürfen Sie beide Längen mit $n$ gleichsetzen,
% obwohl sie normalerweise nicht gleich sind.
% \points{2}
\item
Was passiert, wenn Sie beim Aufruf der Funktion für einen der
Parameter den Wert \lstinline{NULL} übergeben?
Begründen Sie Ihre Antwort.
\points{2}
\item
Was kann passieren, wenn Sie das Hauptprogramm wie folgt abändern
(\gitfile{hp}{20191107}{aufgabe-1c.c})?
Begründen Sie Ihre Antwort.
\begin{lstlisting}[gobble=8]
int main (void)
{
int a[] = { 10, 4, 3, 7, 12, 0, 1 };
int b[] = { 7, 14, 0, 8, 9, 22, 10 };
f (a, b);
return 0;
}
\end{lstlisting}
\points{2}
% \item
% Beschreiben Sie -- in Worten und/oder als C-Quelltext --, wie
% sich die Funktion \lstinline{f} effizienter gestalten läßt,
% wenn man die ihr übergebenen Arrays \lstinline{s0} und
% \lstinline{s1} als sortiert voraussetzt.
% \points{5}
%
% Hinweis: Wie würden Sie als Mensch die Aufgabe erledigen?
% \item
% Von welcher
% Ordnung (Landau-Symbol) ist Ihre effizientere Version der Funktion und warum?
% \points{2}
\end{enumerate}
\end{minipage}
\solution
\begin{enumerate}[\quad(a)]
\item
\textbf{Was bewirkt die Funktion \lstinline{f}, und wie funktioniert sie?}
Die Funktion gibt alle Zahlen aus, die sowohl im Array \lstinline{s0}
als auch im Array \lstinline{s1} vorkommen (Schnittmenge).
Dies geschieht, indem der Zeiger \lstinline{s0} das gesamte Array durchläuft
(äußere Schleife).
Für jedes Element des ersten Arrays durchläuft der Zeiger \lstinline{s}
das gesamte zweite Array (innere Schleife).
Auf diese Weise wird jedes Element von \lstinline{s0}
mit jedem von \lstinline{s1} verglichen und bei Gleichheit ausgegeben.
Um die Schleifen abbrechen zu können, enthalten beide Arrays
als Ende-Markierung eine negative Zahl (\lstinline{-1}).
\item
\textbf{Was passiert, wenn Sie beim Aufruf der Funktion für einen der
Parameter den Wert \lstinline{NULL} übergeben?
Begründen Sie Ihre Antwort.}
In dem Moment, wo auf den jeweiligen Parameter-Zeiger zugegriffen wird
(\lstinline{while (*s0 >= 0)} für \lstinline{s0} bzw.\
\lstinline{int *s = s1; while (*s >= 0)} für \lstinline{s1}),
kommt es zu einem Absturz (Speicherzugriffsfehler).
Die Dereferenzierung eines Zeigers mit dem Wert \lstinline{NULL}
ist nicht zulässig.
\item
\textbf{Was kann passieren, wenn Sie das Hauptprogramm wie folgt abändern
(\gitfile{hp}{20191107}{aufgabe-1c.c})?
Begründen Sie Ihre Antwort.}
\begin{minipage}{0.35\textwidth}
\begin{lstlisting}[gobble=10]
int main (void)
{
int a[] = { 10, 4, 3, 7, 12, 0, 1 };
int b[] = { 7, 14, 0, 8, 9, 22, 10 };
f (a, b);
return 0;
}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}{0.575\textwidth}
Durch die fehlenden Ende-Markierungen der Arrays
laufen die Schleifen immer weiter,
bis sie irgendwann zufällig auf Speicherzellen stoßen,
die sich als Ende-Markierungen interpretieren lassen (negative Zahlen).
Dadurch kann es zu einem Lesezugriff auf Speicher kommen,
für den das Programm kein Lesezugriffsrecht hat,
also zu einem Absturz (Speicherzugriffsfehler).
\end{minipage}
\end{enumerate}
\exercise{Datum-Bibliothek}
Schreiben Sie eine Bibliothek (= Sammlung von Deklarationen und Funktionen)
zur Behandlung von Datumsangaben.
Diese soll enthalten:
\begin{itemize}
\item
einen \lstinline{struct}-Datentyp \lstinline{date},
der eine Datumsangabe speichert,
\item
eine Funktion \lstinline{void date_print (date *d)}, die ein Datum ausgibt,
\item
eine Funktion \lstinline{int date_set (date *d, int day, int month, int year)},
die ein Datum auf einen gegebenen Tag setzt
und zurückgibt, ob es sich um ein gültiges Datum handelt (0 = nein, 1 = ja),
\item
eine Funktion \lstinline{void date_next (date *d)},
die ein Datum auf den nächsten Tag vorrückt.
\end{itemize}
Schreiben Sie auch ein Programm, das die o.\,a.\ Funktionen testet.
\solution
Die Datei \gitfile{hp}{20191107}{loesung-2.c}
enthält die Bibliothek zusammen mit einem Test-Programm.
Eine detaillierte Anleitung,
wie man auf die Funktion \lstinline{date_next()} kommt,
finden Sie im Skript zur Lehrveranstaltung, Datei \gitfile{hp}{script}{hp-2019ws.pdf},
ab Seite 29.
(Die Vorgehensweise,
die Bibliothek und das Hauptprogramm in dieselbe Datei zu schreiben,
hat den Nachteil,
daß man die Bibliothek in jedes weitere Programm, das sie benutzt,
kopieren und auch dort aktuell halten muß.
Eine sinnvollere Lösung wird demnächst in der Vorlesung vorgestellt werden.)
\end{document}
#include <stdio.h>
typedef struct
{
char day, month;
int year;
}
date;
int is_leap_year (int year)
{
if (year % 4 == 0)
if (year % 100 == 0)
if (year % 400 == 0)
return 1;
else
return 0;
else
return 1;
else
return 0;
}
int days_in_month (int month, int year)
{
if (month == 2)
if (is_leap_year (year))
return 29;
else
return 28;
else if (month == 4 || month == 6 || month == 9 || month == 11)
return 30;
else
return 31;
}
void date_print (date *d)
{
printf ("%02d.%02d.%04d", d->day, d->month, d->year);
}
int date_set (date *d, char day, char month, int year)
{
d->year = year;
if (month > 0 && month <= 12)
d->month = month;
else
return 0;
if (day > 0 && day <= days_in_month (month, year))
d->day = day;
else
return 0;
return 1;
}
void date_next (date *d)
{
d->day++;
if (d->day > days_in_month (d->month, d->year))
{
d->month++;
d->day = 1;
if (d->month > 12)
{
d->year++;
d->month = 1;
}
}
}
void check (char day, char month, int year)
{
date d;
if (date_set (&d, day, month, year))
{
date_print (&d);
printf (" --> ");
date_next (&d);
date_print (&d);
printf ("\n");
}
else
printf ("%02d.%02d.%04d: invalid date\n", day, month, year);
}
int main (void)
{
check (6, 11, 2018);
check (29, 11, 2018);
check (30, 11, 2018);
check (31, 11, 2018);
check (29, 12, 2018);
check (30, 12, 2018);
check (31, 12, 2018);
check (28, 2, 2016);
check (29, 2, 2016);
check (30, 2, 2016);
check (28, 2, 2015);
check (29, 2, 2015);
check (30, 2, 2015);
check (31, 12, 2008);
check (28, 2, 2000);
check (29, 2, 2000);
check (30, 2, 2000);
check (28, 2, 1900);
check (29, 2, 1900);
check (30, 2, 1900);
return 0;
}
README: Beispiele für Bit-Manipulation
......@@ -39,10 +39,11 @@ Musterlösungen:
* [17.10.2019: Schaltjahr ermitteln, Multiplikationstabelle, Fibonacci-Zahlen, fehlerhaftes Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191017/hp-musterloesung-20191017.pdf)
* [24.10.2019: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191024/hp-musterloesung-20191024.pdf)
* [31.10.2019: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191031/hp-musterloesung-20191031.pdf)
* [07.11.2019: Arrays mit Zahlen, Datum-Bibliothek](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191107/hp-musterloesung-20191107.pdf)
Tafelbilder:
------------
(keine)
* [07.11.2019: Beispiele für Bit-Manipulation](https://gitlab.cvh-server.de/pgerwinski/hp/raw/master/20191107/photo-20191107-172458.jpg)
Praktikumsunterlagen:
---------------------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment