add pages
@@ -0,0 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 5c323e642e12d9fbf3c26fc7fc5af7e8
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
@@ -0,0 +1,215 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>01 - Erste Schritte mit C — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="02: Funktionen, Datentyp “enum”" href="../P02_Funktionen_Datentyp_enum/README.html" />
|
||||
<link rel="prev" title="SNP Laboratories" href="../index.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="erste-schritte-mit-c">
|
||||
<h1>01 - Erste Schritte mit C<a class="headerlink" href="#erste-schritte-mit-c" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum erstellen Sie mehrere kleine C-Programme, in denen Sie Input- und Output-Funktionen der C Standard Library verwenden.</p>
|
||||
<p>Arbeiten Sie in Zweiergruppen und diskutieren Sie ihre Lösungsansätze miteinander, bevor Sie diese umsetzen.</p>
|
||||
<p>Bevor Sie mit den Programmieraufgaben beginnen, setzen Sie eine virtuelle Maschine mit der vorbereiteten Praktikumsumgebung auf.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum schreiben Sie selbst von Grund auf einige einfache C-Programme und wenden verschiedene Kontrollstrukturen an.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie können mit <em>#include</em> Funktionen der C Standard Library einbinden</p></li>
|
||||
<li><p>Sie können mit <em>#define</em> Macros definieren und diese anwenden</p></li>
|
||||
<li><p>Sie wenden die <em>Input-</em> und <em>Output-Funktionen</em> von C an, um Tastatur-Input einzulesen und formatierte Ausgaben zu machen.</p></li>
|
||||
<li><p>Sie verwenden die Kommandozeile, um ihren Sourcecode in ein ausführbares Programm umzuwandeln.</p></li>
|
||||
<li><p>Sie wenden for-und while-Loops sowie if-then-else-Verzweigungen an.</p></li>
|
||||
<li><p>Sie setzen eine Programmieraufgabe selbständig in ein funktionierendes Programm um.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-1-virtuelle-maschine">
|
||||
<h2>3. Aufgabe 1: virtuelle Maschine<a class="headerlink" href="#aufgabe-1-virtuelle-maschine" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Im Moodle-Kurs “Systemnahe Programmierung” finden Sie unter “Praktika” eine Installationsanleitung für die virtuelle Maschine, die wir Ihnen zur Verfügung stellen. Die virtuelle Maschine enthält ein Ubuntu Linux-Betriebssystem und die für das Praktikum benötigten Frameworks.</p>
|
||||
<p>Folgen sie der Anleitung, um die virtuelle Maschine auf ihrem Rechner zu installieren.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-2-hello-world">
|
||||
<h2>4. Aufgabe 2: Hello World<a class="headerlink" href="#aufgabe-2-hello-world" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Schreiben Sie ein C-Programm, das “Hello World” auf die Standardausgabe schreibt. Verwenden Sie die printf-Funktion aus der Standard Library. In den Vorlesungsfolien finden Sie bei Bedarf eine Vorlage.</p>
|
||||
<p>Erstellen sie das Source-File mit einem beliebigen Editor, sie benötigen nicht unbedingt eine IDE. Speichern Sie das Source-File mit der Endung <code class="docutils literal notranslate"><span class="pre">.c</span></code>.</p>
|
||||
<p>Um ihr Source-File zu kompilieren, verwenden Sie den GNU Compiler auf der Kommandozeile:</p>
|
||||
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span>$> gcc hello.c
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Der Compiler übersetzt ihr Programm in eine ausführbare Datei <code class="docutils literal notranslate"><span class="pre">a.out</span></code>, die Sie mit</p>
|
||||
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span>$> ./a.out
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>ausführen können. Sie können den Namen der ausführbaren Datei wählen, indem Sie die Option <code class="docutils literal notranslate"><span class="pre">-o</span></code> verwenden:</p>
|
||||
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span>$> gcc hello.c -o hello
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>erzeugt die ausführbare Datei <code class="docutils literal notranslate"><span class="pre">hello</span></code>.</p>
|
||||
<p>Verwenden Sie die Option <code class="docutils literal notranslate"><span class="pre">-Wall</span></code>, um alle Warnungen des Compilers auszugeben. Dies weist Sie auf allfällige Programmierfehler hin.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-3-tabellenausgabe">
|
||||
<h2>5. Aufgabe 3: Tabellenausgabe<a class="headerlink" href="#aufgabe-3-tabellenausgabe" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Schreiben Sie ein Programm in C, das von <code class="docutils literal notranslate"><span class="pre">stdin</span></code> einen Umrechnungsfaktor zwischen CHF und Bitcoin einliest und danach eine Tabelle von Franken- und Bitcoin-Beträgen ausgibt. Die Tabelle soll sauber formatiert sein, z.B. so:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Enter</span> <span class="n">conversion</span> <span class="n">rate</span> <span class="p">(</span><span class="mf">1.00</span> <span class="n">BTC</span> <span class="o">-></span> <span class="n">CHF</span><span class="p">):</span> <span class="mf">43158.47</span>
|
||||
<span class="mi">200</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.00463</span> <span class="n">BTC</span>
|
||||
<span class="mi">400</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.00927</span> <span class="n">BTC</span>
|
||||
<span class="mi">600</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.01390</span> <span class="n">BTC</span>
|
||||
<span class="mi">800</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.01854</span> <span class="n">BTC</span>
|
||||
<span class="mi">1000</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.02317</span> <span class="n">BTC</span>
|
||||
<span class="mi">1200</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.02780</span> <span class="n">BTC</span>
|
||||
<span class="mi">1400</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.03244</span> <span class="n">BTC</span>
|
||||
<span class="mi">1600</span> <span class="n">CHF</span> <span class="o"><--></span> <span class="mf">0.03707</span> <span class="n">BTC</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Verwenden Sie eine Schleife und die <code class="docutils literal notranslate"><span class="pre">printf</span></code>-Funktion für die Tabellenausgabe</p></li>
|
||||
<li><p>Definieren Sie ein Makro <code class="docutils literal notranslate"><span class="pre">NUM_ROWS</span></code>, um an zentraler Stelle im Source-Code zu definieren, wie viele Einträge die Tabelle in der Ausgabe haben soll.</p></li>
|
||||
<li><p>Lesen Sie den Umrechnungsfaktor mit der <code class="docutils literal notranslate"><span class="pre">scanf</span></code>-Funktion als <code class="docutils literal notranslate"><span class="pre">double</span></code> von der Kommandozeile ein.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-4-zeichen-und-worter-zahlen">
|
||||
<h2>6. Aufgabe 4: Zeichen und Wörter zählen<a class="headerlink" href="#aufgabe-4-zeichen-und-worter-zahlen" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Schreiben Sie ein C-Programm, welches die Zeichen und Wörter einer mit der Tastatur eingegebenen Zeile zählt. Wortzwischenräume sind entweder Leerzeichen (’ ‘) oder Tabulatoren (‘\t’). Die Eingabe der Zeile mit einem newline-character (‘\n’) abgeschlossen. Danach soll ihr Programm die Anzahl Zeichen und die Anzahl Wörter ausgeben und terminieren.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Verwenden Sie die <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">getchar(void)</span></code> Funktion aus der <code class="docutils literal notranslate"><span class="pre">stdio.h</span></code> Library, um die Zeichen einzeln einzulesen. Die Funktion <code class="docutils literal notranslate"><span class="pre">getchar</span></code> kehrt nicht gleich bei Eingabe des ersten Zeichens zurück, sondern puffert die Daten, bis die Eingabe einer kompletten Zeile mit Return abgeschlossen wird. Dann wird das erste Zeichen aus dem Puffer zurückgegeben und mit weiteren Aufrufen von getchar können die nachfolgenden Zeichen aus dem Puffer gelesen werden. Gibt <code class="docutils literal notranslate"><span class="pre">getchar</span></code> das Zeichen <code class="docutils literal notranslate"><span class="pre">\n</span></code> zurück, ist die Zeile komplett zurückgegeben und der Puffer ist wieder leer.</p></li>
|
||||
<li><p>Setzen Sie eine Schleife ein, die beim Zeichen ‘\n’ terminiert.</p></li>
|
||||
<li><p>Benutzen Sie if-then-else-Strukturen um die Wörter zu zählen.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>7. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">01 - Erste Schritte mit C</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-1-virtuelle-maschine">3. Aufgabe 1: virtuelle Maschine</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-2-hello-world">4. Aufgabe 2: Hello World</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-3-tabellenausgabe">5. Aufgabe 3: Tabellenausgabe</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-4-zeichen-und-worter-zahlen">6. Aufgabe 4: Zeichen und Wörter zählen</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">7. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../index.html" title="previous chapter">SNP Laboratories</a></li>
|
||||
<li>Next: <a href="../P02_Funktionen_Datentyp_enum/README.html" title="next chapter">02: Funktionen, Datentyp “enum”</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P01_Erste_Schritte_mit_C/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,412 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>02: Funktionen, Datentyp “enum” — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="03 - Bit Operationen, Struct, Typedef" href="../P03_Bit_Operation_struct_typedef/README.html" />
|
||||
<link rel="prev" title="01 - Erste Schritte mit C" href="../P01_Erste_Schritte_mit_C/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="funktionen-datentyp-enum">
|
||||
<h1>02: Funktionen, Datentyp “enum”<a class="headerlink" href="#funktionen-datentyp-enum" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<p><img alt="" src="../_images/random_number.png" /></p>
|
||||
<p>(Copyright Bild: xkcd.com)</p>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum sind zwei Themen im Fokus: Funktionen und der Datentyp enum.</p>
|
||||
<p>Funktionen sind der wesentlichste Bestandteil der C Programmierung welcher eine strukturierte Programmierung ermöglicht:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Eine Funktion ein Teil eines C Codes, der eine spezielle Aufgabe ausführt. Sie kann aus dem Hauptprogramm, oder aus anderen Funktionen, aufgerufen werden.</p></li>
|
||||
<li><p>Jede Funktion besitzt einen eindeutigen Namen, eine eindeutige Signatur (Typen und Reihenfolge der Parameter) und einen Rückgabewert (int falls nichts angegeben wird).</p></li>
|
||||
<li><p>Eine Funktion kann Werte aus dem aufrufendem Kontext übernehmen und bei Bedarf einen Wert an den aufrufenden Kontext zurückliefern.
|
||||
Beispiel einer Additions-Funktion:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">#include <stdio.h></span>
|
||||
|
||||
<span class="o">/*</span> <span class="n">Funktionsdeklaration</span> <span class="o">*/</span>
|
||||
<span class="nb">int</span> <span class="n">add</span><span class="p">(</span><span class="nb">int</span> <span class="n">a</span><span class="p">,</span> <span class="nb">int</span> <span class="n">b</span><span class="p">);</span>
|
||||
|
||||
<span class="nb">int</span> <span class="n">main</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nb">int</span> <span class="n">aa</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">bb</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">cc</span><span class="p">;</span>
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s2">"</span><span class="si">%a</span><span class="s2">a + %bb = </span><span class="si">%c</span><span class="s2">c"</span><span class="p">,</span> <span class="n">aa</span><span class="p">,</span> <span class="n">bb</span><span class="p">,</span> <span class="n">add</span><span class="p">(</span><span class="n">aa</span><span class="p">,</span> <span class="n">bb</span><span class="p">););</span>
|
||||
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="o">/*</span> <span class="n">Funktionsdefinition</span> <span class="o">*/</span>
|
||||
<span class="nb">int</span> <span class="n">add</span><span class="p">(</span><span class="nb">int</span> <span class="n">a</span><span class="p">,</span> <span class="nb">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Der Daten typt enum wird verwendet um die Lesbarkeit von Programmen zu erhöhen:</p>
|
||||
<p>Beispiel eines enum:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">enum</span> <span class="n">Ampeln</span> <span class="o">=</span> <span class="p">{</span><span class="n">rot</span> <span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">gelb</span><span class="p">,</span> <span class="n">gruen</span><span class="p">};</span>
|
||||
|
||||
<span class="nb">int</span> <span class="n">main</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="n">Ampeln</span> <span class="n">ampel1</span><span class="p">;</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">ampel1</span> <span class="o">==</span> <span class="n">rot</span><span class="p">)</span> <span class="p">{</span><span class="o">...</span><span class="p">}</span>
|
||||
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum lernen Sie Funktionen zu definieren und aufzurufen, sowie enum anzuwenden.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie können ein Programm schreiben welches aus mehreren Funktionen besteht.</p></li>
|
||||
<li><p>Sie können Funktionen deklarieren, definieren und aufrufen.</p></li>
|
||||
<li><p>Sie können enum Typen definieren und deren Werte bestimmen und abfragen.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgaben">
|
||||
<h2>3. Aufgaben<a class="headerlink" href="#aufgaben" title="Permalink to this headline">¶</a></h2>
|
||||
<figure class="align-center" id="kalender-108-v-ardfotogalerie">
|
||||
<a class="reference internal image-reference" href="../_images/kalender-108_v-ARDFotogalerie.jpg"><img alt="../_images/kalender-108_v-ARDFotogalerie.jpg" src="../_images/kalender-108_v-ARDFotogalerie.jpg" style="width: 600px;" /></a>
|
||||
</figure>
|
||||
<p>(Copyright Bild: www.planet-wissen.de)</p>
|
||||
<section id="aufgabe-1-tage-pro-monat">
|
||||
<h3>3.1 Aufgabe 1 Tage pro Monat<a class="headerlink" href="#aufgabe-1-tage-pro-monat" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In der ersten Aufgabe berechnen Sie die Tag pro Monat einer beliebigen Kombination Monat / Jahr.
|
||||
Erweitern Sie dazu das Programm um folgende Aspekte:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Bereichsprüfung von Jahr und Monat</p></li>
|
||||
<li><p>Funktion istSchaltjahr, welche berechnet, ob das Jahr eine Schaljahr ist</p></li>
|
||||
<li><p>Funktion tageProMonat, welche die Anzahl Tage des gegebenen Monats und Jahres berechnet.</p></li>
|
||||
</ul>
|
||||
<p>Vorgaben:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Die Funktion istSchaltjahr nimmt ein Integer (jahr) entgegen und gibt 1 im Falle eiens Schltjahres und 0 im andreren Fall zurück</p></li>
|
||||
<li><p>Die Funktion tageProMonat nimmt zwei integer (monat und jahr) entgegeben und gibt die Anzahl Tage als Integer zurück</p></li>
|
||||
<li><p>Die Jahreszahl, welche den Funktionen übergeben wird, muss überprüft werden und grösser gleich 1599 und kleiner als 10000 sein</p></li>
|
||||
<li><p>Der übergebene Monat muss grösser als 0 und kleine als 13 sein.</p></li>
|
||||
</ul>
|
||||
<p>Die Regeln für die Schaltjahrberechnung:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Schaltjahre sind alle Jahre, die durch 4 teilbar sind.</p></li>
|
||||
<li><p>Eine Ausnahme bilden die Jahrhunderte (1600, 1700…). Diese sind keine Schltjahre.</p></li>
|
||||
<li><p>zu den 100er gibt es ebenfalls Ausnahmen: Diese sind immer Schaltjahre, wenn sie durch 400 teilbar sind
|
||||
… also zum Beispiel 1600 ist eines, nicht jedoch 1700. Weiterführende Details finden Sie unter https://de.wikipedia.org/wiki/Gregorianischer_Kalender</p></li>
|
||||
</ul>
|
||||
<p>Gegeben ist die main Funktion des Programms. Ergänzen Sie die enum Definition und die fehlenden Funktionen:</p>
|
||||
<ul class="simple">
|
||||
<li><p>gibIntWert: Die Funktion soll einen Int Wert zurückgeben. Der Bereich, wie auch Fehleingaben sollen sollen berücksichtigt werden. (atoi unfd fgets sind hier hilfreich)</p></li>
|
||||
<li><p>istSchaltjahr: Die Funktion gibt 1 im Falle eines Schltjahr und o im anderen Falle zurück.</p></li>
|
||||
<li><p>tageProMonat: Die Funktion gibt den die Tage des Monats für das definierte Jahr zurück. Verwenden Sie die Switchanweisung , sowie den enum Datentypen</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>int main (int argc, char *argv[]) {
|
||||
|
||||
int monat, jahr;
|
||||
|
||||
// Monat einlesen und Bereich ueberpruefen
|
||||
monat = gibIntWert("Monat", 1, 12);
|
||||
jahr = gibIntWert("Jahr", 1600, 9999);
|
||||
|
||||
// Ausgabe zum Test
|
||||
printf("Monat: %d, Jahr: %d \n", monat, jahr);
|
||||
|
||||
// Ausgabe zum Test (hier mit dem ternaeren Operator "?:")
|
||||
printf("%d ist %s Schaltjahr\n", jahr, istSchaltjahr(jahr) ? "ein" : "kein");
|
||||
|
||||
// Ausgabe
|
||||
printf("Der Monat %02d-%d hat %d Tage.\n", monat, jahr, tageProMonat(jahr, monat));
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Tipp: Angenommen Sie verwenden den enum month_t { JAN=1, FEB, MAR, APR, MAI, JUN, JUL, AUG, SEP, OKT, NOV, DEZ };
|
||||
Dann können Sie im Programm direkt die Konstanten verwenden:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="o">...</span> <span class="o">//</span> <span class="n">schlecht</span> <span class="n">lesbar</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">monat</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="o">...</span> <span class="o">//</span> <span class="n">besserer</span> <span class="n">Variablenname</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">monat</span> <span class="o">==</span> <span class="n">FEB</span><span class="p">)</span> <span class="o">...</span> <span class="o">//</span> <span class="n">am</span> <span class="n">besten</span> <span class="n">lesbar</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Als Abnahme müssen die Tests unverändert ohne Fehler ausgeführt werden (<code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code>)</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-2-bestimmen-des-wochentags">
|
||||
<h3>3.2 Aufgabe 2 Bestimmen des Wochentags<a class="headerlink" href="#aufgabe-2-bestimmen-des-wochentags" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Erweitern Sie das vorgegebene zweite Programm Gerüst an den bezeichneten Stellen so, dass das Programm von der Kommando Zeile ein Argument entgegennimmt, es auf Gültigkeit überprüft und schliesslich den Wochentag für das gegebene Datum berechnet und ausgibt.
|
||||
Prüfen Sie die Umsetzung beider Teilaufgaben mittels make test.</p>
|
||||
<section id="teilaufgabe-argumente-parsen-und-auf-korrektheit-prufen">
|
||||
<h4>3.2.1 Teilaufgabe Argumente Parsen und auf Korrektheit prüfen<a class="headerlink" href="#teilaufgabe-argumente-parsen-und-auf-korrektheit-prufen" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Das Argument stellt ein gültiges Datum unseres Gregorianischen Kalenders dar (d.h. ein Datum ab Donnerstag, den 15. Oktober 1582, mit der Gregorianischen Schaltjahr Regel).
|
||||
Wenn kein Argument gegeben ist oder wenn das eingegebene Datum nicht gültig ist, soll das Programm einem Hilfetext auf stderr ausgeben und mit EXIT_FAILURE Exit Code terminieren. Wenn ein gültiges Datum erkannt wurde terminiert das Programm mit Exit Code EXIT_SUCCESS.</p>
|
||||
<section id="argument-format">
|
||||
<h5>3.2.1.1 Argument Format<a class="headerlink" href="#argument-format" title="Permalink to this headline">¶</a></h5>
|
||||
<p>Das Format des Kommando Zeilen Arguments soll yyyy-mm-dd sein, wobei yyyy für das vier-stellige Jahr, mm für einen 1-2-stelligen Monat (1…12) und dd für einen Tag des Monats, begin-nend mit 01. Z.B. 2020-02-29.</p>
|
||||
</section>
|
||||
<section id="korrektes-datum">
|
||||
<h5>3.2.1.2 Korrektes Datum<a class="headerlink" href="#korrektes-datum" title="Permalink to this headline">¶</a></h5>
|
||||
<p>Das Datum muss alle folgenden Bedingungen erfüllen damit es als korrekt erkannt wird:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Obergrenze für ein «sinnvolles» Datum ist das Jahr 9999</p></li>
|
||||
<li><p>es muss Gregorianisch sein, d.h. ab 15. Oktober 1582 (inklusive)</p></li>
|
||||
<li><p>es darf nur Monate von 1 für Januar bis 12 für Dezember beinhalten</p></li>
|
||||
<li><p>der Tag muss grösser oder gleich 1 sein</p></li>
|
||||
<li><p>der Tag darf nicht grösser als 31 sein für Monate mit einer Länge von 31 Tagen</p></li>
|
||||
<li><p>der Tag darf nicht grösser als 30 sein für Monate mit einer Länge von 30 Tagen</p></li>
|
||||
<li><p>der Tag darf für den Februar nicht grösser sein als 29 für ein Schaltjahr</p></li>
|
||||
<li><p>der Tag darf für den Februar nicht grösser sein als 28 für ein Nicht-Schaltjahr</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="vorgaben-an-die-umsetzung">
|
||||
<h5>3.2.1.3 Vorgaben an die Umsetzung<a class="headerlink" href="#vorgaben-an-die-umsetzung" title="Permalink to this headline">¶</a></h5>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Definieren Sie einen enum Typen mit (typedef) Namen month_t dessen Werte die Englischen 3-Zeichen Abkürzungen der Monate sind, nämlich Jan, Feb, … Dec und stellen Sie sicher dass die Abkürzungen für die uns geläufigen Monatsnummer stehen.</p></li>
|
||||
<li><p>Definierend Sie einen struct Typen mit (typedef) Namen date_t und den int Elementen year, month, day. Lesen Sie das Argument (falls vorhanden) via sscanf und dem Formatstring “%d-%d-%d” in die drei Elemente einer Date Variable. Siehe dazu die Hinweise im Anhang.</p></li>
|
||||
<li><p>Für die Berechnung der Monatslänge implementieren Sie die Hilfsfunktion is_leap_year(date_t date) (nach obigen Vorgaben). Der Return Wert 0 bedeutet «Kein Schaltjahr», 1 bedeutet «Schaltjahr».</p></li>
|
||||
<li><p>Implementieren Sie die Funktion <code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">get_month_length(date_t</span> <span class="pre">date)</span></code>. Diese soll für den Monat des Datums die Monatslänge (was dem letzten Tag des Monats ent-spricht) ausgeben – geben Sie 0 für ungültige Monatswerte zurück.</p></li>
|
||||
<li><p>Schliesslich implementieren Sie die Funktion int is_gregorian_date(date_t date) welche prüft, ob ein gegebenes Datum im Bereich 15. Oktober 1582 und dem Jahr 9999 ist (0 = nein, 1 = ja).</p></li>
|
||||
<li><p>Implementieren Sie eine Funktion int is_valid_date(date_t date), welche obige Bedingungen für ein gültiges Datum umsetzt. Der Return Wert 0 bedeutet «Kein gültiges Datum», 1 bedeutet «Gültiges Datum». Benutzen Sie für die Prüfung des Datums die <code class="docutils literal notranslate"><span class="pre">month_t</span></code> Werte wo immer möglich und sinnvoll. Verwenden Sie die oben implemen-tierten Hilfsfunktionen.</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
<section id="hinweise">
|
||||
<h5>3.2.1.4 Hinweise<a class="headerlink" href="#hinweise" title="Permalink to this headline">¶</a></h5>
|
||||
<p>Beachten Sie die Kommentare im Code für die geforderten Implementierungs-Details.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="teilaufgabe-wochentag-berechnung">
|
||||
<h4>3.2.2 Teilaufgabe Wochentag Berechnung<a class="headerlink" href="#teilaufgabe-wochentag-berechnung" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Schreiben Sie eine Funktion welche zu einem Datum den Wochentag berechnet.
|
||||
Die Formel wird Georg Glaeser zugeschrieben, möglicherweise angelehnt an eine Formel von Carl Friedrich Gauss.</p>
|
||||
<figure class="align-center" id="wochentagsberechnung">
|
||||
<a class="reference internal image-reference" href="../_images/Wochentagsberechnung.jpg"><img alt="../_images/Wochentagsberechnung.jpg" src="../_images/Wochentagsberechnung.jpg" style="width: 600px;" /></a>
|
||||
</figure>
|
||||
<p>(Quelle: https://de.wikipedia.org/wiki/Wochentagsberechnung)</p>
|
||||
<p>Hier ist eine für C abgewandelte Variante davon.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">weekday</span> <span class="o">=</span> <span class="p">((</span><span class="n">day</span> <span class="o">+</span> <span class="p">(</span><span class="mi">13</span> <span class="o">*</span> <span class="n">m</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="mi">5</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">y</span> <span class="o">/</span> <span class="mi">4</span> <span class="o">+</span> <span class="n">c</span> <span class="o">/</span> <span class="mi">4</span> <span class="o">-</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">c</span><span class="p">)</span> <span class="o">%</span> <span class="mi">7</span> <span class="o">+</span> <span class="mi">7</span><span class="p">)</span> <span class="o">%</span> <span class="mi">7</span>
|
||||
<span class="n">alle</span> <span class="n">Zahlen</span> <span class="n">sind</span> <span class="nb">int</span> <span class="n">Werte</span> <span class="n">und</span> <span class="n">alles</span> <span class="n">basiert</span> <span class="n">auf</span> <span class="nb">int</span><span class="o">-</span><span class="n">Arithmetik</span>
|
||||
<span class="n">m</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="n">month</span> <span class="o">+</span> <span class="mi">9</span><span class="p">)</span> <span class="o">%</span> <span class="mi">12</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">year</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">(</span><span class="n">für</span> <span class="n">month</span> <span class="o"><</span> <span class="n">Mar</span><span class="p">),</span> <span class="n">ansonsten</span> <span class="n">year</span>
|
||||
<span class="n">y</span> <span class="o">=</span> <span class="n">a</span> <span class="o">%</span> <span class="mi">100</span>
|
||||
<span class="n">c</span> <span class="o">=</span> <span class="n">a</span> <span class="o">/</span> <span class="mi">100</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Erweitern sie das Programm so, dass vor dem erfolgreichen Terminieren des Programms fol-gende Zeile (inklusive Zeilenumbruch) ausgegeben wird: yyyy-mm-dd is a Ddd, wobei yyyy für das Jahr, mm für die Nummer des Monats (01…12) und dd für den Tag im Monat (01…). Z.B. 2020-02-29 is a Sat.
|
||||
Vorgaben an die Umsetzung</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Definieren Sie einen enum Typen mit (typedef) Namen weekday_t dessen Werte die Englischen 3-Zeichen Abkürzungen der Tage sind, nämlich Sun, Mon, … Sat und stel-len Sie sicher dass die Abkürzungen für die Werte 0…6 stehen.</p></li>
|
||||
<li><p>Schreiben Sie eine Funktion weekday_t calculate_weekday(date_t date) nach der Beschreibung der obigen Formel. Das date Argument ist als gültig angenom-men, d.h. es ist ein Programmier-Fehler, wenn das Programm diese Funktion mit einem ungültigen Datum aufruft. Machen Sie dafür als erste Codezeile in der Funktion eine Zu-sicherung (assert(is_valid_date(date));)</p></li>
|
||||
<li><p>Schreiben Sie eine Funktion void print_weekday(weekday_t day), welche für jeden gülteigen Tag eine Zeile auf stdout schreibt mit den Englischen 3-Zeichen Ab-kürzungen für den Wochentag, z.B. Sonntag: Sun, Montag: Mon, etc. Wenn ein ungülti-ger Wert für day erkannt wird, soll assert(!”day is out-of-range”); aufgeru-fen werden.
|
||||
Hinweise
|
||||
• Für interessierte, siehe: https://de.wikipedia.org/wiki/Wochentagsberechnung</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>4. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden können.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Gewicht</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p>alle</p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>gibIntWert</p></td>
|
||||
<td class="text-left"><p>Eingabe, Bereichsüberprüfung korrekt</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>istSchaltjahr</p></td>
|
||||
<td class="text-left"><p>Funktion korrekt</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>TageProMonat</p></td>
|
||||
<td class="text-left"><p>Funktion korrekt</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>Aufgabe 2</p></td>
|
||||
<td class="text-left"><p>Fehlenden Teile ergänzt und lauffähig</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="anhang">
|
||||
<h2>5. Anhang<a class="headerlink" href="#anhang" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="sprach-element">
|
||||
<h3>5.1 Sprach Element<a class="headerlink" href="#sprach-element" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-int notranslate"><div class="highlight"><pre><span></span> ...
|
||||
} argc: Anzahl Einträge in argv.
|
||||
argv: Array von Command Line Argumenten.
|
||||
argv[0]: wie das Programm gestartet wurde
|
||||
argv[1]: erstes Argument
|
||||
…
|
||||
argv[argc-1]: letztes Argument
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
int res = sscanf(argv[1]
|
||||
, "%d-%d-%d"
|
||||
, &a, &b, &c
|
||||
);
|
||||
if (res != 3) {
|
||||
// Fehler Behandlung...
|
||||
// ...
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="beschreibung">
|
||||
<h3>5.2 Beschreibung<a class="headerlink" href="#beschreibung" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Siehe man 3 sscanf.
|
||||
Die Funktion sscanf gibt die Anzahl erfolgreich erkannte Argumente zurück. Unbedingt prüfen und angemessen darauf reagieren.
|
||||
Die gelesenen Werte werden in a, b und c, gespeichert, dazu müssen Sie die Adresse der Variablen übergeben. Mehr Details dazu werden später erklärt.
|
||||
fprintf(stderr, “Usage: %s…\n”, argv[0]); Siehe man 3 fprintf.
|
||||
Schreibt formatierten Text auf den stderr Stream.</p>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 15.02.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">02: Funktionen, Datentyp “enum”</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgaben">3. Aufgaben</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-1-tage-pro-monat">3.1 Aufgabe 1 Tage pro Monat</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-2-bestimmen-des-wochentags">3.2 Aufgabe 2 Bestimmen des Wochentags</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#teilaufgabe-argumente-parsen-und-auf-korrektheit-prufen">3.2.1 Teilaufgabe Argumente Parsen und auf Korrektheit prüfen</a><ul>
|
||||
<li class="toctree-l5"><a class="reference internal" href="#argument-format">3.2.1.1 Argument Format</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="#korrektes-datum">3.2.1.2 Korrektes Datum</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="#vorgaben-an-die-umsetzung">3.2.1.3 Vorgaben an die Umsetzung</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="#hinweise">3.2.1.4 Hinweise</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#teilaufgabe-wochentag-berechnung">3.2.2 Teilaufgabe Wochentag Berechnung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">4. Bewertung</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#anhang">5. Anhang</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#sprach-element">5.1 Sprach Element</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#beschreibung">5.2 Beschreibung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P01_Erste_Schritte_mit_C/README.html" title="previous chapter">01 - Erste Schritte mit C</a></li>
|
||||
<li>Next: <a href="../P03_Bit_Operation_struct_typedef/README.html" title="next chapter">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P02_Funktionen_Datentyp_enum/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,245 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Lösungsskizzen — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="losungsskizzen">
|
||||
<h1>Lösungsskizzen<a class="headerlink" href="#losungsskizzen" title="Permalink to this headline">¶</a></h1>
|
||||
<section id="aufgabe-1">
|
||||
<h2>Aufgabe 1<a class="headerlink" href="#aufgabe-1" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>/**
|
||||
* Tage Pro Monat
|
||||
*
|
||||
* Das Programm liest einen Monat (1-12) und ein Jahr (1600-2400) ein und
|
||||
* gibt die Anzahl der Tage dieses Monats aus.
|
||||
*
|
||||
* @author Gerrit Burkert, Adaptation bazz
|
||||
* @version 15-FEB-2013, 16-OCT-2017, 17-OCT-2019, 16-FEB-2022
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ERROR_IN_MONTH 1
|
||||
#define ERROR_IN_YEAR 2
|
||||
|
||||
///// Student Code
|
||||
|
||||
|
||||
|
||||
// Konstante Werte fuer die Monate
|
||||
// ===============================
|
||||
|
||||
enum { JAN=1, FEB, MAR, APR, MAI, JUN, JUL, AUG, SEP, OKT, NOV, DEZ };
|
||||
|
||||
|
||||
// Eingabe pruefen (0 ist vom atoi als Fehelcode verwendet und darf nicht verwendet werden)
|
||||
// ===============
|
||||
|
||||
int gibIntWert(char *name, int von, int bis) {
|
||||
|
||||
int wert;
|
||||
char wertS[20]; //
|
||||
|
||||
do {
|
||||
printf("%s: ", name);
|
||||
fgets(wertS, 20, stdin);
|
||||
wert = atoi(wertS);
|
||||
if (wert < von || wert > bis) {
|
||||
printf("Der Wert muss zwischen %d und %d sein.\n", von, bis);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
return wert;
|
||||
}
|
||||
|
||||
|
||||
// Schaltjahr bestimmen
|
||||
// ====================
|
||||
|
||||
int istSchaltjahr(int jahr){
|
||||
|
||||
if ( (jahr % 400 == 0) || ( (jahr %100 != 0) && (jahr % 4 ==0) ) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Berechnung Anzahl Tage pro Monat
|
||||
// ================================
|
||||
|
||||
int tageProMonat(int jahr, int monat) {
|
||||
|
||||
int anzTage;
|
||||
|
||||
// Tage pro Monat bestimmen
|
||||
switch (monat) {
|
||||
|
||||
// Monate mit 31 Tagen
|
||||
case JAN: case MAR: case MAI: case JUL: case AUG: case OKT: case DEZ:
|
||||
anzTage = 31;
|
||||
break;
|
||||
|
||||
// Monate mit 30 Tagen
|
||||
case APR: case JUN: case SEP: case NOV:
|
||||
anzTage = 30;
|
||||
break;
|
||||
|
||||
// Februar: 28 oder 29 Tage
|
||||
case FEB:
|
||||
|
||||
if (istSchaltjahr(jahr)) {
|
||||
anzTage = 29;
|
||||
} else {
|
||||
anzTage = 28;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return anzTage;
|
||||
}
|
||||
|
||||
///// END Student Code
|
||||
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
|
||||
int monat, jahr;
|
||||
|
||||
// Monat einlesen und Bereich ueberpruefen
|
||||
monat = gibIntWert("Monat", 1, 12);
|
||||
jahr = gibIntWert("Jahr", 1600, 9999);
|
||||
|
||||
// Ausgabe zum Test
|
||||
printf("Monat: %d, Jahr: %d \n", monat, jahr);
|
||||
|
||||
// Ausgabe zum Test (hier mit dem ternaeren Operator "?:")
|
||||
printf("%d ist %s Schaltjahr\n", jahr, istSchaltjahr(jahr) ? "ein" : "kein");
|
||||
|
||||
// Ausgabe
|
||||
printf("Der Monat %02d-%d hat %d Tage.\n", monat, jahr, tageProMonat(jahr, monat));
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="aufgabe-2">
|
||||
<h2>Aufgabe 2<a class="headerlink" href="#aufgabe-2" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Alter bestehender Boilerplate Code</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P02_Funktionen_Datentyp_enum/README_solution.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,372 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>03 - Bit Operationen, Struct, Typedef — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="04 - Modularisieren von C Code" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html" />
|
||||
<link rel="prev" title="02: Funktionen, Datentyp “enum”" href="../P02_Funktionen_Datentyp_enum/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="bit-operationen-struct-typedef">
|
||||
<h1>03 - Bit Operationen, Struct, Typedef<a class="headerlink" href="#bit-operationen-struct-typedef" title="Permalink to this headline">¶</a></h1>
|
||||
<section id="bit-operationen">
|
||||
<h2>1. Bit Operationen<a class="headerlink" href="#bit-operationen" title="Permalink to this headline">¶</a></h2>
|
||||
<p><img alt="" src="../_images/135oALYhkYyXB2aG0F-qrwA.jpeg" /></p>
|
||||
<p>Bit Operationen sind allgegenwärtig in den Computer-Wissenschaften und finden in vielen Disziplinen Anwendung. Folgend ein kleiner Auszug aus den wichtigsten Themen:</p>
|
||||
<ul>
|
||||
<li><p><strong>Bit Felder</strong>: Sind die effizienteste Art, etwas darzustellen, dessen Zustand durch mehrere “wahr” oder “falsch” definiert werden kann. Besonders auf Systemen mit begrenzten Ressourcen sollte jede überflüssige Speicher-Allozierung vermieden werden.</p>
|
||||
<p>Beispiel:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="c1">// primary colors</span>
|
||||
<span class="cp">#define BLUE 0b100</span>
|
||||
<span class="cp">#define GREEN 0b010</span>
|
||||
<span class="cp">#define RED 0b001</span>
|
||||
|
||||
<span class="c1">// mixed colors</span>
|
||||
<span class="cp">#define BLACK 0 </span><span class="cm">/* 000 */</span><span class="cp"></span>
|
||||
<span class="cp">#define YELLOW (RED | GREEN) </span><span class="cm">/* 011 */</span><span class="cp"></span>
|
||||
<span class="cp">#define MAGENTA (RED | BLUE) </span><span class="cm">/* 101 */</span><span class="cp"></span>
|
||||
<span class="cp">#define CYAN (GREEN | BLUE) </span><span class="cm">/* 110 */</span><span class="cp"></span>
|
||||
<span class="cp">#define WHITE (RED | GREEN | BLUE) </span><span class="cm">/* 111 */</span><span class="cp"></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<p><a class="reference external" href="https://de.wikipedia.org/wiki/Bitfeld">https://de.wikipedia.org/wiki/Bitfeld</a></p>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Kommunikation</strong>:</p>
|
||||
<ul>
|
||||
<li><p><strong>Prüfsummen/Paritätsbit</strong>: Übertragungsfehler und Integrität können bis zu einem definiertem Grad erkannt werden. Je nach Komplexität der Berechnung können mehrere Fehler erkannt oder auch korrigiert werden.
|
||||
<a class="reference external" href="https://de.wikipedia.org/wiki/Parit%C3%A4tsbit">https://de.wikipedia.org/wiki/Parit%C3%A4tsbit</a>, <a class="reference external" href="https://de.wikipedia.org/wiki/Pr%C3%BCfsumme">https://de.wikipedia.org/wiki/Pr%C3%BCfsumme</a></p></li>
|
||||
<li><p><strong>Stoppbit</strong>: Markieren bei asynchronen seriellen Datenübertragungen das Ende bzw. Start eines definierten Blocks.
|
||||
<a class="reference external" href="https://de.wikipedia.org/wiki/Stoppbit">https://de.wikipedia.org/wiki/Stoppbit</a></p></li>
|
||||
<li><p><strong>Datenflusssteuerung</strong>: Unterschiedliche Verfahren, mit denen die Datenübertragung von Endgeräten an einem Datennetz, die nicht synchron arbeiten, so gesteuert wird, dass eine möglichst kontinuierliche Datenübermittlung ohne Verluste erfolgen kann.
|
||||
<a class="reference external" href="https://de.wikipedia.org/wiki/Datenflusssteuerung">https://de.wikipedia.org/wiki/Datenflusssteuerung</a></p></li>
|
||||
<li><p>…</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><strong>Datenkompression</strong>: Bei der Datenkompression wird versucht, redundante Informationen zu entfernen. Dazu werden die Daten in eine Darstellung überführt, mit der sich alle – oder zumindest die meisten – Information in kürzerer Form darstellen lassen.
|
||||
<a class="reference external" href="https://de.wikipedia.org/wiki/Datenkompression">https://de.wikipedia.org/wiki/Datenkompression</a></p></li>
|
||||
<li><p><strong>Kryptographie</strong>: Konzeption, Definition und Konstruktion von Informationssystemen, die widerstandsfähig gegen Manipulation und unbefugtes Lesen sind. <a class="reference external" href="https://de.wikipedia.org/wiki/Verschl%C3%BCsselung">https://de.wikipedia.org/wiki/Verschl%C3%BCsselung</a></p></li>
|
||||
<li><p><strong>Grafik-Programmierung</strong>: XOR (oder ^) ist hier besonders interessant, weil eine zweite Eingabe derselben Eingabe die erste rückgängig macht (ein Beispiel dazu weiter unten: “Variablen tauschen, ohne Dritt-Variable
|
||||
“). Ältere GUIs verwendeten dies für die Hervorhebung von Auswahlen und andere Überlagerungen, um kostspielige Neuzeichnungen zu vermeiden. Sie sind immer noch nützlich in langsamen Grafikprotokollen (z. B. Remote-Desktop).</p></li>
|
||||
</ul>
|
||||
<section id="ubungen">
|
||||
<h3>1.1 Übungen<a class="headerlink" href="#ubungen" title="Permalink to this headline">¶</a></h3>
|
||||
<section id="basis-operationen">
|
||||
<h4>1. Basis Operationen<a class="headerlink" href="#basis-operationen" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Manipulationen von einzelnen Bits gehören zu den Basis Operationen und dienen als Grundlagen um weitere komplexere Konstrukte zu schaffen. Verfollständigen sie folgendes Beispiel mit den drei Basis Operationen:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
|
||||
|
||||
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">number</span><span class="p">;</span>
|
||||
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">bit</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span> <span class="c1">// bit at position 3</span>
|
||||
|
||||
<span class="c1">// Setting a bit</span>
|
||||
<span class="n">number</span> <span class="o">=</span> <span class="p">...;</span> <span class="c1">// solution: number |= 1 << bit;</span>
|
||||
|
||||
<span class="c1">// Clearing a bit</span>
|
||||
<span class="n">number</span> <span class="o">=</span> <span class="p">...;</span> <span class="c1">// solution: number &= ~(1 << bit);</span>
|
||||
|
||||
<span class="c1">// Toggling a bit</span>
|
||||
<span class="n">number</span> <span class="o">=</span> <span class="p">...;</span> <span class="c1">// solution; number ^= 1 << bit;</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">EXIT_SUCCESS</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="variablen-tauschen-ohne-dritt-variable">
|
||||
<h4>2. Variablen tauschen (ohne Dritt-Variable)<a class="headerlink" href="#variablen-tauschen-ohne-dritt-variable" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Zwei Variablen zu vertauschen scheint ein einfach lösbares Problem zu sein. Eine offensichtliche Variante wäre mittels einer temporären Variablen:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
|
||||
<span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
|
||||
|
||||
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
|
||||
<span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
|
||||
<span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s">"a: %d; b: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
|
||||
|
||||
<span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
|
||||
<span class="n">b</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span>
|
||||
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s">"a: %d; b: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
|
||||
<span class="k">return</span> <span class="n">EXIT_SUCCESS</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Es gibt aber auch eine Variante, die ohne zusätzliche Variable auskommt. Dabei wird die Tatsache, dass eine zweite XOR Operation eine erste XOR Operation rückgängig macht:</p>
|
||||
<p><em>0011 XOR 0100 = 0111</em></p>
|
||||
<p><em>0111 XOR 0100 = 0011</em></p>
|
||||
<p>Somit kommt man von einem XOR Resultat (<em>0111</em>) wieder auf beide Anfangs Operanden zurück indem man einfach ein zweites Mal mit einem Operanden eine XOR Verknüpfung macht. Damit kann ein Operand als Zwischenspeicher dienen und man muss nicht extra eine Zusatzvariable verwenden.</p>
|
||||
<p>Überlegen sie sich wie sie damit zwei Variablen vertauschen können ohne Zusatzvariable:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
|
||||
<span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
|
||||
|
||||
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
|
||||
<span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
|
||||
<span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s">"a: %d; b: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
|
||||
|
||||
|
||||
<span class="p">...</span>
|
||||
|
||||
<span class="cm">/* Solutions: </span>
|
||||
<span class="cm"> // a == 0011; b == 0100</span>
|
||||
<span class="cm"> a ^= b; // a == 0111; b == 0100</span>
|
||||
<span class="cm"> b ^= a; // a == 0111; b == 0011</span>
|
||||
<span class="cm"> a ^= b; // a == 0100; b == 0011</span>
|
||||
<span class="cm"> */</span>
|
||||
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s">"a: %d; b: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
|
||||
<span class="k">return</span> <span class="n">EXIT_SUCCESS</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="lower-uppercase">
|
||||
<h4>3. Lower- / Uppercase<a class="headerlink" href="#lower-uppercase" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
|
||||
<span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
|
||||
|
||||
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
|
||||
<span class="kt">char</span> <span class="n">word</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="s">"sREedEv"</span><span class="p">;</span>
|
||||
<span class="kt">char</span> <span class="o">*</span><span class="n">wordptr</span> <span class="o">=</span> <span class="o">&</span><span class="n">word</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
|
||||
|
||||
<span class="k">while</span><span class="p">(</span><span class="n">wordptr</span> <span class="o"><</span> <span class="o">&</span><span class="n">word</span><span class="p">[</span><span class="mi">7</span><span class="p">])</span> <span class="p">{</span>
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s">"UPPERCASE: %c</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">*</span><span class="n">wordptr</span> <span class="o">&</span> <span class="sc">'_'</span><span class="p">);</span> <span class="c1">// converts the char into uppercase regardless of the current casing</span>
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s">"LOWERCASE: %c</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">*</span><span class="n">wordptr</span> <span class="o">|</span> <span class="sc">' '</span><span class="p">);</span> <span class="c1">// converts the char into lowercase regardless of the current casing</span>
|
||||
<span class="n">wordptr</span><span class="o">++</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">EXIT_SUCCESS</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="prufen-auf-2-er-potenz">
|
||||
<h4>4. Prüfen auf 2-er Potenz<a class="headerlink" href="#prufen-auf-2-er-potenz" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
|
||||
<span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
|
||||
|
||||
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
|
||||
<span class="kt">int</span> <span class="n">a</span><span class="o">=</span><span class="mi">32</span><span class="p">;</span>
|
||||
<span class="k">if</span><span class="p">(</span><span class="n">a</span> <span class="o">></span> <span class="mi">0</span> <span class="o">&&</span> <span class="p">(</span><span class="n">a</span> <span class="o">&</span> <span class="p">(</span><span class="n">a</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span>
|
||||
<span class="n">printf</span><span class="p">(</span><span class="s">"%d is a power of 2"</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">return</span> <span class="n">EXIT_SUCCESS</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="struct-typedef">
|
||||
<h2>2. Struct & typedef<a class="headerlink" href="#struct-typedef" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="id1">
|
||||
<h3>2.1 Übungen<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h3>
|
||||
<section id="bit-operationen-rechner">
|
||||
<h4>1. Bit Operationen Rechner<a class="headerlink" href="#bit-operationen-rechner" title="Permalink to this headline">¶</a></h4>
|
||||
<ul>
|
||||
<li><p>Bitweise Operationen mit 2 Operanden</p></li>
|
||||
<li><p>Rechnung wird als ein String über scanf dem Programm übergeben</p>
|
||||
<ul>
|
||||
<li><p>String wird in Token zerstückelt und in struct gespeichert:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
|
||||
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">operand_1</span><span class="p">;</span>
|
||||
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">operand_2</span><span class="p">;</span>
|
||||
<span class="kt">char</span> <span class="n">operation</span><span class="p">;</span>
|
||||
<span class="p">}</span> <span class="n">Expression</span><span class="p">;</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Ausgabe in 3 verschiedenen Formaten:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Bin</span><span class="p">:</span>
|
||||
<span class="mi">0000</span><span class="s1">'0000'</span><span class="mi">0000</span><span class="s1">'0001</span>
|
||||
<span class="o">&</span> <span class="mi">0000</span><span class="s1">'0000'</span><span class="mi">0000</span><span class="s1">'0011</span>
|
||||
<span class="o">-------------------</span>
|
||||
<span class="mi">0000</span><span class="s1">'0000'</span><span class="mi">0000</span><span class="s1">'0001</span>
|
||||
|
||||
<span class="n">Hex</span>
|
||||
<span class="mh">0x01</span> <span class="o">&</span> <span class="mh">0x03</span> <span class="o">=</span> <span class="mh">0x01</span>
|
||||
|
||||
<span class="n">Dec</span>
|
||||
<span class="mi">1</span> <span class="o">&</span> <span class="mi">3</span> <span class="o">=</span> <span class="mi">1</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>4. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden können.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Gewicht</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p>alle</p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>gibIntWert</p></td>
|
||||
<td class="text-left"><p>Eingabe, Bereichsüberprüfung korrekt</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>istSchaltjahr</p></td>
|
||||
<td class="text-left"><p>Funktion korrekt</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>TageProMonat</p></td>
|
||||
<td class="text-left"><p>Funktion korrekt</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>Aufgabe 2</p></td>
|
||||
<td class="text-left"><p>Fehlenden Teile ergänzt und lauffähig</p></td>
|
||||
<td class="text-left"><p>1</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">03 - Bit Operationen, Struct, Typedef</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bit-operationen">1. Bit Operationen</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#ubungen">1.1 Übungen</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#basis-operationen">1. Basis Operationen</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#variablen-tauschen-ohne-dritt-variable">2. Variablen tauschen (ohne Dritt-Variable)</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#lower-uppercase">3. Lower- / Uppercase</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#prufen-auf-2-er-potenz">4. Prüfen auf 2-er Potenz</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#struct-typedef">2. Struct & typedef</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#id1">2.1 Übungen</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#bit-operationen-rechner">1. Bit Operationen Rechner</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P02_Funktionen_Datentyp_enum/README.html" title="previous chapter">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li>Next: <a href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html" title="next chapter">04 - Modularisieren von C Code</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P03_Bit_Operation_struct_typedef/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,542 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>04 - Modularisieren von C Code — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="modularisieren-von-c-code">
|
||||
<h1>04 - Modularisieren von C Code<a class="headerlink" href="#modularisieren-von-c-code" title="Permalink to this headline">¶</a></h1>
|
||||
<figure class="align-right" id="logo">
|
||||
<a class="reference internal image-reference" href="P04_Modularisieren_von_C_Code/zhaw_neg_P2945.jpg"><img alt="P04_Modularisieren_von_C_Code/zhaw_neg_P2945.jpg" src="P04_Modularisieren_von_C_Code/zhaw_neg_P2945.jpg" style="width: 100px;" /></a>
|
||||
</figure>
|
||||
<hr class="docutils" />
|
||||
<figure class="align-center" id="logo">
|
||||
<a class="reference internal image-reference" href="../_images/modularisieren_von_c_code.JPG"><img alt="../_images/modularisieren_von_c_code.JPG" src="../_images/modularisieren_von_c_code.JPG" style="width: 500px;" /></a>
|
||||
</figure>
|
||||
<hr class="docutils" />
|
||||
<section id="inhalt">
|
||||
<h2>Inhalt<a class="headerlink" href="#inhalt" title="Permalink to this headline">¶</a></h2>
|
||||
<p><a class="reference internal" href="#introduction"><span class="std std-ref">1. Übersicht</span></a></p>
|
||||
<p><a class="reference internal" href="#learning-objectives"><span class="std std-ref">2. Lernziele</span></a></p>
|
||||
<p><a class="reference internal" href="#task-01"><span class="std std-ref">3. Aufgabe 1: Modularisieren</span></a></p>
|
||||
<p><a class="reference internal" href="#task-02"><span class="std std-ref">4. Aufgabe 2: Makefile Regeln</span></a></p>
|
||||
<p><a class="reference internal" href="#grading"><span class="std std-ref">5. Bewertung</span></a></p>
|
||||
<p><a class="reference internal" href="#appendix"><span class="std std-ref">6. Anhang</span></a></p>
|
||||
<hr class="docutils" />
|
||||
</section>
|
||||
<section id="ubersicht">
|
||||
<span id="introduction"></span><h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum üben Sie modulare Programmierung indem Sie ein
|
||||
Java Programm (bestehend aus drei Java Files) in ein entsprechendes C
|
||||
Programm aus drei Modulen (aus je einem Header- und Implementations-
|
||||
File) übersetzen. Sie passen das Makefile so an, dass die
|
||||
entsprechenden Module mit kompiliert werden.</p>
|
||||
<p>In der zweiten Aufgabe erstellen Sie Makefile Regeln für die drei
|
||||
Schritte von den C Source Files zur graphischen Darstellung der
|
||||
Abhängigkeiten.</p>
|
||||
<figure class="align-center" id="uebersicht">
|
||||
<a class="reference internal image-reference" href="../_images/uebersicht.png"><img alt="../_images/uebersicht.png" src="../_images/uebersicht.png" style="width: 500px;" /></a>
|
||||
</figure>
|
||||
<p>Im Anhang ist eine Übersicht über die verwendeten File Formate gegeben.</p>
|
||||
</section>
|
||||
<section id="lernziele">
|
||||
<span id="learning-objectives"></span><h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum lernen Sie die Handgriffe um ein Programm zu modularisieren, d.h. in mehrere Module aufzuteilen.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie wissen, dass ein Modul aus einem C-File und einem passenden
|
||||
H-File besteht.</p></li>
|
||||
<li><p>Sie können Header Files korrekt strukturieren.</p></li>
|
||||
<li><p>Sie deklarieren im Header-File die öffentlichen Typen und Funktionen
|
||||
eines Moduls.</p></li>
|
||||
<li><p>Sie wissen wie <strong>Include Guards</strong> anzuwenden sind.</p></li>
|
||||
<li><p>Sie können Module im <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> zur Kompilation hinzufügen.</p></li>
|
||||
<li><p>Sie können <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> Regeln schreiben.</p></li>
|
||||
</ul>
|
||||
<p>Die Bewertung dieses Praktikums ist am Ende angegeben.</p>
|
||||
<p>Erweitern Sie die vorgegebenen Code Gerüste, welche im <code class="docutils literal notranslate"><span class="pre">git</span></code>
|
||||
Repository <code class="docutils literal notranslate"><span class="pre">snp-lab-code</span></code> verfügbar sind.</p>
|
||||
</section>
|
||||
<section id="aufgabe-1-modularisieren">
|
||||
<span id="task-01"></span><h2>3. Aufgabe 1: Modularisieren<a class="headerlink" href="#aufgabe-1-modularisieren" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Das zu ergänzende Programm dep2dot hat folgende Funktionalität:</p>
|
||||
<p>Ergänzen Sie in <strong><code class="docutils literal notranslate"><span class="pre">modularize/src</span></code></strong> den Code in <strong><code class="docutils literal notranslate"><span class="pre">triangle.c</span></code></strong>,
|
||||
<strong><code class="docutils literal notranslate"><span class="pre">read.h</span></code></strong>, <strong><code class="docutils literal notranslate"><span class="pre">read.c</span></code></strong>, <strong><code class="docutils literal notranslate"><span class="pre">rectang.h</span></code></strong> und <strong><code class="docutils literal notranslate"><span class="pre">rectang.c</span></code></strong> so
|
||||
dass die Tests erfolgreich durchlaufen. Die C Implementation soll
|
||||
dieselbe Funktionalität haben wie die gegebenen Java Files. Lehnen Sie
|
||||
sich so nahe wie möglich an die Java Files an.</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>In den Header-Files implementieren Sie den Include-Guard und
|
||||
deklarieren Sie die öffentlichen Funktionen und gegebenenfalls
|
||||
<strong><code class="docutils literal notranslate"><span class="pre">#define</span></code></strong>.</p></li>
|
||||
<li><p>In den Implementations-Files implementieren Sie die Funktionen.</p></li>
|
||||
</ol>
|
||||
<p>Die drei Java Files liegen in <strong><code class="docutils literal notranslate"><span class="pre">modularize/java</span></code></strong>.</p>
|
||||
<section id="tipps">
|
||||
<h3>Tipps<a class="headerlink" href="#tipps" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Implementieren Sie die Symbole welche vollständig in Grossbuchstaben
|
||||
geschrieben sind als <strong><code class="docutils literal notranslate"><span class="pre">#define</span></code></strong>.</p></li>
|
||||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">EOF</span></code></strong> kommt schon aus <strong><code class="docutils literal notranslate"><span class="pre">stdio.h</span></code></strong> und sollte deshalb nicht
|
||||
mehr definiert werden.</p></li>
|
||||
<li><p>Jene <strong><code class="docutils literal notranslate"><span class="pre">#define</span></code></strong> welche von andern Modulen verwendet werden
|
||||
kommen ins Header-File, die andern ins Implementations-File.</p></li>
|
||||
<li><p>Ein Grossteil des Java Codes aus den Methoden Bodies kann
|
||||
eins-zu-eins in C übernommen werden. Listen Sie auf welche
|
||||
Unterschiede es gibt:</p></li>
|
||||
</ul>
|
||||
<table>
|
||||
<style>
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th:first-of-type {
|
||||
width: 50%;
|
||||
}
|
||||
table th:nth-of-type(2) {
|
||||
width: 50%;
|
||||
}
|
||||
</style>
|
||||
<tr><th>Java</th><th>C</th></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kt">byte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kt">boolean</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kc">true</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kc">false</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span>System.out.print(…)
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span>System.out.println(…)
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="n">System</span><span class="p">.</span><span class="na">in</span><span class="p">.</span><span class="na">read</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kt">byte</span><span class="o">[]</span> <span class="n">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="n">BUFFERSIZE</span><span class="o">]</span><span class="p">;</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span>public class rectang {
|
||||
public boolean Rectangular(…)
|
||||
{ … }
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">read</span> <span class="p">{</span>
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getInt</span><span class="p">(...)</span>
|
||||
<span class="kd">throws</span> <span class="n">java</span><span class="p">.</span><span class="na">io</span><span class="p">.</span><span class="na">IOException</span>
|
||||
<span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="kd">class</span> <span class="nc">triangle</span> <span class="p">{</span>
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="p">)</span>
|
||||
<span class="kd">throws</span> <span class="n">java</span><span class="p">.</span><span class="na">io</span><span class="p">.</span><span class="na">IOException</span>
|
||||
<span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="n">read</span> <span class="n">ReadInt</span> <span class="o">=</span> <span class="k">new</span> <span class="n">read</span><span class="p">();</span>
|
||||
<span class="p">...</span>
|
||||
<span class="n">word</span> <span class="o">=</span> <span class="n">ReadInt</span><span class="p">.</span><span class="na">getInt</span><span class="p">(</span><span class="n">MAX_NUMBER</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="n">rectang</span> <span class="n">Rect</span> <span class="o">=</span> <span class="k">new</span> <span class="n">rectang</span><span class="p">();</span>
|
||||
<span class="p">...</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">Rect</span><span class="p">.</span><span class="na">Rectangular</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span> <span class="o">==</span> <span class="kc">true</span><span class="p">)</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span>
|
||||
<span class="s2">"-> Dreieck "</span> <span class="o">+</span> <span class="n">a</span> <span class="o">+</span> <span class="s2">"-"</span> <span class="o">+</span> <span class="n">b</span> <span class="o">+</span> <span class="s2">"-"</span> <span class="o">+</span> <span class="n">c</span>
|
||||
<span class="o">+</span> <span class="s2">" ist rechtwinklig"</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
<section id="aufgabe-2-makefile-regeln">
|
||||
<span id="task-02"></span><h2>4. Aufgabe 2: Makefile Regeln<a class="headerlink" href="#aufgabe-2-makefile-regeln" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die folgenden drei Schritte erstellen von einem C Source File eine
|
||||
graphische Darstellung der Abhängigkeiten:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">gcc</span> <span class="pre">...</span> <span class="pre">-H</span> <span class="pre">..</span> <span class="pre">file.c</span> <span class="pre">...</span> <span class="pre">2></span> <span class="pre">file.dep</span></code> (Regeln im Makefile bereits vorhanden)</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">dep2dot</span> <span class="pre">file.c</span> <span class="pre"><file.dep</span> <span class="pre">>file.dot</span></code> (in dieser Aufgabe zu erstellen)</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">dot</span> <span class="pre">-Tpng</span> <span class="pre">file.dot</span> <span class="pre">>file.png</span></code> (in dieser Aufgabe zu erstellen)</p></li>
|
||||
</ol>
|
||||
<p>Sie sollen für die Compiler-ähnlichen Programme <code class="docutils literal notranslate"><span class="pre">dep2dot</span></code> und <code class="docutils literal notranslate"><span class="pre">dot</span></code>
|
||||
Makefile Regeln schreiben.</p>
|
||||
<figure class="align-center" id="uebersicht">
|
||||
<a class="reference internal image-reference" href="../_images/uebersicht.png"><img alt="../_images/uebersicht.png" src="../_images/uebersicht.png" style="width: 500px;" /></a>
|
||||
</figure>
|
||||
<p>Das Programm <code class="docutils literal notranslate"><span class="pre">dep2dot</span></code> hat folgende Funktionalität:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Es liest von <code class="docutils literal notranslate"><span class="pre">stdin</span></code> die vom Compiler generierten
|
||||
Abhängigkeits-Daten in Form des <code class="docutils literal notranslate"><span class="pre">dep</span></code> Formates ein.</p></li>
|
||||
<li><p>Das erste und einzige Command Line Argument gibt das File an für
|
||||
welches die von <code class="docutils literal notranslate"><span class="pre">stdin</span></code> gelesenen Abhängigkeiten gelten.</p></li>
|
||||
<li><p>Auf <code class="docutils literal notranslate"><span class="pre">stdout</span></code> werden die Abhängigkeiten von <code class="docutils literal notranslate"><span class="pre">stdin</span></code> übersetzt als
|
||||
<code class="docutils literal notranslate"><span class="pre">dot</span></code>-File Format ausgegeben.</p></li>
|
||||
</ol>
|
||||
<p>Das Programm <code class="docutils literal notranslate"><span class="pre">dot</span></code> hat folgende Funktionalität:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Es liest die textuelle Beschreibung eines Graphen aus der
|
||||
übergebenen Datei (erstes Argument) ein.</p></li>
|
||||
<li><p>Auf <code class="docutils literal notranslate"><span class="pre">stdout</span></code> wird die grafische Darstellung der Beschreibung der
|
||||
Eingabe-Datei im <code class="docutils literal notranslate"><span class="pre">png</span></code>-File Format ausgegeben.</p></li>
|
||||
</ol>
|
||||
<p>Das <code class="docutils literal notranslate"><span class="pre">dep</span></code>-Format und das <code class="docutils literal notranslate"><span class="pre">dot</span></code>-Format sind im Anhang beschrieben.</p>
|
||||
<p>Sie können die Funktionalität des Programms <code class="docutils literal notranslate"><span class="pre">dep2dot</span></code> kennen lernen,
|
||||
indem Sie folgende Zeilen auf der Bash Shell ausführen. Das
|
||||
<code class="docutils literal notranslate"><span class="pre">dep.input</span></code> File ist Teil der automatisierten Test Suite im
|
||||
Verzeichnis <code class="docutils literal notranslate"><span class="pre">tests</span></code>:</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>bin/dep2dot dir/file <tests/dep.input >dep.dot
|
||||
dot -Tpng dep.dot >dep.png
|
||||
firefox dep.png
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Als Resultat sollte Firefox folgende Graphik darstellen:</p>
|
||||
<figure class="align-center" id="dep-dot">
|
||||
<a class="reference internal image-reference" href="../_images/dep_dot.png"><img alt="../_images/dep_dot.png" src="../_images/dep_dot.png" style="width: 150px;" /></a>
|
||||
</figure>
|
||||
<p>Definieren Sie im <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> Regeln, welche die einzelnen Schritte von
|
||||
den Source Files zu den <code class="docutils literal notranslate"><span class="pre">png</span></code> Files ausführen.</p>
|
||||
<p>Prüfen Sie schliesslich die Umsetzung Aufgabe mittels <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">dep-clean</span> <span class="pre">dep</span> <span class="pre">&&</span> <span class="pre">firefox</span> <span class="pre">src/*.png.</span></code></p>
|
||||
<section id="neue-regeln-hinzufugen">
|
||||
<h3>4.1 Neue Regeln hinzufügen<a class="headerlink" href="#neue-regeln-hinzufugen" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Führen Sie im <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> an den angegebenen Stellen folgende
|
||||
Ergänzungen durch</p>
|
||||
<ul class="simple">
|
||||
<li><p>definieren Sie eine Variable <code class="docutils literal notranslate"><span class="pre">DEPFILES</span></code> deren Inhalt die Liste alle
|
||||
Einträge der Variable <code class="docutils literal notranslate"><span class="pre">SOURCES</span></code> ist, wobei bei allen die Endung <code class="docutils literal notranslate"><span class="pre">.c</span></code>
|
||||
durch die Endung <code class="docutils literal notranslate"><span class="pre">.c.png</span></code> ersetzt ist</p></li>
|
||||
<li><p>fügen Sie zum <code class="docutils literal notranslate"><span class="pre">Pseudo-Target</span> <span class="pre">.PHONEY</span></code> das Target <code class="docutils literal notranslate"><span class="pre">dep</span></code> dazu – dies
|
||||
besagt, dass das später folgenden Target <code class="docutils literal notranslate"><span class="pre">dep</span></code> nicht ein File
|
||||
repräsentiert (ohne dieses Setting würde make gegebenenfalls nach
|
||||
einem File mit Namen <code class="docutils literal notranslate"><span class="pre">dep</span></code> suchen um zu entscheiden ob es
|
||||
inkrementell gebildet werden muss)</p></li>
|
||||
<li><p>schreiben Sie das Target <code class="docutils literal notranslate"><span class="pre">dep</span></code> gemäss der Beschreibung im Makefile</p></li>
|
||||
<li><p>schreiben Sie die Suffix Regel für die Übersetzung von <code class="docutils literal notranslate"><span class="pre">.png</span> <span class="pre"><-</span> <span class="pre">.dot</span></code> gemäss Vorgabe im <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> (als Inspiration, siehe auch die
|
||||
<code class="docutils literal notranslate"><span class="pre">%.c.dep:</span> <span class="pre">%.c</span></code> Suffix Regel weiter unten im <code class="docutils literal notranslate"><span class="pre">Makefile</span></code>) – erklären
|
||||
Sie was die Regel macht</p></li>
|
||||
<li><p>schreiben Sie die Suffix Regel für die Übersetzung von<code class="docutils literal notranslate"> <span class="pre">.dot</span> <span class="pre"><-</span> <span class="pre">.dep</span></code> gemäss Vorgabe im <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> – erklären Sie was die Regel
|
||||
macht</p></li>
|
||||
</ul>
|
||||
<p>Die Umsetzung der obigen Änderungen sind erfolgreich, wenn Sie
|
||||
folgende Shell Command Line erfolgreich ausführen können und in
|
||||
Firefox die Abhängigkeiten der C-Files von den Inclu-de Files
|
||||
dargestellt wird.</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">dep-clean</span> <span class="pre">dep</span> <span class="pre">&&</span> <span class="pre">firefox</span> <span class="pre">src/*.png.</span></code></p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="bewertung">
|
||||
<span id="grading"></span><h2>5. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Punkte</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p>1</p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>1</p></td>
|
||||
<td class="text-left"><p>Module einbinden, Header Files schreiben</p></td>
|
||||
<td class="text-left"><p>2</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>2</p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Makefile demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>2</p></td>
|
||||
<td class="text-left"><p>Neue Regeln hinzufügen</p></td>
|
||||
<td class="text-left"><p>2</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<section id="anhang">
|
||||
<span id="appendix"></span><h2>6. Anhang<a class="headerlink" href="#anhang" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="verwendete-zusatzliche-sprach-elemente">
|
||||
<h3>6.1 Verwendete zusätzliche Sprach Elemente<a class="headerlink" href="#verwendete-zusatzliche-sprach-elemente" title="Permalink to this headline">¶</a></h3>
|
||||
<table><tr><td>
|
||||
<p><strong>Sprach Element</strong></p>
|
||||
</td><td>
|
||||
<p><strong>Beschreibung</strong></p>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"v=%d"</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</td><td>
|
||||
<p>Formatierte Ausgabe auf den Standard Error Stream. Siehe <em><strong>man 3
|
||||
stderr</strong></em> und <em><strong>man 3 fprintf</strong></em>.</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
<section id="verarbeitung-und-verwendete-file-formate-a-name-file-formats-a">
|
||||
<h3>6.2 Verarbeitung und verwendete File Formate <a name="file_formats"></a><a class="headerlink" href="#verarbeitung-und-verwendete-file-formate-a-name-file-formats-a" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Das Programm in diesem Praktikum ist Teil für die graphische
|
||||
Darstellung von <code class="docutils literal notranslate"><span class="pre">#include</span></code> File Abhängigkeit von C Files.</p>
|
||||
<p>Den ersten Schritt für die Darstellung der <code class="docutils literal notranslate"><span class="pre">#include</span></code> File
|
||||
Abhängigkeiten bietet der Compiler. Der Compiler kann mittels der <code class="docutils literal notranslate"><span class="pre">-H</span></code>
|
||||
Command Line Option auf <code class="docutils literal notranslate"><span class="pre">stderr</span></code> ein Text File generieren, welches die
|
||||
tatsächlich verwendeten Header Files auflistet. Zusätzlich wird im
|
||||
Resultat die Verschachtelungstiefe der Includes angegeben.</p>
|
||||
<p>Im zweiten Schritt übersetzt das Programm (<code class="docutils literal notranslate"><span class="pre">dep2dot</span></code>) dieses
|
||||
Praktikums solche Dependency Files (<code class="docutils literal notranslate"><span class="pre">dep</span></code>) in eine Text Repräsentation
|
||||
der Abhängigkeiten (<code class="docutils literal notranslate"><span class="pre">dot</span></code>) welche in graphische Darstel-lung (<code class="docutils literal notranslate"><span class="pre">png</span></code>)
|
||||
übersetzt werden kann.</p>
|
||||
<p>Als Tool zur Übersetzung der <code class="docutils literal notranslate"><span class="pre">dot</span></code> Files in das <code class="docutils literal notranslate"><span class="pre">png</span></code> Format dient das
|
||||
<code class="docutils literal notranslate"><span class="pre">dot</span></code> Tool. Dieses Tool muss gegebenenfalls installiert werden:</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">sudo</span> <span class="pre">apt</span> <span class="pre">install</span> <span class="pre">graphviz</span></code></p>
|
||||
<p>Die <code class="docutils literal notranslate"><span class="pre">png</span></code> Files können dann z.B. in der Programm Dokumentation
|
||||
integriert werden (Darstellung zu Test Zwecken z.B. mittels <code class="docutils literal notranslate"><span class="pre">firefox</span> <span class="pre">file.png</span></code>).</p>
|
||||
<section id="dep-file">
|
||||
<h4>6.2.1 dep File<a class="headerlink" href="#dep-file" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Siehe: <code class="docutils literal notranslate"><span class="pre">man</span> <span class="pre">gcc</span></code></p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>-H Print the name of each header file used, <span class="k">in</span> addition to other
|
||||
normal activities. Each name is indented to show how deep <span class="k">in</span> the
|
||||
<span class="c1">#include stack it is. [...]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Das File wird auf <code class="docutils literal notranslate"><span class="pre">stderr</span></code> ausgegeben.</p>
|
||||
<p><strong>Beispiel File</strong> (für Abhängigkeiten des <code class="docutils literal notranslate"><span class="pre">main.c</span></code> Files des <code class="docutils literal notranslate"><span class="pre">dep2dot</span></code> Programms)</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>. /usr/include/stdio.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/libc-header-start.h
|
||||
... /usr/include/features.h
|
||||
.... /usr/include/x86_64-linux-gnu/sys/cdefs.h
|
||||
..... /usr/include/x86_64-linux-gnu/bits/wordsize.h
|
||||
..... /usr/include/x86_64-linux-gnu/bits/long-double.h
|
||||
.... /usr/include/x86_64-linux-gnu/gnu/stubs.h
|
||||
..... /usr/include/x86_64-linux-gnu/gnu/stubs-64.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/types.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/wordsize.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/typesizes.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/types/__FILE.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/types/FILE.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/libio.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/_G_config.h
|
||||
.... /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
.... /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h
|
||||
... /usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/stdio_lim.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/sys_errlist.h
|
||||
. /usr/include/stdlib.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/libc-header-start.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/floatn.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/floatn-common.h
|
||||
.... /usr/include/x86_64-linux-gnu/bits/long-double.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/stdlib-float.h
|
||||
. src/error.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
. src/data.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
. src/output.h
|
||||
Multiple include guards may be useful <span class="k">for</span>:
|
||||
/usr/include/x86_64-linux-gnu/bits/stdlib-float.h
|
||||
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h
|
||||
/usr/include/x86_64-linux-gnu/bits/typesizes.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs.h
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="dot-file">
|
||||
<h4>6.2.2 dot File<a class="headerlink" href="#dot-file" title="Permalink to this headline">¶</a></h4>
|
||||
<p><strong>Graphviz</strong> ist ein mächtiges Tool-Set welches Graphen, definiert in
|
||||
einem <code class="docutils literal notranslate"><span class="pre">dot</span></code>-Text File, automatisch anordnet und in <code class="docutils literal notranslate"><span class="pre">png</span></code>, <code class="docutils literal notranslate"><span class="pre">gif</span></code> und
|
||||
andere Formate übersetzt.</p>
|
||||
<p>Siehe die offizielle Web-Page
|
||||
<a class="reference external" href="https://www.graphviz.org/">https://www.graphviz.org/</a>.</p>
|
||||
<p>Es gibt als Teil dieses Tool-Sets verschiedene Übersetzer. Der hier
|
||||
verwendete ist der Basis-übersetzer: <code class="docutils literal notranslate"><span class="pre">dot</span></code>.</p>
|
||||
<p>Das <code class="docutils literal notranslate"><span class="pre">dot</span></code>-File Format kennt viele Möglichkeiten die Knoten und Kanten
|
||||
eines Graphen und de-ren Anordnung anzugeben.</p>
|
||||
<p>Der Vorteil eines solchen Tool-Sets ist, dass man den Inhalt (den
|
||||
Graphen) einfach definieren kann und sich nicht um das komplexe
|
||||
Problem der ansprechenden Visualisierung kümmern muss.</p>
|
||||
<p><strong>Beispiel File</strong> (<code class="docutils literal notranslate"><span class="pre">dot</span> <span class="pre">-Tpng</span> <span class="pre">sample.dot</span> <span class="pre">></span> <span class="pre">sample.png</span></code>)</p>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="n">digraph</span> <span class="n">G</span> <span class="p">{</span>
|
||||
<span class="n">node</span> <span class="p">[</span><span class="n">shape</span><span class="o">=</span><span class="n">box</span><span class="p">]</span>
|
||||
<span class="n">A</span> <span class="p">[</span><span class="n">label</span><span class="o">=</span><span class="s">"a.c"</span><span class="p">];</span>
|
||||
<span class="n">B</span> <span class="p">[</span><span class="n">label</span><span class="o">=</span><span class="s">"a.h"</span><span class="p">];</span>
|
||||
<span class="n">C</span> <span class="p">[</span><span class="n">label</span><span class="o">=</span><span class="s">"b.h"</span><span class="p">];</span>
|
||||
|
||||
<span class="n">subgraph</span> <span class="n">cluster_c0</span> <span class="p">{</span>
|
||||
<span class="n">label</span><span class="o">=</span><span class="s">"main"</span><span class="p">;</span> <span class="n">color</span><span class="o">=</span><span class="n">black</span><span class="p">;</span>
|
||||
<span class="n">A</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="n">subgraph</span> <span class="n">cluster_c1</span> <span class="p">{</span>
|
||||
<span class="n">label</span><span class="o">=</span><span class="s">"others"</span><span class="p">;</span> <span class="n">style</span><span class="o">=</span><span class="n">filled</span><span class="p">;</span> <span class="n">col</span><span class="o">-</span><span class="n">or</span><span class="o">=</span><span class="n">lightgrey</span><span class="p">;</span>
|
||||
<span class="p">{</span> <span class="n">B</span><span class="p">;</span> <span class="n">C</span><span class="p">;</span> <span class="n">rank</span><span class="o">=</span><span class="n">same</span><span class="p">;</span> <span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="n">A</span> <span class="o">-></span> <span class="n">B</span><span class="p">;</span>
|
||||
<span class="n">A</span> <span class="o">-></span> <span class="n">C</span><span class="p">;</span>
|
||||
<span class="n">B</span> <span class="o">-></span> <span class="n">C</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="png-file">
|
||||
<h4>6.2.3 png File<a class="headerlink" href="#png-file" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Das <code class="docutils literal notranslate"><span class="pre">png</span></code> Format ist ein verlustfrei komprimiertes Raster Graphik
|
||||
Format. Es wird oft in Web Pages verwendet.</p>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 15.02.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P04_Modularisieren_von_C_Code/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,289 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>04 - Modularisieren von C Code — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css" />
|
||||
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../search.html" />
|
||||
<link rel="next" title="05 - Arrays/Strings/TicTacToe" href="../../P05_TicTacToe/README.html" />
|
||||
<link rel="prev" title="03 - Bit Operationen, Struct, Typedef" href="../../P03_Bit_Operation_struct_typedef/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="modularisieren-von-c-code">
|
||||
<h1>04 - Modularisieren von C Code<a class="headerlink" href="#modularisieren-von-c-code" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum wird eine kleine Sammlung von Funktionen als Modul erstellt.</p>
|
||||
<p>In der ersten Aufgabe schreiben Sie zu einem bestehenden C Programm die notwendigen Header Files plus passen das Makefile so an, dass die entsprechenden Module mit kompiliert werden.</p>
|
||||
<p>In der zweiten Aufgabe erstellen Sie Makefile Regeln um aus Konfigurationsdateien graphischen Darstellungen zu erzeugen.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum lernen Sie die Handgriffe um ein Programm zu modularisieren, d.h. in mehrere Module aufzuteilen.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie wissen, dass ein Modul aus einem C-File und einem passenden H-File bestehen.</p></li>
|
||||
<li><p>Sie können Header Files korrekt strukturieren.</p></li>
|
||||
<li><p>Sie wissen wie <strong>Include Guards</strong> anzuwenden sind.</p></li>
|
||||
<li><p>Sie können Module im <strong>Makefile</strong> zur Kompilation hinzufügen.</p></li>
|
||||
<li><p>Sie können anhand einer Beschreibung Typen und Funktionen in den passenden Header Files deklarieren.</p></li>
|
||||
<li><p>Sie können <strong>Makefile</strong> Regeln schreiben.</p></li>
|
||||
</ul>
|
||||
<p>Die Bewertung dieses Praktikums ist am Ende angegeben.</p>
|
||||
<p>Erweitern Sie die vorgegebenen Code Gerüste, welche im <strong>git</strong> Repository <strong>snp-lab-code</strong> verfügbar sind.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-1-modularisieren">
|
||||
<h2>3. Aufgabe 1: Modularisieren<a class="headerlink" href="#aufgabe-1-modularisieren" title="Permalink to this headline">¶</a></h2>
|
||||
<p><img alt="" src="../../_images/P04_Aufgabenstellung.png" /></p>
|
||||
<section id="teilaufgabe-modules-einbinden-header-files-schreiben">
|
||||
<h3>3.1 Teilaufgabe Modules einbinden, Header Files schreiben<a class="headerlink" href="#teilaufgabe-modules-einbinden-header-files-schreiben" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>src/objects.h</p>
|
||||
<ul>
|
||||
<li><p>2 Datenstukturen definieren</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">point</span></code> mit 2 double für x und y Koordinate</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">line</span></code> mit 2 point</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>src/functions.h und .c</p>
|
||||
<ul>
|
||||
<li><p>2 Funktionen deklarieren und definieren</p></li>
|
||||
<li><p>Berechnung der Länge <code class="docutils literal notranslate"><span class="pre">get_length</span></code>einer Linie (Annahme: Koordinaten sind alle positiv)</p>
|
||||
<ul>
|
||||
<li><p>l = sqrt(h^ 2 + b^ 2)</p></li>
|
||||
<li><p>ev. muss hier in den Anhang <code class="docutils literal notranslate"><span class="pre">#include</span> <span class="pre"><math.h></span></code></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>Berechnung der Steigung <code class="docutils literal notranslate"><span class="pre">get_slope</span></code> der Linie gegenüber dem Koordinatensystem</p>
|
||||
<ul>
|
||||
<li><p>m = h / b</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>tests vorgeben</p></li>
|
||||
<li><p>src/objects.h</p>
|
||||
<ul>
|
||||
<li><p>Include Guard</p></li>
|
||||
<li><p>Includes</p></li>
|
||||
<li><p>Struct für Punkt und Linie</p></li>
|
||||
<li><p>Include Guard</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>src/functions.h</p>
|
||||
<ul>
|
||||
<li><p>Include Guard</p></li>
|
||||
<li><p>Includes</p></li>
|
||||
<li><p>Deklarationen der Funktionen für Berechnung der Länge und Steigung</p></li>
|
||||
<li><p>Include Guard</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>src/functions.c</p>
|
||||
<ul>
|
||||
<li><p>Includes</p></li>
|
||||
<li><p>Definitionen der Funktionen für Berechnung der Länge und Steigung</p></li>
|
||||
<li><p>Include Guard</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-2-makefile-regeln">
|
||||
<h2>4. Aufgabe 2: Makefile Regeln<a class="headerlink" href="#aufgabe-2-makefile-regeln" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Makefile ergänzen, damit Modul <code class="docutils literal notranslate"><span class="pre">functions</span></code> korrekt eingebunden und kompiliert wird.</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Kompilieren Sie das ganze mittels <strong>make clean default</strong>. Es sollten keine Compiler Fehler auftreten.</p></li>
|
||||
</ol>
|
||||
<section id="neue-regeln-hinzufugen">
|
||||
<h3>4.1 Neue Regeln hinzufügen<a class="headerlink" href="#neue-regeln-hinzufugen" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Vorraussetzung: tab2svg.sh aus Praktikum 3 wird um die Möglichkeit erweitert eine Linie zu zeichnen (<code class="docutils literal notranslate"><span class="pre">line:x1:y1:x2:y2:color</span></code>)</p></li>
|
||||
<li><p>Studierende erstellen</p>
|
||||
<ul>
|
||||
<li><p>mind. 2 Files <code class="docutils literal notranslate"><span class="pre">long.line</span></code> und <code class="docutils literal notranslate"><span class="pre">short.line</span></code> mit 2 unterschiedlichen Linien</p></li>
|
||||
<li><p>Makefile Regeln um aus einem File <code class="docutils literal notranslate"><span class="pre">.line</span></code> ein File <code class="docutils literal notranslate"><span class="pre">.svg</span></code> mit Hilfe des Scripts zu erstellen</p></li>
|
||||
<li><p>PHONY Regel <code class="docutils literal notranslate"><span class="pre">display</span></code> um beide <code class="docutils literal notranslate"><span class="pre">.svg</span></code> mit Firefox darzustellen</p>
|
||||
<ul>
|
||||
<li><p>Vorgabe: sie sollen eine Variable für die Input-Dateien nutzen</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Nachdem das Programm in Aufgabe 1 umgesetzt ist, geht es nun darum, im <strong>Makefile</strong> Regeln zu definieren welche die einzelnen Schritte von den Source Files zu den <strong>png</strong> Files ausführen.</p>
|
||||
<p>Prüfen Sie schliesslich die Umsetzung mittels <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">display</span></code>.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-3">
|
||||
<h2>5. Aufgabe 3<a class="headerlink" href="#aufgabe-3" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li><p>Studierende sollen Ausgabe von <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">doc</span></code> analysieren und die Include Diagramme erklären können</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">make</span> <span class="n">doc</span>
|
||||
<span class="n">firefox</span> <span class="n">doc</span><span class="o">/</span><span class="n">index</span><span class="o">.</span><span class="n">html</span> <span class="o">&</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>6. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="erweiterung-doxyfile-fur-abhangigkeitsanalyse">
|
||||
<h2>7. Erweiterung Doxyfile für Abhängigkeitsanalyse<a class="headerlink" href="#erweiterung-doxyfile-fur-abhangigkeitsanalyse" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">---</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">vagrant</span><span class="o">/</span><span class="n">huno</span><span class="o">/</span><span class="n">snp</span><span class="o">-</span><span class="n">new</span><span class="o">/</span><span class="n">snp</span><span class="o">/</span><span class="n">praktika</span><span class="o">/</span><span class="n">Shared</span><span class="o">/</span><span class="n">work</span><span class="o">/</span><span class="n">Doxyfile</span> <span class="mi">2022</span><span class="o">-</span><span class="mi">02</span><span class="o">-</span><span class="mi">07</span> <span class="mi">21</span><span class="p">:</span><span class="mi">16</span><span class="p">:</span><span class="mf">42.343302707</span> <span class="o">+</span><span class="mi">0100</span>
|
||||
<span class="o">+++</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">vagrant</span><span class="o">/</span><span class="n">snp</span><span class="o">/</span><span class="n">Doxyfile</span> <span class="mi">2022</span><span class="o">-</span><span class="mi">02</span><span class="o">-</span><span class="mi">07</span> <span class="mi">22</span><span class="p">:</span><span class="mi">22</span><span class="p">:</span><span class="mf">36.266839126</span> <span class="o">+</span><span class="mi">0100</span>
|
||||
<span class="o">@@</span> <span class="o">-</span><span class="mi">297</span><span class="p">,</span><span class="mi">14</span> <span class="o">+</span><span class="mi">297</span><span class="p">,</span><span class="mi">14</span> <span class="o">@@</span>
|
||||
<span class="n">UML_LOOK</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="n">UML_LIMIT_NUM_FIELDS</span> <span class="o">=</span> <span class="mi">10</span>
|
||||
<span class="n">TEMPLATE_RELATIONS</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="o">-</span><span class="n">INCLUDE_GRAPH</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="o">-</span><span class="n">INCLUDED_BY_GRAPH</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="o">+</span><span class="n">INCLUDE_GRAPH</span> <span class="o">=</span> <span class="n">YES</span>
|
||||
<span class="o">+</span><span class="n">INCLUDED_BY_GRAPH</span> <span class="o">=</span> <span class="n">YES</span>
|
||||
<span class="n">CALL_GRAPH</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="n">CALLER_GRAPH</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="o">-</span><span class="n">GRAPHICAL_HIERARCHY</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="o">-</span><span class="n">DIRECTORY_GRAPH</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="o">+</span><span class="n">GRAPHICAL_HIERARCHY</span> <span class="o">=</span> <span class="n">YES</span>
|
||||
<span class="o">+</span><span class="n">DIRECTORY_GRAPH</span> <span class="o">=</span> <span class="n">YES</span>
|
||||
<span class="n">DOT_IMAGE_FORMAT</span> <span class="o">=</span> <span class="n">png</span>
|
||||
<span class="o">-</span><span class="n">INTERACTIVE_SVG</span> <span class="o">=</span> <span class="n">NO</span>
|
||||
<span class="o">+</span><span class="n">INTERACTIVE_SVG</span> <span class="o">=</span> <span class="n">YES</span>
|
||||
<span class="n">DOT_PATH</span> <span class="o">=</span>
|
||||
<span class="n">DOTFILE_DIRS</span> <span class="o">=</span>
|
||||
<span class="n">MSCFILE_DIRS</span> <span class="o">=</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../../index.html">
|
||||
<img class="logo" src="../../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">04 - Modularisieren von C Code</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-1-modularisieren">3. Aufgabe 1: Modularisieren</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#teilaufgabe-modules-einbinden-header-files-schreiben">3.1 Teilaufgabe Modules einbinden, Header Files schreiben</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-2-makefile-regeln">4. Aufgabe 2: Makefile Regeln</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#neue-regeln-hinzufugen">4.1 Neue Regeln hinzufügen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-3">5. Aufgabe 3</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">6. Bewertung</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#erweiterung-doxyfile-fur-abhangigkeitsanalyse">7. Erweiterung Doxyfile für Abhängigkeitsanalyse</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../../P03_Bit_Operation_struct_typedef/README.html" title="previous chapter">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li>Next: <a href="../../P05_TicTacToe/README.html" title="next chapter">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../../_sources/P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,424 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>05 - SNP: TicTacToe — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="snp-tictactoe">
|
||||
<h1><a class="toc-backref" href="#id1">05 - SNP: TicTacToe</a><a class="headerlink" href="#snp-tictactoe" title="Permalink to this headline">¶</a></h1>
|
||||
<a class="reference internal image-reference" href="P05_TicTacToe/zhaw_neg_P2945.jpg"><img alt="P05_TicTacToe/zhaw_neg_P2945.jpg" class="align-right" src="P05_TicTacToe/zhaw_neg_P2945.jpg" style="width: 25.0px; height: 25.0px;" /></a>
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="#snp-tictactoe" id="id1">05 - SNP: TicTacToe</a></p>
|
||||
<ul>
|
||||
<li><p><a class="reference internal" href="#ubersicht" id="id2">Übersicht</a></p></li>
|
||||
<li><p><a class="reference internal" href="#lernziele" id="id3">Lernziele</a></p></li>
|
||||
<li><p><a class="reference internal" href="#aufgabe-tictactoe" id="id4">Aufgabe: TicTacToe</a></p>
|
||||
<ul>
|
||||
<li><p><a class="reference internal" href="#test-driven-development" id="id5">Test-Driven-Development</a></p></li>
|
||||
<li><p><a class="reference internal" href="#test-model-init" id="id6">3.2 test_model_init</a></p></li>
|
||||
<li><p><a class="reference internal" href="#test-model-get-state-test-model-get-winner" id="id7">3.3 test_model_get_state test_model_get_winner</a></p></li>
|
||||
<li><p><a class="reference internal" href="#test-model-can-move" id="id8">3.4 test_model_can_move</a></p></li>
|
||||
<li><p><a class="reference internal" href="#test-model-move-test-model-get-win-line" id="id9">3.5 test_model_move test_model_get_win_line</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><a class="reference internal" href="#bewertung" id="id10">4. Bewertung</a></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<section id="ubersicht">
|
||||
<h2><a class="toc-backref" href="#id2">Übersicht</a><a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum erweitern Sie einen Programm Rahmen zu einem funktionierenden TicTacToe Spiel. Bei TicTacToe legen zwei Spieler abwechselnd auf einem 3x3 Brett einen Stein, bis ein Spieler mit einer horizontalen, vertikalen oder diagonalen Linie gewinnt, oder alle Felder besetzt sind.</p>
|
||||
<img alt="../_images/TicTacToe.svg" src="../_images/TicTacToe.svg" /><p>In der Aufgabe implementieren Sie die fehlenden Funktionen bis alle Tests erfolgreich durchlau-fen. Die gewählte Vorgehensweise ist somit TDD – Test-Driven-Development: es existieren zuerst Tests welche alle fehlschlagen. Schrittweise werden die Funktionen implementiert bis alle Tests erfolgreich durchlaufen.</p>
|
||||
<p>Wenn die Tests erfolgreich durchlaufen, wird auch das Programm funktionieren und Sie können jemanden mit dem Spiel herausfordern 😉.</p>
|
||||
</section>
|
||||
<section id="lernziele">
|
||||
<h2><a class="toc-backref" href="#id3">Lernziele</a><a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum lernen Sie den Zugriff auf Arrays.</p>
|
||||
<blockquote>
|
||||
<div><ul class="simple">
|
||||
<li><p>Sie können anhand einer Beschreibung im Code die fehlenden Funktionen implementieren wo auf Arrays zugegriffen wird.</p></li>
|
||||
</ul>
|
||||
</div></blockquote>
|
||||
<p>Die Bewertung dieses Praktikums ist am Ende angegeben.</p>
|
||||
<p>Erweitern Sie die vorgegebenen Code Gerüste, welche im git Repository snp-lab-code verfügbar sind.</p>
|
||||
</section>
|
||||
<section id="aufgabe-tictactoe">
|
||||
<h2><a class="toc-backref" href="#id4">Aufgabe: TicTacToe</a><a class="headerlink" href="#aufgabe-tictactoe" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Das zu ergänzende Programm tic-tac-toe hat folgende Funktionalität:
|
||||
#. es stellt ein 3x3 TicTacToe Spielbrett auf dem Terminal dar
|
||||
#. es liest von stdin eine Ziffer 0…9 ein, wobei 0 für Programm-Terminieren, die übrigen Ziffern für die Wahl eines Feldes stehen
|
||||
#. der erste Spielzug wird von Spieler A geführt, danach wechselt das Programm zwischen den Spielern A und B
|
||||
# bei Gewinn oder bei vollem Brett ist das Spiel vorbei</p>
|
||||
<p>Wenn die Aufgabe erfolgreich umgesetzt ist, können Sie das Spiel ausführen:
|
||||
<code class="docutils literal notranslate"><span class="pre">`bash</span>
|
||||
<span class="pre">bin/tic-tac-toe</span>
|
||||
<span class="pre">`</span></code></p>
|
||||
<p>Als Abnahme müssen die Tests unverändert ohne Fehler ausgeführt werden (<code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code>).</p>
|
||||
<p>Die Architektur des Programms folgt dem MVC – Model-View-Control Paradigma. Dieses Paradigma besagt, dass die View (Eingabe und Darstellung) über Control (Vermittler) das Modell (die eigentliche Programm-Logik) steuert und darstellt. Dabei sind folgende Abhängigkeiten gegeben:</p>
|
||||
<img alt="../_images/MVC_pattern.svg" src="../_images/MVC_pattern.svg" /><section id="test-driven-development">
|
||||
<h3><a class="toc-backref" href="#id5">Test-Driven-Development</a><a class="headerlink" href="#test-driven-development" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Das Programm besteht aus folgenden Files:</p>
|
||||
<table class="docutils align-default">
|
||||
<colgroup>
|
||||
<col style="width: 50%" />
|
||||
<col style="width: 50%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr class="row-odd"><td><p>Datei</p></td>
|
||||
<td><p>ToDo</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>Makefile</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>tests/tests.c</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>src/main.c</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>src/view.h</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>src/view.c</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>src/control.h</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>src/control.c</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>src/model.h</p></td>
|
||||
<td><ul class="simple">
|
||||
<li></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>src/model.c</p></td>
|
||||
<td><p>siehe unten</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> aus:</p></li>
|
||||
</ol>
|
||||
<blockquote>
|
||||
<div><p>Suite: lab test
|
||||
Test: test_model_init
|
||||
init_model:… 0/0 FAILED</p>
|
||||
<blockquote>
|
||||
<div><ol class="arabic simple">
|
||||
<li><p>tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)</p></li>
|
||||
</ol>
|
||||
</div></blockquote>
|
||||
<dl>
|
||||
<dt>Test: test_model_get_state …FAILED</dt><dd><ol class="arabic simple">
|
||||
<li><p>tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)</p></li>
|
||||
</ol>
|
||||
</dd>
|
||||
<dt>Test: test_model_get_winner …FAILED</dt><dd><ol class="arabic simple">
|
||||
<li><p>tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)</p></li>
|
||||
</ol>
|
||||
</dd>
|
||||
<dt>Test: test_model_can_move …FAILED</dt><dd><ol class="arabic simple">
|
||||
<li><p>tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)</p></li>
|
||||
</ol>
|
||||
</dd>
|
||||
<dt>Test: test_model_move …FAILED</dt><dd><ol class="arabic simple">
|
||||
<li><p>tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)</p></li>
|
||||
</ol>
|
||||
</dd>
|
||||
<dt>Test: test_model_get_win_line …FAILED</dt><dd><ol class="arabic simple">
|
||||
<li><p>tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)</p></li>
|
||||
</ol>
|
||||
</dd>
|
||||
<dt>Run Summary: Type Total Ran Passed Failed Inactive</dt><dd><blockquote>
|
||||
<div><dl class="simple">
|
||||
<dt>suites 1 1 n/a 0 0</dt><dd><p>tests 6 6 0 6 0</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</div></blockquote>
|
||||
<p>asserts 6 6 0 6 n/a</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</div></blockquote>
|
||||
<p>2. Konzentrieren Sie sich auf den ersten Test der fehlschlägt. Dies ist ein Unit Test, welcher die Funktion <strong>model_init()</strong> prüft. Suchen Sie die Funktion in <strong>src/model.h</strong> und <strong>src/model.c</strong>.
|
||||
Was ist die geforderte Funktionalität und wie ist sie implementiert?
|
||||
Suchen Sie die darin aufgerufene <strong>model_init()</strong> Funktion und implementieren Sie diese.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">model_init</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">instance</span><span class="p">);</span>
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// set all fields of the board to model_state_none</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE }</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple" start="3">
|
||||
<li><p>Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> und korrigieren Sie obige Funktion, bis der Test nicht mehr fehlschlägt.</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
<section id="test-model-init">
|
||||
<h3><a class="toc-backref" href="#id6">3.2 test_model_init</a><a class="headerlink" href="#test-model-init" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Gehen Sie analog zur ersten Teilaufgabe vor:
|
||||
1. Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> aus.
|
||||
2. Suchen Sie die Funktion <strong>model_get_state()</strong> in <strong>model.h</strong> und <strong>model.c</strong>.
|
||||
3. Implementieren Sie die intern benutzte Funktion <strong>get_state()</strong> gemäss der Anleitung im Code.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">model_state_t</span> <span class="nf">model_get_state</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">,</span> <span class="n">model_pos_t</span> <span class="n">pos</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">instance</span><span class="p">);</span>
|
||||
<span class="n">assert_pos</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
|
||||
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// replace the stub implementation my access to the field at the given position.</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
|
||||
<span class="k">return</span> <span class="n">model_state_none</span><span class="p">;</span> <span class="c1">// stub</span>
|
||||
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple" start="4">
|
||||
<li><p>Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> und korrigieren Sie, bis die beiden Tests nicht mehr fehlschlagen.</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
<section id="test-model-get-state-test-model-get-winner">
|
||||
<h3><a class="toc-backref" href="#id7">3.3 test_model_get_state test_model_get_winner</a><a class="headerlink" href="#test-model-get-state-test-model-get-winner" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Gehen Sie analog zur ersten Teilaufgabe vor:
|
||||
1. Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> aus.
|
||||
2. Suchen Sie die Funktion <strong>model_get_state()</strong> in <strong>model.h</strong> und <strong>model.c</strong>.
|
||||
3. Implementieren Sie die intern benutzte Funktion <strong>get_state()</strong> gemäss der Anleitung im Code.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">model_state_t</span> <span class="nf">model_get_state</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">,</span> <span class="n">model_pos_t</span> <span class="n">pos</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">instance</span><span class="p">);</span>
|
||||
<span class="n">assert_pos</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
|
||||
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// replace the stub implementation my access to the field at the given position.</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
|
||||
<span class="k">return</span> <span class="n">model_state_none</span><span class="p">;</span> <span class="c1">// stub</span>
|
||||
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="test-model-can-move">
|
||||
<h3><a class="toc-backref" href="#id8">3.4 test_model_can_move</a><a class="headerlink" href="#test-model-can-move" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Gehen Sie analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion <strong>model_can_move()</strong>.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="nf">model_can_move</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">){</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">instance</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">model_get_winner</span><span class="p">(</span><span class="n">instance</span><span class="p">)</span> <span class="o">==</span> <span class="n">model_state_none</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// scan all fields: return 1 with first field which equals model_state_none</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE}</span>
|
||||
<span class="k">return</span> <span class="mi">0</span><span class="p">;}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="test-model-move-test-model-get-win-line">
|
||||
<h3><a class="toc-backref" href="#id9">3.5 test_model_move test_model_get_win_line</a><a class="headerlink" href="#test-model-move-test-model-get-win-line" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Schliesslich gehen Sie auch hier analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion <strong>set_state()</strong>.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/**</span>
|
||||
<span class="cm">* @brief Sets the field on the board to the given state.</span>
|
||||
<span class="cm">* @param instance [INOUT] The instance which holds the state.</span>
|
||||
<span class="cm">* @param pos [IN] The affected field.</span>
|
||||
<span class="cm">* @param state [IN] The new state of the field.</span>
|
||||
<span class="cm">*/</span>
|
||||
<span class="k">static</span> <span class="kt">void</span> <span class="n">set_state</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">,</span> <span class="n">model_pos_t</span> <span class="n">pos</span><span class="p">,</span> <span class="n">model_state_t</span> <span class="n">state</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="n">assert_pos</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
|
||||
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// set the field of the board to the new state</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Wenn die beiden obigen Teilaufgaben erfolgreich umgesetzt sind, laufen die Tests ohne Fehler durch und das Spiel kann gespielt werden.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="bewertung">
|
||||
<h2><a class="toc-backref" href="#id10">4. Bewertung</a><a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="docutils align-default">
|
||||
<colgroup>
|
||||
<col style="width: 33%" />
|
||||
<col style="width: 33%" />
|
||||
<col style="width: 33%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr class="row-odd"><td><p>Aufgabe</p></td>
|
||||
<td><p>Kriterium</p></td>
|
||||
<td><p>Gewicht</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>TicTacToe</p></td>
|
||||
<td><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>TicTacToe</p></td>
|
||||
<td><p>Teilaufgabe test_model_init</p></td>
|
||||
<td><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>TicTacToe</p></td>
|
||||
<td><p>Teilaufgabe test_model_get_state und test_model_get_winner</p></td>
|
||||
<td><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>TicTacToe</p></td>
|
||||
<td><p>Teilaufgabe test_model_can_move</p></td>
|
||||
<td><p>1</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>TicTacToe</p></td>
|
||||
<td><p>Teilaufgabe test_model_move und test_model_get_win_line</p></td>
|
||||
<td><p>1</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Version: 15.02.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P05_TicTacToe/P05_TicTacToe.rst.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,393 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>05 - Arrays/Strings/TicTacToe — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="06 - Personen Verwaltung – Linked List" href="../P06_Personen_Verwaltung_Linked_List/README.html" />
|
||||
<link rel="prev" title="04 - Modularisieren von C Code" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="arrays-strings-tictactoe">
|
||||
<h1>05 - Arrays/Strings/TicTacToe<a class="headerlink" href="#arrays-strings-tictactoe" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum werden Sie in der ersten Aufgabe ein Programm zum Einlesen, Sortieren und Ausgeben von Strings von Grund auf entwickeln.</p>
|
||||
<p>In der zweiten Aufgabe werden Sie einen Programmrahmen zu einem funktionierenden TicTacToe-Spiel erweitern. Sie implementieren hierbei die fehlenden Funktionen bis alle Tests erfolgreich durchlaufen. Die gewählte Vorgehensweise entspricht somit Test-Driven-Development (TDD). D.h. es existieren zuerst Tests, welche alle fehlschlagen. Schrittweise werden die Funktionen implementiert bis alle Tests erfolgreich durchlaufen. Wenn die Tests erfolgreich durchlaufen, wird auch das Programm funktionieren.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum schreiben Sie selbst von Grund auf ein C-Programme, das mit Strings operiert. Ferner ergänzen Sie ein bestehendes und lernen dabei den Zugriff auf Arrays.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie können mit Arrays von Strings umgehen.</p></li>
|
||||
<li><p>Sie können String-Funktionen aus der Standard Library verwenden.</p></li>
|
||||
<li><p>Sie können anhand einer Beschreibung im Code die fehlenden Funktionen die auf Arrays zugreifen implementieren.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-1-sortieren-von-strings">
|
||||
<h2>3. Aufgabe 1: Sortieren von Strings<a class="headerlink" href="#aufgabe-1-sortieren-von-strings" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Schreiben Sie ein C-Programm, das bis zu 10 Wörter mit einer maximalen Länge von jeweils 20 char von der Tastatur einliest, diese in Grossbuchstaben umwandelt, in einem Array der Reihe nach ablegt und zum Schluss im Array alphabetisch sortiert und ausgibt. Wiederholt eingegebene Wörter sollen dabei ignoriert werden. Das Ende der Eingabe soll durch das Erreichen der zehn unterschiedlichen Wörter oder durch die Eingabe von „ZZZ“ erfolgen. Die Ausgabe der sortierten Wörter soll direkt nach Beendigung der Eingabe erfolgen.</p>
|
||||
<p>Hinweise:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Zur Speicherung der Wörter sollten Sie ein zweidimensionales Array verwenden.</p></li>
|
||||
<li><p>Verwenden Sie die String-Funktionen der C Standard Library (include <string.h>), z.B. um Strings alphabetisch zu vergleichen.</p></li>
|
||||
<li><p>Wenn Sie aus anderen Vorlesungen bereits einen effizienten Sortieralgorithmus kennen, können Sie diesen natürlich verwenden. Sonst erfinden Sie einfach einen eigenen.</p></li>
|
||||
<li><p>Strukturieren Sie das Programm durch geeignete Funktionen.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-2-tictactoe">
|
||||
<h2>4. Aufgabe 2: TicTacToe<a class="headerlink" href="#aufgabe-2-tictactoe" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Das zu ergänzende Programm tic-tac-toe hat folgende Funktionalität:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>es stellt ein 3x3 TicTacToe Spielbrett auf dem Terminal dar</p></li>
|
||||
<li><p>es liest von stdin eine Ziffer 0…9 ein, wobei 0 für Programm-Terminieren, die übrigen Ziffern für die Wahl eines Feldes stehen</p></li>
|
||||
<li><p>der erste Spielzug wird von Spieler A geführt, danach wechselt das Programm zwischen den Spielern A und B</p></li>
|
||||
<li><p>bei Gewinn oder bei vollem Brett ist das Spiel vorbei</p></li>
|
||||
</ol>
|
||||
<p>Erweitern Sie die vorgegebenen Code Gerüste, welche im git Repository snp-lab-code verfügbar sind.</p>
|
||||
<p>Wenn die Aufgabe erfolgreich umgesetzt ist, können Sie das Spiel ausführen:</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>bin/tic-tac-toe
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><img alt="" src="../_images/TicTacToe.png" /></p>
|
||||
<p>Als Abnahme müssen die Tests unverändert ohne Fehler ausgeführt werden (<code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code>).</p>
|
||||
<p>Die Architektur des Programms folgt dem MVC – Model-View-Control Paradigma. Dieses Paradigma besagt, dass die View (Eingabe und Darstellung) über Control (Vermittler) das Modell (die eigentliche Programm-Logik) steuert und darstellt. Dabei sind folgende Abhängigkeiten gegeben:</p>
|
||||
<p><img alt="" src="../_images/MVC_pattern.png" /></p>
|
||||
<hr class="docutils" />
|
||||
<section id="teilaufgabe-test-model-init">
|
||||
<h3>4.1 Teilaufgabe test_model_init<a class="headerlink" href="#teilaufgabe-test-model-init" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Das Programm besteht aus folgenden Files:</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Datei</p></th>
|
||||
<th class="text-left head"><p>ToDo</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p>Makefile</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>tests/tests.c</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>src/main.c</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>src/view.h</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>src/view.c</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>src/control.h</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>src/control.c</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>src/model.h</p></td>
|
||||
<td class="text-left"><p>-> gegeben, d.h. nichts anzupassen</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>src/model.c</p></td>
|
||||
<td class="text-left"><p>-> <strong>anzupassen:</strong> umsetzen gemäss den Angaben unten</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> aus</p></li>
|
||||
</ol>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Suite: lab <span class="nb">test</span>
|
||||
Test: test_model_init ...
|
||||
init_model:... <span class="m">0</span>/0 FAILED
|
||||
<span class="m">1</span>. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL<span class="o">(</span>instance->board<span class="o">[</span>row<span class="o">][</span>col<span class="o">]</span>,model_state_none<span class="o">)</span>
|
||||
Test: test_model_get_state ...FAILED
|
||||
<span class="m">1</span>. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL<span class="o">(</span>instance->board<span class="o">[</span>row<span class="o">][</span>col<span class="o">]</span>,model_state_none<span class="o">)</span>
|
||||
Test: test_model_get_winner ...FAILED
|
||||
<span class="m">1</span>. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL<span class="o">(</span>instance->board<span class="o">[</span>row<span class="o">][</span>col<span class="o">]</span>,model_state_none<span class="o">)</span>
|
||||
Test: test_model_can_move ...FAILED
|
||||
<span class="m">1</span>. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL<span class="o">(</span>instance->board<span class="o">[</span>row<span class="o">][</span>col<span class="o">]</span>,model_state_none<span class="o">)</span>
|
||||
Test: test_model_move ...FAILED
|
||||
<span class="m">1</span>. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL<span class="o">(</span>instance->board<span class="o">[</span>row<span class="o">][</span>col<span class="o">]</span>,model_state_none<span class="o">)</span>
|
||||
Test: test_model_get_win_line ...FAILED
|
||||
<span class="m">1</span>. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL<span class="o">(</span>instance->board<span class="o">[</span>row<span class="o">][</span>col<span class="o">]</span>,model_state_none<span class="o">)</span>
|
||||
|
||||
Run Summary: Type Total Ran Passed Failed Inactive
|
||||
suites <span class="m">1</span> <span class="m">1</span> n/a <span class="m">0</span> <span class="m">0</span>
|
||||
tests <span class="m">6</span> <span class="m">6</span> <span class="m">0</span> <span class="m">6</span> <span class="m">0</span>
|
||||
asserts <span class="m">6</span> <span class="m">6</span> <span class="m">0</span> <span class="m">6</span> n/a
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Konzentrieren Sie sich auf den ersten Test der fehlschlägt. Dies ist ein Unit Test, welcher die Funktion <strong>model_init()</strong> prüft. Suchen Sie die Funktion in <strong>src/model.h</strong> und <strong>src/model.c</strong>.</p></li>
|
||||
<li><p>Was ist die geforderte Funktionalität und wie ist sie implementiert?</p></li>
|
||||
</ol>
|
||||
<p>Suchen Sie die darin aufgerufene <strong>model_init()</strong> Funktion und implementieren Sie diese.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">model_init</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">instance</span><span class="p">);</span>
|
||||
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// set all fields of the board to model_state_none</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> und korrigieren Sie obige Funktion, bis der Test nicht mehr fehlschlägt.</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="teilaufgabe-test-model-get-state-und-test-model-get-winner">
|
||||
<h3>4.2 Teilaufgabe test_model_get_state und test_model_get_winner<a class="headerlink" href="#teilaufgabe-test-model-get-state-und-test-model-get-winner" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Gehen Sie analog zur ersten Teilaufgabe vor:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Führen Sie <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> aus.</p></li>
|
||||
<li><p>Suchen Sie die Funktion <strong>model_get_state()</strong> in <strong>model.h</strong> und <strong>model.c</strong>.</p></li>
|
||||
<li><p>Implementieren Sie die intern benutzte Funktion <strong>get_state()</strong> gemäss der Anleitung im Code.</p></li>
|
||||
</ol>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">model_state_t</span> <span class="nf">model_get_state</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">,</span> <span class="n">model_pos_t</span> <span class="n">pos</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">instance</span><span class="p">);</span>
|
||||
<span class="n">assert_pos</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
|
||||
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// replace the stub implementation my access to the field at the given position.</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
|
||||
<span class="k">return</span> <span class="n">model_state_none</span><span class="p">;</span> <span class="c1">// stub</span>
|
||||
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="teilaufgabe-test-model-can-move">
|
||||
<h3>4.3 Teilaufgabe test_model_can_move<a class="headerlink" href="#teilaufgabe-test-model-can-move" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Gehen Sie analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion <strong>model_can_move()</strong>.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="nf">model_can_move</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="n">assert</span><span class="p">(</span><span class="n">instance</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">model_get_winner</span><span class="p">(</span><span class="n">instance</span><span class="p">)</span> <span class="o">==</span> <span class="n">model_state_none</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// scan all fields: return 1 with first field which equals model_state_none</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="teilaufgabe-test-model-move-und-test-model-get-win-line">
|
||||
<h3>4.4 Teilaufgabe test_model_move und test_model_get_win_line<a class="headerlink" href="#teilaufgabe-test-model-move-und-test-model-get-win-line" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Schliesslich gehen Sie auch hier analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion <strong>set_state()</strong>.</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/**</span>
|
||||
<span class="cm"> * @brief Sets the field on the board to the given state.</span>
|
||||
<span class="cm"> * @param instance [INOUT] The instance which holds the state.</span>
|
||||
<span class="cm"> * @param pos [IN] The affected field.</span>
|
||||
<span class="cm"> * @param state [IN] The new state of the field.</span>
|
||||
<span class="cm"> */</span>
|
||||
<span class="k">static</span> <span class="kt">void</span> <span class="n">set_state</span><span class="p">(</span><span class="n">model_t</span> <span class="o">*</span><span class="n">instance</span><span class="p">,</span> <span class="n">model_pos_t</span> <span class="n">pos</span><span class="p">,</span> <span class="n">model_state_t</span> <span class="n">state</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="n">assert_pos</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
|
||||
|
||||
<span class="c1">// Instructions to the students:</span>
|
||||
<span class="c1">// set the field of the board to the new state</span>
|
||||
<span class="c1">// BEGIN-STUDENTS-TO-ADD-CODE</span>
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="c1">// END-STUDENTS-TO-ADD-CODE</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Wenn die beiden obigen Teilaufgaben erfolgreich umgesetzt sind, laufen die Tests ohne Fehler durch und das Spiel kann gespielt werden.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>5. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Der funktionierende Programmcode muss der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Punkte</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p>Sortieren von Strings</p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p>2</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>TicTacToe</p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>TicTacToe</p></td>
|
||||
<td class="text-left"><p>Teilaufgabe test_model_init</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>TicTacToe</p></td>
|
||||
<td class="text-left"><p>Teilaufgabe test_model_get_state und test_model_get_winner</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>TicTacToe</p></td>
|
||||
<td class="text-left"><p>Teilaufgabe test_model_can_move</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>TicTacToe</p></td>
|
||||
<td class="text-left"><p>Teilaufgabe test_model_move und test_model_get_win_line</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 14.02.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">05 - Arrays/Strings/TicTacToe</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-1-sortieren-von-strings">3. Aufgabe 1: Sortieren von Strings</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-2-tictactoe">4. Aufgabe 2: TicTacToe</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#teilaufgabe-test-model-init">4.1 Teilaufgabe test_model_init</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#teilaufgabe-test-model-get-state-und-test-model-get-winner">4.2 Teilaufgabe test_model_get_state und test_model_get_winner</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#teilaufgabe-test-model-can-move">4.3 Teilaufgabe test_model_can_move</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#teilaufgabe-test-model-move-und-test-model-get-win-line">4.4 Teilaufgabe test_model_move und test_model_get_win_line</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">5. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html" title="previous chapter">04 - Modularisieren von C Code</a></li>
|
||||
<li>Next: <a href="../P06_Personen_Verwaltung_Linked_List/README.html" title="next chapter">06 - Personen Verwaltung – Linked List</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P05_TicTacToe/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,394 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>06 - Personen Verwaltung – Linked List — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="07 - Prozesse und Threads" href="../P07_Prozesse_und_Threads/README.html" />
|
||||
<link rel="prev" title="05 - Arrays/Strings/TicTacToe" href="../P05_TicTacToe/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="personen-verwaltung-linked-list">
|
||||
<h1>06 - Personen Verwaltung – Linked List<a class="headerlink" href="#personen-verwaltung-linked-list" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<p><img alt="" src="../_images/linked_list.png" /></p>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum schreiben Sie eine einfache Personenverwaltung. Dabei werden Sie etliche Elemente von C anwenden:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Header Files selber schreiben, inklusive Include Guard</p></li>
|
||||
<li><p>Typen definieren</p></li>
|
||||
<li><p>Funktionen mit <code class="docutils literal notranslate"><span class="pre">by</span> <span class="pre">value</span></code> und <code class="docutils literal notranslate"><span class="pre">by</span> <span class="pre">reference</span></code> Parametern deklarieren und definieren</p></li>
|
||||
<li><p>einfache Variablen, Pointer Variablen, struct Variablen und Array Variablen benutzen</p></li>
|
||||
<li><p>Strukturen im Speicher dynamisch allozieren und freigeben</p></li>
|
||||
<li><p>I/O und String Funktionen aus der Standard Library anwenden</p></li>
|
||||
<li><p>Anwender Eingaben verarbeiten</p></li>
|
||||
<li><p>Fehlerbehandlung</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum wenden Sie viele der bisher gelernten C Elemente an.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie können anhand dieser Beschreibung ein vollständiges C Programm schreiben.</p></li>
|
||||
<li><p>Sie können Unit Tests schreiben welche die wesentlichen Funktionen des Programms individuell testen.</p></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
<p>Die Bewertung dieses Praktikums ist am Ende angegeben.</p>
|
||||
<p>Erweitern Sie die vorgegebenen Code Gerüste, welche im <code class="docutils literal notranslate"><span class="pre">git</span></code> Repository <code class="docutils literal notranslate"><span class="pre">snp-lab-code</span></code> verfügbar sind.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="personenverwaltung">
|
||||
<h2>3. Personenverwaltung<a class="headerlink" href="#personenverwaltung" title="Permalink to this headline">¶</a></h2>
|
||||
<hr class="docutils" />
|
||||
<section id="programmfunktion">
|
||||
<h3>3.1 Programmfunktion<a class="headerlink" href="#programmfunktion" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Das Programm soll in einer Schleife dem Benutzer jeweils folgende Auswahl bieten, wovon eine Aktion mit Eingabe des entsprechenden Buchstabens ausgelöst wird:</p>
|
||||
<p><strong>I</strong>(nsert), <strong>R</strong>(emove), <strong>S</strong>(how), <strong>C</strong>(lear), <strong>E</strong>(nd):</p>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Insert</strong>: der Benutzer wird aufgefordert, eine Person einzugeben</p></li>
|
||||
<li><p><strong>Remove</strong>: der Benutzer wird aufgefordert, die Daten einer zu löschenden Person einzu-geben</p></li>
|
||||
<li><p><strong>Show</strong>: eine komplette Liste aller gespeicherten Personen wird in alphabetischer Rei-henfolge ausgegeben</p></li>
|
||||
<li><p><strong>Clear</strong>: alle Personen werden gelöscht</p></li>
|
||||
<li><p><strong>End</strong>: das Programm wird beendet</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="designvorgaben">
|
||||
<h3>3.2 Designvorgaben<a class="headerlink" href="#designvorgaben" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Verkettete Liste</strong>
|
||||
Da zur Kompilierzeit nicht bekannt ist, ob 10 oder 10’000 Personen eingegeben werden, wäre es keine gute Idee, im Programm einen statischen Array mit z.B. 10’000 Personen-Einträgen zu allozieren. Dies wäre ineffizient und umständlich beim sortierten Einfügen von Personen. In solchen Situationen arbeitet man deshalb mit dynamischen Datenstrukturen, die zur Laufzeit beliebig (solange Speicher vorhanden ist) wachsen und wieder schrumpfen können. Eine sehr populäre dynamische Datenstruktur ist die <strong>verkettete Liste</strong> und genau die werden wir in diesem Praktikum verwenden.</p>
|
||||
<p><img alt="" src="../_images/a.png" /></p>
|
||||
<p><img alt="" src="../_images/b.png" /></p>
|
||||
<p><img alt="" src="../_images/c.png" /></p>
|
||||
<p><img alt="" src="../_images/d.png" />
|
||||
Abbildung 1: Zyklisch verkettete Liste</p>
|
||||
<p>Eine verkettete Liste bedeutet, dass ein Knoten der verketten Liste einen Datensatz einer Person speichert und zusätzlich einen Pointer auf den nächsten Knoten in der Liste aufweist (siehe Abbildung 1). In dieser Pointer Variablen (<code class="docutils literal notranslate"><span class="pre">next</span></code> in der <code class="docutils literal notranslate"><span class="pre">node_t</span></code> Struktur unten) steht also einfach die Adresse des nächsten Knotens.</p>
|
||||
<p>Die leere Liste besteht aus einem einzelnen Element, welches keine spezifische Person abspeichert und welches auf sich selbst zeigt (Abbildung 1 a). Dieses Element ist der Einstiegspunkt der Liste (auch Anker oder Wurzel genannt) und ist das einzige Element, das Sie im Programm direkt kennen und einer Variablen zuweisen. Dieses Element können Sie statisch allozieren (z.B. <code class="docutils literal notranslate"><span class="pre">node_t</span> <span class="pre">anchor</span></code>;, siehe Details weiter unten), denn es existiert während der gesamten Ausführungszeit. Alle anderen Elemente erreichen Sie ausgehend vom Anker, indem Sie einmal, den Pointern folgend, im Kreis herum gehen. Abbildung 1 b zeigt die Liste nach dem Einfügen der Person <code class="docutils literal notranslate"><span class="pre">Max</span> <span class="pre">Mueller,</span> <span class="pre">40</span></code> Jahre. Nach dem Einfügen von zwei weiteren Personen sieht die Datenstruktur aus wie in Abbildung 1 c. Das Entfernen der Person <code class="docutils literal notranslate"><span class="pre">Arno</span> <span class="pre">Bosshard</span></code> führt zu Abbildung 1 d.</p>
|
||||
<p>Eine Person kann <strong>zugefügt</strong> werden, indem dynamisch ein neuer Knoten erzeugt wird und dieser in die verkettete Liste eingefügt wird. Beim Einfügen müssen die Adressen der Knoten so den Pointern zugewiesen werden, dass die Kette intakt bleibt.</p>
|
||||
<p>Ein Knoten wird <strong>entfernt</strong>, indem der entsprechende Knoten aus der Verkettung herausgelöst wird (<code class="docutils literal notranslate"><span class="pre">next</span></code> des Vorgängerknotens soll neu auf <code class="docutils literal notranslate"><span class="pre">next</span></code> des herauszulösenden Knotens zeigen) und dann der Speicher des entsprechenden Knotens freigegeben wird.</p>
|
||||
<p><strong>Personen und Knoten Records</strong></p>
|
||||
<p>Die für je eine Person zu speichernden Daten sollen in folgendem C <code class="docutils literal notranslate"><span class="pre">struct</span></code> zusammengefasst sein.</p>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="cp">#define NAME_LEN 20</span>
|
||||
|
||||
<span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
|
||||
<span class="kt">char</span> <span class="n">name</span><span class="p">[</span><span class="n">NAME_LEN</span><span class="p">];</span>
|
||||
<span class="kt">char</span> <span class="n">first_name</span><span class="p">[</span><span class="n">NAME_LEN</span><span class="p">];</span>
|
||||
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">age</span><span class="p">;</span>
|
||||
<span class="p">}</span> <span class="n">person_t</span><span class="p">;</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Jeder Knoten der verketteten Liste soll aus folgendem C <code class="docutils literal notranslate"><span class="pre">struct</span></code> bestehen.</p>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="k">struct</span> <span class="nc">node</span> <span class="p">{</span>
|
||||
<span class="n">person_t</span> <span class="n">content</span><span class="p">;</span> <span class="c1">// in diesem Knoten gespeicherte Person</span>
|
||||
<span class="k">struct</span> <span class="nc">node</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span> <span class="c1">// Pointer auf den nächsten Knoten in der Liste</span>
|
||||
<span class="p">}</span> <span class="n">node_t</span><span class="p">;</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><strong>Vorschlag: zyklisch verkettete Liste</strong></p>
|
||||
<p>Erkennen des Endes der Liste: bei der zyklisch verketteten Liste zeigt das letzte Element wie-der auf den Anker, die Liste bildet also einen Kreis. Dies ist in Abbildung 1 so abgebildet.</p>
|
||||
<p>Alternativ könnte man das Ende erkennbar machen, indem die Kette anstelle von zyklisch, mit einem NULL Pointer endet.</p>
|
||||
<p>Die Wahl ist ihnen überlassen ob sie die eine oder andere Art der End-Erkennung implementieren. In der Beschreibung wird angenommen, dass es sich um eine zyklisch verkettete Liste handelt.</p>
|
||||
<p><strong>Sortiertes Einfügen</strong></p>
|
||||
<p>Die Personen Records sollen sortiert in die Liste eingefügt werden. Dies bedeutet, dass vom Anker her gesucht werden soll, bis der erste Knoten gefunden wurde dessen Nachfolgeknoten entweder „grösser“ ist als der einzufügende Knoten, oder wo das Ende der Liste erreicht ist. Die Ordnung (grösser, gleich, kleiner) soll so definiert sein:</p>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="c1">// if (p1 > p2) { ... }</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">person_compare</span><span class="p">(</span><span class="o">&</span><span class="n">p1</span><span class="p">,</span> <span class="o">&</span><span class="n">p2</span><span class="p">)</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
|
||||
<span class="cm">/**</span>
|
||||
<span class="cm"> * @brief Compares two persons in this sequence: 1st=name, 2nd=first_name, 3rd=age</span>
|
||||
<span class="cm"> * @param a [IN] const reference to 1st person in the comparison</span>
|
||||
<span class="cm"> * @param b [IN] const reference to 2nd person in the comparison</span>
|
||||
<span class="cm"> * @return =0 if all record fields are the same</span>
|
||||
<span class="cm"> * >0 if all previous fields are the same, but for this field, a is greater</span>
|
||||
<span class="cm"> * <0 if all previous fields are the same, but for this field, b is greater</span>
|
||||
<span class="cm"> * @remark strncmp() is used for producing the result of string field comparisons</span>
|
||||
<span class="cm"> * @remark a->age – b->age is used for producing the result of age comparison</span>
|
||||
<span class="cm"> */</span>
|
||||
<span class="kt">int</span> <span class="n">person_compare</span><span class="p">(</span><span class="k">const</span> <span class="n">person_t</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="n">person_t</span> <span class="o">*</span><span class="n">b</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><strong>Eingabe</strong></p>
|
||||
<p><strong>Fehlerhafte Wahl der Operation</strong> in der Hauptschleife soll gemeldet werden, ansonsten aber ignoriert werden.</p>
|
||||
<p><strong>Fehlerhafte Eingabe der Personenangaben</strong> sollen gemeldet werden und die gesamte Operation (z.B. Insert) verworfen werden.</p>
|
||||
<p>Zu prüfende Fehler bei Personeneingaben:</p>
|
||||
<ul class="simple">
|
||||
<li><p>für die Namen</p>
|
||||
<ul>
|
||||
<li><p>zu lange Namen</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>für das Alter</p>
|
||||
<ul>
|
||||
<li><p>keine Zahl</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>Duplikat</p>
|
||||
<ul>
|
||||
<li><p>derselbe Record soll nicht doppelt in der Liste vorkommen</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Weitergehende Prüfungen sind nicht erwartet.</p>
|
||||
<p><strong>Zu beachten:</strong> bei fehlerhafter Eingabe darf kein „Memory Leak“ entstehen, d.h. potentiell auf dem Heap allozierter Speicher muss im Fehlerfall freigegeben werden.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bestehender-programmrahmen">
|
||||
<h3>3.3 Bestehender Programmrahmen<a class="headerlink" href="#bestehender-programmrahmen" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Der Programmrahmen besteht aus den unten aufgelisteten Files. Es sollen weitere Module in <code class="docutils literal notranslate"><span class="pre">src</span></code> hinzugefügt werden und die bestehenden Files ergänzt werden gemäss den Aufgaben.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p></p></th>
|
||||
<th class="text-left head"><p></p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p>Makefile</p></td>
|
||||
<td class="text-left"><p>-> <strong>zu ergänzen</strong> mit neuen Modulen</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>tests/tests.c</p></td>
|
||||
<td class="text-left"><p>-> <strong>zu ergänzen</strong> gemäss Aufgaben (implementieren von Unit Tests)</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>src/main.c</p></td>
|
||||
<td class="text-left"><p>-> <strong>zu ergänzen</strong> gemäss Aufgaben (Hauptprogramm)</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-1-modularisierung-api-und-implementation-main-c">
|
||||
<h2>4. Aufgabe 1: Modularisierung – API und Implementation main.c<a class="headerlink" href="#aufgabe-1-modularisierung-api-und-implementation-main-c" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Kreieren Sie folgende Files in <code class="docutils literal notranslate"><span class="pre">src</span></code> und implementieren Sie <code class="docutils literal notranslate"><span class="pre">main.c</span></code> basierend auf dem unten von Ihnen gegebenen API.</p>
|
||||
<p><strong>File person.h</strong></p>
|
||||
<p>Typ Definitionen:</p>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="n">person_t</span><span class="p">...</span> <span class="c1">// siehe Beschreibung oben</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Funktionsdeklarationen:</p>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="c1">// siehe Beschreibung oben</span>
|
||||
<span class="kt">int</span> <span class="nf">person_compare</span><span class="p">(</span><span class="k">const</span> <span class="n">person_t</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="n">person_t</span> <span class="o">*</span><span class="n">b</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>gegebenenfalls weitere Funktionen für die Bearbeitung von Personen</p></li>
|
||||
</ul>
|
||||
<p><strong>File list.h</strong></p>
|
||||
<p>Typ Definitionen:</p>
|
||||
<div class="highlight-C notranslate"><div class="highlight"><pre><span></span><span class="n">person_t</span><span class="p">...</span> <span class="c1">// siehe Beschreibung oben</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Funktionsdeklarationen:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Funktionen für <code class="docutils literal notranslate"><span class="pre">insert</span></code>, <code class="docutils literal notranslate"><span class="pre">remove</span></code>, <code class="docutils literal notranslate"><span class="pre">clear</span></code> Operationen auf der Liste</p></li>
|
||||
</ul>
|
||||
<hr class="docutils" />
|
||||
<p>Das Hauptprogramm soll die Eingabeschleife implementieren und die obigen Funktionen (wo angebracht) aufrufen.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-2-implementierung-von-person-c-und-list-c">
|
||||
<h2>5. Aufgabe 2: Implementierung von person.c und list.c<a class="headerlink" href="#aufgabe-2-implementierung-von-person-c-und-list-c" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Fügen Sie die beiden Implementationsfiles <code class="docutils literal notranslate"><span class="pre">person.c</span></code> und <code class="docutils literal notranslate"><span class="pre">list.c</span></code> zu <code class="docutils literal notranslate"><span class="pre">src</span></code>. Fügen Sie die beiden Module im <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> zu der vorgegebenen Variablen <code class="docutils literal notranslate"><span class="pre">MODULES</span></code> hinzu, so dass sie beim <code class="docutils literal notranslate"><span class="pre">make</span></code> Aufruf auch berücksichtigt werden.</p>
|
||||
<hr class="docutils" />
|
||||
<section id="teilaufgabe-implementierung-von-person-c">
|
||||
<h3>5.1 Teilaufgabe: Implementierung von person.c<a class="headerlink" href="#teilaufgabe-implementierung-von-person-c" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Implementieren Sie die Funktionen aus <code class="docutils literal notranslate"><span class="pre">person.h</span></code>.</p>
|
||||
<p>Falls nötig, stellen Sie weitere statische Hilfsfunktionen in <code class="docutils literal notranslate"><span class="pre">person.c</span></code> zur Verfügung.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="teilaufgabe-implementierung-von-list-c">
|
||||
<h3>5.2 Teilaufgabe: Implementierung von list.c<a class="headerlink" href="#teilaufgabe-implementierung-von-list-c" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Implementieren Sie die Funktionen aus <code class="docutils literal notranslate"><span class="pre">list.h</span></code>.</p>
|
||||
<p>Falls nötig, stellen Sie weitere statische Hilfsfunktionen in <code class="docutils literal notranslate"><span class="pre">list.c</span></code> zur Verfügung.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-3-unit-tests">
|
||||
<h2>6. Aufgabe 3: Unit Tests<a class="headerlink" href="#aufgabe-3-unit-tests" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Schreiben Sie Unit Tests für mindestens die folgenden Funktionen</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">person.h:</span></code></p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">person_compare</span></code></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">list.h:</span></code></p>
|
||||
<ul>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">list_insert</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">list_remove</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">list_clear</span></code></p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Es existieren in <code class="docutils literal notranslate"><span class="pre">tests/tests.c</span></code> schon vier Test Rahmen für diese Test Cases.</p>
|
||||
<p>In diese Test Cases sollen die entsprechenden Funktionen unter verschiedenen Bedingungen isoliert aufgerufen werden und deren Verhalten überprüft werden.</p>
|
||||
<p>Verwenden Sie für die Überprüfung die CUnit <code class="docutils literal notranslate"><span class="pre">CU_ASSERT_...</span></code> Makros.</p>
|
||||
<p>Siehe dazu auch <code class="docutils literal notranslate"><span class="pre">man</span> <span class="pre">CUnit</span></code>.</p>
|
||||
<p>Wenn die obigen Teilaufgaben erfolgreich umgesetzt sind, laufen die Tests ohne Fehler durch.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>7. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Punkte</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p></p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>1</p></td>
|
||||
<td class="text-left"><p>API von list.h und person.h plus die Implementation von main.c</p></td>
|
||||
<td class="text-left"><p>2</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>2</p></td>
|
||||
<td class="text-left"><p>Teilaufgabe: person.c</p></td>
|
||||
<td class="text-left"><p>2</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>2</p></td>
|
||||
<td class="text-left"><p>Teilaufgabe: list.c</p></td>
|
||||
<td class="text-left"><p>2</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>3</p></td>
|
||||
<td class="text-left"><p>Unit Tests</p></td>
|
||||
<td class="text-left"><p>2</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 11.01.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">06 - Personen Verwaltung – Linked List</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#personenverwaltung">3. Personenverwaltung</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#programmfunktion">3.1 Programmfunktion</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#designvorgaben">3.2 Designvorgaben</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#bestehender-programmrahmen">3.3 Bestehender Programmrahmen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-1-modularisierung-api-und-implementation-main-c">4. Aufgabe 1: Modularisierung – API und Implementation main.c</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-2-implementierung-von-person-c-und-list-c">5. Aufgabe 2: Implementierung von person.c und list.c</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#teilaufgabe-implementierung-von-person-c">5.1 Teilaufgabe: Implementierung von person.c</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#teilaufgabe-implementierung-von-list-c">5.2 Teilaufgabe: Implementierung von list.c</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-3-unit-tests">6. Aufgabe 3: Unit Tests</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">7. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P05_TicTacToe/README.html" title="previous chapter">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li>Next: <a href="../P07_Prozesse_und_Threads/README.html" title="next chapter">07 - Prozesse und Threads</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P06_Personen_Verwaltung_Linked_List/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,646 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>07 - Prozesse und Threads — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="08 - Synchronisationsprobleme" href="../P08_Sync/README.html" />
|
||||
<link rel="prev" title="06 - Personen Verwaltung – Linked List" href="../P06_Personen_Verwaltung_Linked_List/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="prozesse-und-threads">
|
||||
<h1>07 - Prozesse und Threads<a class="headerlink" href="#prozesse-und-threads" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<p><img alt="" src="../_images/ein_mann_orchester.png" /></p>
|
||||
<p><a class="reference external" href="https://www.wikiwand.com/de/Ein-Mann-Orchester">Quelle: https://www.wikiwand.com/de/Ein-Mann-Orchester</a></p>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum werden wir uns mit Prozessen, Prozesshierarchien und Threads beschäftigen, um ein gutes Grundverständnis dieser Abstraktionen zu erhalten. Sie werden bestehenden Code analysieren und damit experimentieren. D.h. dies ist nicht ein «Codierungs»-Praktikum, sondern ein «Analyse»- und «Experimentier»-Praktikum.</p>
|
||||
<hr class="docutils" />
|
||||
<section id="nachweis">
|
||||
<h3>1.1 Nachweis<a class="headerlink" href="#nachweis" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Dieses Praktikum ist eine leicht abgewandelte Variante des ProcThreads Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.</p>
|
||||
<p>Als Autoren des BSY Praktikums sind genannt: M. Thaler, J. Zeman.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum werden Sie sich mit Prozessen, Prozesshierarchien und Threads beschäftigen. Sie erhalten einen vertieften Einblick und Verständnis zur Erzeugung, Steuerung und Terminierung von Prozessen unter Unix/Linux und Sie werden die unterschiedlichen Eigenschaften von Prozessen und Threads kennenlernen.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie können Prozesse erzeugen und die Prozesshierarchie erklären</p></li>
|
||||
<li><p>Sie wissen was beim Erzeugen eines Prozesses vom Elternprozess vererbt wird</p></li>
|
||||
<li><p>Sie wissen wie man auf die Terminierung von Kindprozessen wartet</p></li>
|
||||
<li><p>Sie kennen die Unterschiede zwischen Prozessen und Threads</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgaben">
|
||||
<h2>3. Aufgaben<a class="headerlink" href="#aufgaben" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Das Betriebssystem bietet Programme um die aktuellen Prozesse und Threads darzustellen.</p>
|
||||
<p>Die Werkzeuge kommen mit einer Vielzahl von Optionen für die Auswahl und Darstellung der Daten, z.B. ob nur Prozesse oder auch Threads aufgelistet werden sollen, und ob alle Prozesse oder nur die «eigenen» Prozesse ausgewählt werden sollen, etc.</p>
|
||||
<p>Siehe die entsprechenden <code class="docutils literal notranslate"><span class="pre">man</span></code> Pages für weitere Details.</p>
|
||||
<p>Eine Auswahl, welche unter Umständen für die folgenden Aufgaben nützlich sind:</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p></p></th>
|
||||
<th class="text-left head"><p></p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p><code class="docutils literal notranslate"><span class="pre">ps</span></code></p></td>
|
||||
<td class="text-left"><p>Auflisten der Prozess Zustände zum gegebenen Zeitpunkt.</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p><code class="docutils literal notranslate"><span class="pre">pstree</span></code></p></td>
|
||||
<td class="text-left"><p>Darstellung der gesamten Prozesshierarchie.</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p><code class="docutils literal notranslate"><span class="pre">top</span></code></p></td>
|
||||
<td class="text-left"><p>Wie <code class="docutils literal notranslate"><span class="pre">ps</span></code>, aber die Darstellung wird in Zeitintervallen aufdatiert.</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p><code class="docutils literal notranslate"><span class="pre">htop</span></code></p></td>
|
||||
<td class="text-left"><p>Wie <code class="docutils literal notranslate"><span class="pre">top</span></code>, aber zusätzlich dazu die Auslastung der CPU in einem System mit mehreren CPUs.</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p><code class="docutils literal notranslate"><span class="pre">lscpu</span></code></p></td>
|
||||
<td class="text-left"><p>Auflisten der CPUs.</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p><code class="docutils literal notranslate"><span class="pre">cat</span></code>/<code class="docutils literal notranslate"><span class="pre">proc</span></code>/<code class="docutils literal notranslate"><span class="pre">cpuinfo</span></code></p></td>
|
||||
<td class="text-left"><p>Ähnlich zu <code class="docutils literal notranslate"><span class="pre">lscpu</span></code>, aber mit Zusatzinformationen wie enthaltene CPU Bugs (z.B. <code class="docutils literal notranslate"><span class="pre">bugs:</span> <span class="pre">cpu_meltdown</span> <span class="pre">spectre_v1</span> <span class="pre">spect-re_v2</span> <span class="pre">spec_store_bypass</span> <span class="pre">l1tf</span> <span class="pre">mds</span> <span class="pre">swapgs</span> <span class="pre">itlb_multihit</span></code>)</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-1-prozess-mit-fork-erzeugen">
|
||||
<h3>3.1 Aufgabe 1: Prozess mit fork() erzeugen<a class="headerlink" href="#aufgabe-1-prozess-mit-fork-erzeugen" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Verstehen, wie mit <code class="docutils literal notranslate"><span class="pre">fork()</span></code> Prozesse erzeugt werden.</p></li>
|
||||
<li><p>Einfache Prozesshierarchien kennenlernen.</p></li>
|
||||
<li><p>Verstehen, wie ein Programm, das <code class="docutils literal notranslate"><span class="pre">fork()</span></code> aufruft, durchlaufen wird.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic">
|
||||
<li><p>Studieren Sie zuerst das Programm <code class="docutils literal notranslate"><span class="pre">ProcA1.c</span></code> und beschrieben Sie was geschieht.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Notieren Sie sich, was ausgegeben wird. Starten Sie das Programm und vergleichen Sie die Ausgabe mit ihren Notizen? Was ist gleich, was anders und wieso?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-2-prozess-mit-fork-und-exec-programm-image-ersetzen">
|
||||
<h3>3.2 Aufgabe 2: Prozess mit fork() und exec(): Programm Image ersetzen<a class="headerlink" href="#aufgabe-2-prozess-mit-fork-und-exec-programm-image-ersetzen" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>An einem Beispiel die Funktion <code class="docutils literal notranslate"><span class="pre">execl()</span></code> kennenlernen.</p></li>
|
||||
<li><p>Verstehen, wie nach <code class="docutils literal notranslate"><span class="pre">fork()</span></code> ein neues Programm gestartet wird.
|
||||
<strong>Aufgaben</strong></p></li>
|
||||
</ul>
|
||||
<ol class="arabic">
|
||||
<li><p>Studieren Sie zuerst die Programme <code class="docutils literal notranslate"><span class="pre">ProcA2.c</span></code> und <code class="docutils literal notranslate"><span class="pre">ChildProcA2.c</span></code>.</p></li>
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA2.e</span></code> und vergleichen Sie die Ausgabe mit der Ausgabe unter Aufgabe 1. Diskutieren und erklären Sie was gleich ist und was anders.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Benennen Sie <code class="docutils literal notranslate"><span class="pre">ChildProcA2.e</span></code> auf <code class="docutils literal notranslate"><span class="pre">ChildProcA2.f</span></code> um (Shell Befehl <code class="docutils literal notranslate"><span class="pre">mv</span></code>) und überlegen Sie, was das Programm nun ausgibt. Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA2.e</span></code> und vergleichen Sie Ihre Überlegungen mit der Programmausgabe.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Nennen Sie das Kindprogramm wieder <code class="docutils literal notranslate"><span class="pre">ChildProcA2.e</span></code> und geben Sie folgenden Befehl ein: <code class="docutils literal notranslate"><span class="pre">chmod</span> <span class="pre">-x</span> <span class="pre">ChildProcA2.e</span></code>. Starten Sie wiederum <code class="docutils literal notranslate"><span class="pre">ProcA2.e</span></code> und analysieren Sie die Ausgabe von <code class="docutils literal notranslate"><span class="pre">perror("...")</span></code>. Wieso verwenden wir <code class="docutils literal notranslate"><span class="pre">perror()</span></code>?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-3-prozesshierarchie-analysieren">
|
||||
<h3>3.3 Aufgabe 3: Prozesshierarchie analysieren<a class="headerlink" href="#aufgabe-3-prozesshierarchie-analysieren" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Verstehen, was <code class="docutils literal notranslate"><span class="pre">fork()</span></code> wirklich macht.</p></li>
|
||||
<li><p>Verstehen, was Prozesshierarchien sind.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Studieren Sie zuerst Programm <code class="docutils literal notranslate"><span class="pre">ProcA3.c</span></code> und zeichnen Sie die entstehende Prozesshierarchie (Baum) von Hand auf. Starten Sie das Programm und verifizieren Sie ob Ihre Prozesshierarchie stimmt.</p></li>
|
||||
<li><p>Mit dem Befehl <code class="docutils literal notranslate"><span class="pre">ps</span> <span class="pre">f</span></code> oder <code class="docutils literal notranslate"><span class="pre">pstree</span></code> können Sie die Prozesshierarchie auf dem Bildschirm ausgeben. Damit die Ausgabe von <code class="docutils literal notranslate"><span class="pre">pstree</span></code> übersichtlich ist, müssen Sie in dem Fenster, wo Sie das Programm <code class="docutils literal notranslate"><span class="pre">ProcA3.e</span></code> starten, zuerst die PID der Shell erfragen, z.B. über <code class="docutils literal notranslate"><span class="pre">echo</span> <span class="pre">$$</span></code>. Wenn Sie nun den Befehl <code class="docutils literal notranslate"><span class="pre">pstree</span> <span class="pre">-n</span> <span class="pre">-p</span> <span class="pre">pid-von-oben</span></code> eingeben, wird nur die Prozesshierarchie ausgehend von der Bash Shell angezeigt: <code class="docutils literal notranslate"><span class="pre">-n</span></code> sortiert die Prozesse numerisch, <code class="docutils literal notranslate"><span class="pre">-p</span></code> zeigt für jeden Prozess die PID an.</p></li>
|
||||
</ol>
|
||||
<p><strong>Hinweis:</strong> alle erzeugten Prozesse müssen arbeiten (d.h. nicht terminiert sein), damit die Darstellung gelingt. Wie wird das im gegebenen Programm erreicht?</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-4-zeitlicher-ablauf-von-prozessen">
|
||||
<h3>3.4 Aufgabe 4: Zeitlicher Ablauf von Prozessen<a class="headerlink" href="#aufgabe-4-zeitlicher-ablauf-von-prozessen" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Verstehen, wie Kind- und Elternprozesse zeitlich ablaufen.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic">
|
||||
<li><p>Studieren Sie Programm <code class="docutils literal notranslate"><span class="pre">ProcA4.c.</span></code> Starten Sie nun mehrmals hintereinander das Programm <code class="docutils literal notranslate"><span class="pre">ProcA4.e</span></code> und vergleichen Sie die jeweiligen Outputs (leiten Sie dazu auch die Ausgabe auf verschiedene Dateien um). Was schliessen Sie aus dem Resultat?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
<p><strong>Anmerkung:</strong> Der Funktionsaufruf <code class="docutils literal notranslate"><span class="pre">selectCPU(0)</span></code> erzwingt die Ausführung des Eltern- und Kindprozesses auf CPU 0 (siehe Modul <code class="docutils literal notranslate"><span class="pre">setCPU.c</span></code>). Die Prozedur <code class="docutils literal notranslate"><span class="pre">justWork(HARD_WORK)</span></code> simuliert CPU-Load durch den Prozess (siehe Modul <code class="docutils literal notranslate"><span class="pre">workerUtils.c</span></code>).</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-5-waisenkinder-orphan-processes">
|
||||
<h3>3.5 Aufgabe 5: Waisenkinder (Orphan Processes)<a class="headerlink" href="#aufgabe-5-waisenkinder-orphan-processes" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Verstehen, was mit verwaisten Kindern geschieht.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic">
|
||||
<li><p>Analysieren Sie Programm <code class="docutils literal notranslate"><span class="pre">ProcA5.c</span></code>: was läuft ab und welche Ausgabe erwarten Sie?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA5.e</span></code>: der Elternprozess terminiert: was geschieht mit dem Kind?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Was geschieht, wenn der Kindprozess vor dem Elternprozess terminiert? Ändern Sie dazu im <code class="docutils literal notranslate"><span class="pre">sleep()</span></code> Befehl die Zeit von 2 Sekunden auf 12 Sekunden und verfolgen Sie mit top das Verhalten der beiden Prozesse, speziell auch die Spalte S.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-6-terminierte-halbtote-prozesse-zombies">
|
||||
<h3>3.6 Aufgabe 6: Terminierte, halbtote Prozesse (Zombies)<a class="headerlink" href="#aufgabe-6-terminierte-halbtote-prozesse-zombies" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Verstehen, was ein Zombie ist.</p></li>
|
||||
<li><p>Eine Möglichkeit kennenlernen, um Zombies zu verhindern.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic">
|
||||
<li><p>Analysieren Sie das Programm <code class="docutils literal notranslate"><span class="pre">ProcA6.c</span></code>.</p></li>
|
||||
<li><p>Starten Sie das Script <code class="docutils literal notranslate"><span class="pre">mtop</span></code> bzw. <code class="docutils literal notranslate"><span class="pre">mtop</span> <span class="pre">aaaa.e</span></code>. Es stellt das Verhalten der Prozesse dynamisch dar.</p>
|
||||
<p><strong>Hinweis:</strong> <code class="docutils literal notranslate"><span class="pre"><defunct></span></code> = Zombie.</p>
|
||||
</li>
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">aaaa.e</span></code> und verfolgen Sie im <code class="docutils literal notranslate"><span class="pre">mtop</span></code>-Fenster was geschieht. Was beachten Sie?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>In gewissen Fällen will man nicht auf die Terminierung eines Kindes mit <code class="docutils literal notranslate"><span class="pre">wait()</span></code>, bzw. <code class="docutils literal notranslate"><span class="pre">waitpid()</span></code> warten. Überlegen Sie sich, wie Sie in diesem Fall verhindern können, dass ein Kind zum Zombie wird.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-7-auf-terminieren-von-kindprozessen-warten">
|
||||
<h3>3.7 Aufgabe 7: Auf Terminieren von Kindprozessen warten<a class="headerlink" href="#aufgabe-7-auf-terminieren-von-kindprozessen-warten" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Vorbemerkung:</strong> Diese Aufgabe verwendet Funktionen welche erst in der Vorlesung über <em>Inter-Process-Communication (IPC)</em> im Detail behandelt werden.</p>
|
||||
<p>Sie können diese Aufgabe bis dann aufsparen oder die verwendeten Funktionen selber via <code class="docutils literal notranslate"><span class="pre">man</span></code> Pages im benötigten Umfang kennenlernen: <code class="docutils literal notranslate"><span class="pre">man</span> <span class="pre">2</span> <span class="pre">kill</span></code> und <code class="docutils literal notranslate"><span class="pre">man</span> <span class="pre">7</span> <span class="pre">signal</span></code>.</p>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Verstehen, wie Informationen zu Kindprozessen abgefragt werden können.</p></li>
|
||||
<li><p>Die Befehle <code class="docutils literal notranslate"><span class="pre">wait()</span></code> und <code class="docutils literal notranslate"><span class="pre">waitpid()</span></code> verwenden können.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic">
|
||||
<li><p>Starten Sie das Programm <code class="docutils literal notranslate"><span class="pre">ProcA7.e</span></code> und analysieren Sie wie die Ausgabe im Hauptprogramm zustande kommt und was im Kindprozess <code class="docutils literal notranslate"><span class="pre">ChildProcA7.c</span></code> abläuft.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA7.e</span></code> und danach nochmals mit <code class="docutils literal notranslate"><span class="pre">1</span></code> als erstem Argument. Dieser Argument Wert bewirkt, dass im Kindprozess ein ”Segmentation Error” erzeugt wird, also eine Speicherzugriffsverletzung. Welches Signal wird durch die Zugriffsverletzung an das Kind geschickt? Diese Information finden Sie im Manual mit <code class="docutils literal notranslate"><span class="pre">man</span> <span class="pre">7</span> <span class="pre">signal</span></code>. Schalten Sie nun core dump ein (siehe README) und starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA7.e</span> <span class="pre">1</span></code> erneut und analysieren Sie die Ausgabe.</p></li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><strong>Hinweis:</strong> ein core Dump ist ein Abbild des Speichers z.B. zum Zeitpunkt, wenn das Programm abstürzt (wie oben mit der Speicher Zugriff Verletzung). Der Dump wird im File <strong>core</strong> abgelegt und kann mit dem <strong>gdb</strong> (GNU-Debugger) gelesen werden (siehe <code class="docutils literal notranslate"><span class="pre">README</span></code>). Tippen Sie nach dem Starten des Command Line UI des <code class="docutils literal notranslate"><span class="pre">gdb</span> <span class="pre">where</span></code> gefolgt von list ein, damit sie den Ort des Absturzes sehen. Mit <code class="docutils literal notranslate"><span class="pre">quit</span></code> verlassen Sie <strong>gdb</strong> wieder.</p>
|
||||
<ol class="arabic">
|
||||
<li><p>Wenn Sie <code class="docutils literal notranslate"><span class="pre">ProcA7.e</span> <span class="pre">2</span></code> starten, sendet das Kind das Signal 30 an sich selbst. Was geschieht?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Wenn Sie <code class="docutils literal notranslate"><span class="pre">ProcA7.e</span> <span class="pre">3</span></code> starten, sendet ProcA7.e das Signal SIGABRT (abort) an das Kind: was geschieht in diesem Fall?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Mit <code class="docutils literal notranslate"><span class="pre">ProcA7.e</span> <span class="pre">4</span></code> wird das Kind gestartet und terminiert nach 5 Sekunden. Analysieren Sie wie in ProcA7.e der Lauf- bzw. Exit-Zustand des Kindes abgefragt wird (siehe dazu auch <code class="docutils literal notranslate"><span class="pre">man</span> <span class="pre">3</span> <span class="pre">exit</span></code>).</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-8-kindprozess-als-kopie-des-elternprozesses">
|
||||
<h3>3.8 Aufgabe 8: Kindprozess als Kopie des Elternprozesses<a class="headerlink" href="#aufgabe-8-kindprozess-als-kopie-des-elternprozesses" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Verstehen, wie Prozessräume vererbt werden.</p></li>
|
||||
<li><p>Unterschiede zwischen dem Prozessraum von Eltern und Kindern erfahren.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic">
|
||||
<li><p>Analysieren Sie Programm <code class="docutils literal notranslate"><span class="pre">ProcA8_1.c</span></code>: was gibt das Programm aus?</p>
|
||||
<ul class="simple">
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA8_1.e</span> </code>und überprüfen Sie Ihre Überlegungen.</p></li>
|
||||
<li><p>Waren Ihre Überlegungen richtig? Falls nicht, was könnten Sie falsch überlegt haben?</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Analysieren Sie Programm <code class="docutils literal notranslate"><span class="pre">ProcA8_2.c</span></code>: was gibt das Programm aus?</p>
|
||||
<ul class="simple">
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA8_2.e</span></code> und überprüfen Sie Ihre Überlegungen.</p></li>
|
||||
<li><p>Waren Ihre Überlegungen richtig? Falls nicht, was könnten Sie falsch gemacht haben?</p></li>
|
||||
<li><p>Kind und Eltern werden in verschiedener Reihenfolge ausgeführt: ist ein Unterschied ausser der Reihenfolge festzustellen?</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Analysieren Sie Programm <code class="docutils literal notranslate"><span class="pre">ProcA8_3.c</span></code> und Überlegen Sie, was in die Datei <code class="docutils literal notranslate"><span class="pre">AnyOutPut.txt</span></code> geschrieben wird, wer schreibt alles in diese Datei (sie wird ja vor <code class="docutils literal notranslate"><span class="pre">fork()</span></code> geöffnet) und wieso ist das so?</p>
|
||||
<ul class="simple">
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA8_3.e</span></code> und überprüfen Sie Ihre Überlegungen.</p></li>
|
||||
<li><p>Waren Ihre Überlegungen richtig? Falls nicht, wieso nicht?</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-9-unterschied-von-threads-gegenuber-prozessen">
|
||||
<h3>3.9 Aufgabe 9: Unterschied von Threads gegenüber Prozessen<a class="headerlink" href="#aufgabe-9-unterschied-von-threads-gegenuber-prozessen" title="Permalink to this headline">¶</a></h3>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Den Unterschied zwischen Thread und Prozess kennenlernen.</p></li>
|
||||
<li><p>Problemstellungen um Threads kennenlernen.</p></li>
|
||||
<li><p>Die <code class="docutils literal notranslate"><span class="pre">pthread</span></code>-Implementation kennen lernen.</p></li>
|
||||
</ul>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Studieren Sie Programm <code class="docutils literal notranslate"><span class="pre">ProcA9.c</span></code> und überlegen Sie, wie die Programmausgabe aussieht. Vergleichen Sie Ihre Überlegungen mit denjenigen aus Aufgabe 8.2 b) (<code class="docutils literal notranslate"><span class="pre">Pro-cA8_2.e</span></code>).</p>
|
||||
<ul class="simple">
|
||||
<li><p>Starten Sie <code class="docutils literal notranslate"><span class="pre">ProcA9.e</span></code> und vergleichen das Resultat mit Ihren Überlegungen.</p></li>
|
||||
<li><p>Was ist anders als bei <code class="docutils literal notranslate"><span class="pre">ProcA8_2.e</span></code>?</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic">
|
||||
<li><p>Setzen Sie in der Thread-Routine vor dem Befehl <code class="docutils literal notranslate"><span class="pre">pthread_exit()</span></code> eine unendliche Schleife ein, z.B. <code class="docutils literal notranslate"><span class="pre">while(1)</span> <span class="pre">{</span> <span class="pre">}</span></code>; .</p>
|
||||
<ul>
|
||||
<li><p>Starten Sie das Programm und beobachten Sie das Verhalten mit <code class="docutils literal notranslate"><span class="pre">top</span></code>. Was beobachten Sie und was schliessen Sie daraus?</p>
|
||||
<p><strong>Hinweis:</strong> wenn Sie in <code class="docutils literal notranslate"><span class="pre">top</span></code> den Buchstaben H eingeben, werden die Threads einzeln dargestellt.</p>
|
||||
</li>
|
||||
<li><p>Kommentieren Sie im Hauptprogram die beiden <code class="docutils literal notranslate"><span class="pre">pthread_join()</span></code> Aufrufe aus und starten Sie das Programm. Was geschieht? Erklären Sie das Verhalten.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-10-optional">
|
||||
<h3>3.10 Aufgabe 10 (optional):<a class="headerlink" href="#aufgabe-10-optional" title="Permalink to this headline">¶</a></h3>
|
||||
<section id="id1">
|
||||
<h4>3.10.1 Übersicht<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Dieser Teil des Praktikums behandelt spezielle Prozesse: die Dämon Prozesse («daemon pro-cesses»). Es ist gedacht als Zusatz zum Basis Praktikum über Prozesse und Threads.</p>
|
||||
<p>Auch dieser Teil ist ein «Analyse»- und «Experimentier»-Praktikum.</p>
|
||||
<hr class="docutils" />
|
||||
<section id="id2">
|
||||
<h5>3.10.1.1 Nachweis<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h5>
|
||||
<p>Dieses Praktikum ist eine leicht abgewandelte Variante des ProcThreads Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.</p>
|
||||
<p>Als Autoren des BSY Praktikums sind genannt: M. Thaler, J. Zeman.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="id3">
|
||||
<h4>3.10.2 Lernziele<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h4>
|
||||
<p>In diesem Praktikum werden Sie sich mit Dämon Prozessen beschäftigen.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie können die Problemstellung der Dämon Prozesse erklären</p></li>
|
||||
<li><p>Sie können einen Dämon Prozess kreieren</p></li>
|
||||
<li><p>Sie können aus dem Dämon Prozess mit der Umgebung kommunizieren</p></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-damon-prozesse">
|
||||
<h4>3.10.3 Aufgabe: Dämon Prozesse<a class="headerlink" href="#aufgabe-damon-prozesse" title="Permalink to this headline">¶</a></h4>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Problemstellungen um Daemons kennenlernen:</p>
|
||||
<ul>
|
||||
<li><p>wie wird ein Prozess zum Daemon?</p></li>
|
||||
<li><p>wie erreicht man, dass nur ein Daemon vom gleichen Typ aktiv ist?</p></li>
|
||||
<li><p>wie teilt sich ein Daemon seiner Umwelt mit?</p></li>
|
||||
<li><p>wo “lebt” ein Daemon?</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p><strong>Einleitung</strong></p>
|
||||
<p>Für diese Aufgabe haben wir einen Daemon implementiert: <strong>MrTimeDaemon</strong> gibt auf Anfrage die Systemzeit Ihres Rechners bekannt. Abfragen können Sie diese Zeit mit dem Programm <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span> <span class="pre">localhost</span></code>. Die Kommunikation zwischen den beiden Prozessen haben wir mit TCP/IP Sockets implementiert. Weitere Infos zum Daemon finden Sie nach den Aufgaben.</p>
|
||||
<p>Im Abschnitt 4 finden Sie Zusatzinformationen über diese Implementation eines Dämon Prozesses plus weiterführende Informationen.</p>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic">
|
||||
<li><p>Für die folgende Aufgabe benötigen Sie mindestens zwei Fenster (Kommandozeilen-Konsolen). Übersetzen Sie die Programme mit <code class="docutils literal notranslate"><span class="pre">make</span></code> und starten Sie das Programm <strong>PlapperMaul</strong> in einem der Fenster. Das Programm schreibt (ca.) alle 0.5 Sekunden <em>Hallo, ich bins…. Pidi</em> plus seine Prozess-ID auf den Bildschirm. Mit dem Shell Befehl <code class="docutils literal notranslate"><span class="pre">ps</span></code> können Sie Ihre aktiven Prozesse auflisten, auch <strong>PlapperMaul</strong>. Überlegen Sie sich zuerst, was mit <strong>PlapperMaul</strong> geschieht, wenn Sie das Fenster schliessen: läuft <strong>PlapperMaul</strong> weiter? Was geschieht mit <strong>PlapperMaul</strong> wenn Sie sich ausloggen und wieder einloggen? Testen Sie Ihre Überlegungen, in dem Sie die entsprechenden Aktionen durchführen. Stimmen Ihre Überlegungen?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Starten Sie nun das Programm bzw. den Daemon <strong>MrTimeDaemon</strong>. Stellen Sie die gleichen Überlegungen an wie mit <strong>PlapperMaul</strong> und testen Sie wiederum, ob Ihre Überlegungen stimmen. Ob <strong>MrTimeDaemon</strong> noch läuft können Sie feststellen, indem Sie die Zeit abfragen oder den Befehl <code class="docutils literal notranslate"><span class="pre">ps</span> <span class="pre">ajx</span> <span class="pre">|</span> <span class="pre">grep</span> <span class="pre">MrTimeDaemon</span></code> eingeben: was fällt Ihnen am Output auf? Was schliessen Sie aus Ihren Beobachtungen?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Starten Sie <strong>MrTimeDaemon</strong> erneut, was geschieht?</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Stoppen Sie nun <strong>MrTimeDaemon</strong> mit <code class="docutils literal notranslate"><span class="pre">killall</span> <span class="pre">MrTimeDaemon</span></code>.</p></li>
|
||||
<li><p>Starten Sie <strong>MrTimeDaemon</strong> und fragen Sie mit <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span> <span class="pre">localhost</span></code> oder mit <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span> <span class="pre">127.0.0.1</span></code> die aktuelle Zeit auf Ihrem Rechner ab.</p>
|
||||
<p><strong>Optional:</strong>
|
||||
Fragen Sie die Zeit bei einem Ihrer Kollegen ab. Dazu muss beim Server (dort wo <strong>MrTimeDaemon</strong> läuft) ev. die Firewall angepasst werden. Folgende Befehle müssen dazu mit <strong>root-Privilegien</strong> ausgeführt werden:</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>iptables-save > myTables.txt <span class="c1"># sichert die aktuelle Firewall</span>
|
||||
iptables -I INPUT <span class="m">1</span> -p tcp --dport <span class="m">65534</span> -j ACCEPT
|
||||
iptables -I OUTPUT <span class="m">2</span> -p tcp --sport <span class="m">65534</span> -j ACCEPT
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Nun sollten Sie über die IP-Nummer oder über den Rechner-Namen auf den <strong>TimeServer</strong> mit <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span></code> zugreifen können.
|
||||
Die Firewall können Sie mit folgendem Befehl wiederherstellen:</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>iptables-restore myTables.txt
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Studieren Sie <code class="docutils literal notranslate"><span class="pre">MrTimeDaemon.c</span></code>, <code class="docutils literal notranslate"><span class="pre">Daemonizer.c</span></code> und <code class="docutils literal notranslate"><span class="pre">TimeDaemon.c</span></code> und analysieren Sie, wie die Daemonisierung abläuft. Entfernen Sie die Kommentare im Macro <code class="docutils literal notranslate"><span class="pre">Out-PutPIDs</span></code> am Anfang des Moduls <code class="docutils literal notranslate"><span class="pre">Daemonizer.c</span></code>. Übersetzen Sie die Programme mit make und starten Sie <code class="docutils literal notranslate"><span class="pre">MrTimeDaemon</span></code> erneut. Analysieren Sie die Ausgabe, was fällt Ihnen auf? Notieren Sie alle für die vollständige Daemonisierung notwendigen Schritte.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>Setzen Sie beim Aufruf von <code class="docutils literal notranslate"><span class="pre">Daemonizer()</span></code> in <code class="docutils literal notranslate"><span class="pre">MrTimeDaemon.c</span></code> anstelle von <code class="docutils literal notranslate"><span class="pre">lock-FilePath</span></code> den Null-Zeiger <code class="docutils literal notranslate"><span class="pre">NULL</span></code> ein. Damit wird keine lock-Datei erzeugt. Übersetzen Sie die Programme und starten Sie erneut <code class="docutils literal notranslate"><span class="pre">MrTimedaemon</span></code>. Was geschieht bzw. wie können Sie feststellen, was geschehen ist?</p>
|
||||
<p><strong>Hinweis:</strong> lesen Sie das log-File: <code class="docutils literal notranslate"><span class="pre">/tmp/timeDaemon.log.</span></code></p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Wenn Sie noch Zeit und Lust haben: messen Sie die Zeit, zwischen Start der Zeitanfrage und Eintreffen der Antwort. Dazu müssen Sie die Datei <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr.c</span></code> entsprechend anpassen.</p>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="zusatzinformationen">
|
||||
<h4>3.10.4 Zusatzinformationen<a class="headerlink" href="#zusatzinformationen" title="Permalink to this headline">¶</a></h4>
|
||||
<hr class="docutils" />
|
||||
<section id="diese-implementation">
|
||||
<h5>3.10.4.1 Diese Implementation<a class="headerlink" href="#diese-implementation" title="Permalink to this headline">¶</a></h5>
|
||||
<p>Dieser Daemon besteht aus den 3 Komponenten.</p>
|
||||
<p><strong>Hauptprogramm: MrTimeDaemon.c</strong></p>
|
||||
<p>Hier werden die Pfade für die lock-Datei, die log-Datei und der ”Aufenthaltsort” des Daemons gesetzt. Die lock-Datei wird benötigt um sicherzustellen, dass der Daemon nur einmal gestartet werden kann. In die lock-Datei schreibt der Daemon z.B. seine PID und sperrt sie dann für Schreiben. Wird der Daemon ein zweites Mal gestartet und will seine PID in diese Datei schreiben, erhält er eine Fehlermeldung und terminiert (es soll ja nur ein Daemon arbeiten). Terminiert der Daemon, wird die Datei automatisch freigegeben. Weil Daemonen sämtliche Kontakte mit ihrer Umwelt im Normalfall abbrechen und auch kein Kontrollterminal besitzen, ist es sinnvoll, zumindest die Ausgabe des Daemons in eine log-Datei umzuleiten. Dazu stehen einige Systemfunktionen für Logging zur Verfügung. Der Einfachheit halber haben wir hier eine normale Datei im Verzeichnis <code class="docutils literal notranslate"><span class="pre">/tmp</span></code> gewählt.</p>
|
||||
<blockquote>
|
||||
<div><p><strong>Anmerkung:</strong> die Wahl des Verzeichnisses <code class="docutils literal notranslate"><span class="pre">/tmp</span></code> für die lock- und log-Datei ist für den normalen Betrieb problematisch, weil der Inhalt dieses Verzeichnisses jederzeit gelöscht werden kann, bzw. darf. Wir haben dieses Verzeichnis gewählt, weil wir die beiden Dateien nur für die kurze Zeit des Praktikums benötigen.</p>
|
||||
</div></blockquote>
|
||||
<p>Der Daemon erbt sein Arbeitsverzeichnis vom Elternprozesse, er sollte deshalb in ein festes Verzeichnis des Systems wechseln, um zu verhindern, dass er sich in einem montierten (gemounteten) Verzeichnis aufhält, das dann beim Herunterfahren nicht demontiert werden könnte (wir haben hier wiederum <code class="docutils literal notranslate"><span class="pre">/tmp</span></code> gewählt).</p>
|
||||
<p><strong>Daemonizer: Daemonizer.c</strong></p>
|
||||
<p>Der Daemonizer macht aus dem aktuellen Prozess einen Daemon. Z.B. sollte er Signale (eine Art Softwareinterrupts) ignorieren: wenn Sie die CTRL-C Taste während dem Ausführen eines Vordergrundprozess drücken, erhält dieser vom Betriebssystem das Signal SIGINT und bricht seine Ausführung ab. Weiter sollte er die Dateierzeugungsmaske auf 0 setzen (Dateizugriffsrechte), damit kann er beim Öffnen von Dateien beliebige Zugriffsrechte verlangen (die Dateierzeugungsmaske erbt er vom Elternprozess). Am Schluss startet der Daemonizer das eigentliche Daemonprogramm: TimeDaemon.e.</p>
|
||||
<p><strong>Daemonprogramm: TimeDaemon.c</strong></p>
|
||||
<p>Das Daemonprogramm wartet in einer unendlichen Schleife auf Anfragen zur Zeit und schickt die Antwort an den Absender zurück. Die Datenkommunikation ist, wie schon erwähnt, mit Sockets implementiert, auf die wir aber im Rahmen dieses Praktikums nicht weiter eingehen wollen (wir stellen lediglich Hilfsfunktionen zur Verfügung).</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="zusatzinformation-zu-damon-prozessen">
|
||||
<h5>3.10.4.2 Zusatzinformation zu Dämon Prozessen<a class="headerlink" href="#zusatzinformation-zu-damon-prozessen" title="Permalink to this headline">¶</a></h5>
|
||||
<p>Dämonen oder englisch Daemons sind eine spezielle Art von Prozessen, die vollständig unabhängig arbeiten, d.h. ohne direkte Interaktion mit dem Anwender. Dämonen sind Hintergrundprozesse und terminieren i.A. nur, wenn das System heruntergefahren wird oder abstürzt. Dämonen erledigen meist Aufgaben, die periodisch ausgeführt werden müssen, z.B. Überwachung von Systemkomponenten, abfragen, ob neue Mails angekommen sind, etc.</p>
|
||||
<p>Ein typisches Beispiel unter Unix ist der Printer Daemon <code class="docutils literal notranslate"><span class="pre">lpd</span></code>, der periodisch nachschaut, ob ein Anwender eine Datei zum Ausdrucken hinterlegt hat. Wenn ja, schickt er die Datei auf den Drucker.</p>
|
||||
<p>Hier wird eine weitere Eigenschaft von Daemons ersichtlich: meist kann nur ein Dämon pro Aufgabe aktiv sein: stellen Sie sich vor, was passiert, wenn zwei Druckerdämonen gleichzeitig arbeiten. Andererseits muss aber auch dafür gesorgt werden, dass ein Dämon wieder gestartet wird, falls er stirbt.</p>
|
||||
<hr class="docutils" />
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>4. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Punkte</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p></p></td>
|
||||
<td class="text-left"><p>Sie können die gestellten Fragen erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>1</p></td>
|
||||
<td class="text-left"><p>Prozess mit <code class="docutils literal notranslate"><span class="pre">fork()</span></code> erzeugen</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>2</p></td>
|
||||
<td class="text-left"><p>Prozess mit <code class="docutils literal notranslate"><span class="pre">fork()</span></code> und <code class="docutils literal notranslate"><span class="pre">exec()</span></code>: Programm Image ersetzen</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>3</p></td>
|
||||
<td class="text-left"><p>Prozesshierarchie analysieren</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>4</p></td>
|
||||
<td class="text-left"><p>Zeitlicher Ablauf von Prozessen</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>5</p></td>
|
||||
<td class="text-left"><p>Waisenkinder (Orphan Processes)</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>6</p></td>
|
||||
<td class="text-left"><p>Terminierte, halbtote Prozesse (Zombies)</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>7</p></td>
|
||||
<td class="text-left"><p>Auf Terminieren von Kindprozessen warten</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>8</p></td>
|
||||
<td class="text-left"><p>Kindprozess als Kopie des Elternprozesses</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>9</p></td>
|
||||
<td class="text-left"><p>Unterschied von Threads gegenüber Prozessen</p></td>
|
||||
<td class="text-left"><p>0.5</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>10</p></td>
|
||||
<td class="text-left"><p>Dämon Prozesse</p></td>
|
||||
<td class="text-left"><p>(4)</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 11.01.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">07 - Prozesse und Threads</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#nachweis">1.1 Nachweis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgaben">3. Aufgaben</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-1-prozess-mit-fork-erzeugen">3.1 Aufgabe 1: Prozess mit fork() erzeugen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-2-prozess-mit-fork-und-exec-programm-image-ersetzen">3.2 Aufgabe 2: Prozess mit fork() und exec(): Programm Image ersetzen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-3-prozesshierarchie-analysieren">3.3 Aufgabe 3: Prozesshierarchie analysieren</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-4-zeitlicher-ablauf-von-prozessen">3.4 Aufgabe 4: Zeitlicher Ablauf von Prozessen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-5-waisenkinder-orphan-processes">3.5 Aufgabe 5: Waisenkinder (Orphan Processes)</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-6-terminierte-halbtote-prozesse-zombies">3.6 Aufgabe 6: Terminierte, halbtote Prozesse (Zombies)</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-7-auf-terminieren-von-kindprozessen-warten">3.7 Aufgabe 7: Auf Terminieren von Kindprozessen warten</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-8-kindprozess-als-kopie-des-elternprozesses">3.8 Aufgabe 8: Kindprozess als Kopie des Elternprozesses</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-9-unterschied-von-threads-gegenuber-prozessen">3.9 Aufgabe 9: Unterschied von Threads gegenüber Prozessen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-10-optional">3.10 Aufgabe 10 (optional):</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#id1">3.10.1 Übersicht</a><ul>
|
||||
<li class="toctree-l5"><a class="reference internal" href="#id2">3.10.1.1 Nachweis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#id3">3.10.2 Lernziele</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#aufgabe-damon-prozesse">3.10.3 Aufgabe: Dämon Prozesse</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#zusatzinformationen">3.10.4 Zusatzinformationen</a><ul>
|
||||
<li class="toctree-l5"><a class="reference internal" href="#diese-implementation">3.10.4.1 Diese Implementation</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="#zusatzinformation-zu-damon-prozessen">3.10.4.2 Zusatzinformation zu Dämon Prozessen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P06_Personen_Verwaltung_Linked_List/README.html" title="previous chapter">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li>Next: <a href="../P08_Sync/README.html" title="next chapter">08 - Synchronisationsprobleme</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P07_Prozesse_und_Threads/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,264 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>09/02 - Dämon Prozesse — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="damon-prozesse">
|
||||
<h1>09/02 - Dämon Prozesse<a class="headerlink" href="#damon-prozesse" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<p><img alt="" src="../_images/daemon.png" /></p>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Dieser Teil des Praktikums behandelt spezielle Prozesse: die Dämon Prozesse («daemon pro-cesses»). Es ist gedacht als Zusatz zum Basis Praktikum über Prozesse und Threads.</p>
|
||||
<p>Auch dieser Teil ist ein «Analyse»- und «Experimentier»-Praktikum.</p>
|
||||
<hr class="docutils" />
|
||||
<section id="nachweis">
|
||||
<h3>1.1 Nachweis<a class="headerlink" href="#nachweis" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Dieses Praktikum ist eine leicht abgewandelte Variante des ProcThreads Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.</p>
|
||||
<p>Als Autoren des BSY Praktikums sind genannt: M. Thaler, J. Zeman.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum werden Sie sich mit Dämon Prozessen beschäftigen.</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie können die Problemstellung der Dämon Prozesse erklären</p></li>
|
||||
<li><p>Sie können einen Dämon Prozess kreieren</p></li>
|
||||
<li><p>Sie können aus dem Dämon Prozess mit der Umgebung kommunizieren</p></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-damon-prozesse">
|
||||
<h2>3. Aufgabe: Dämon Prozesse<a class="headerlink" href="#aufgabe-damon-prozesse" title="Permalink to this headline">¶</a></h2>
|
||||
<p><strong>Ziele</strong></p>
|
||||
<ul class="simple">
|
||||
<li><p>Problemstellungen um Daemons kennenlernen:</p>
|
||||
<ul>
|
||||
<li><p>wie wird ein Prozess zum Daemon?</p></li>
|
||||
<li><p>wie erreicht man, dass nur ein Daemon vom gleichen Typ aktiv ist?</p></li>
|
||||
<li><p>wie teilt sich ein Daemon seiner Umwelt mit?</p></li>
|
||||
<li><p>wo “lebt” ein Daemon?</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p><strong>Einleitung</strong></p>
|
||||
<p>Für diese Aufgabe haben wir einen Daemon implementiert: <strong>MrTimeDaemon</strong> gibt auf Anfrage die Systemzeit Ihres Rechners bekannt. Abfragen können Sie diese Zeit mit dem Programm <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span> <span class="pre">localhost</span></code>. Die Kommunikation zwischen den beiden Prozessen haben wir mit TCP/IP Sockets implementiert. Weitere Infos zum Daemon finden Sie nach den Aufgaben.</p>
|
||||
<p>Im Abschnitt 4 finden Sie Zusatzinformationen über diese Implementation eines Dämon Prozesses plus weiterführende Informationen.</p>
|
||||
<p><strong>Aufgaben</strong></p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Für die folgende Aufgabe benötigen Sie mindestens zwei Fenster (Kommandozeilen-Konsolen). Übersetzen Sie die Programme mit <code class="docutils literal notranslate"><span class="pre">make</span></code> und starten Sie das Programm <strong>PlapperMaul</strong> in einem der Fenster. Das Programm schreibt (ca.) alle 0.5 Sekunden <em>Hallo, ich bins…. Pidi</em> plus seine Prozess-ID auf den Bildschirm. Mit dem Shell Befehl <code class="docutils literal notranslate"><span class="pre">ps</span></code> können Sie Ihre aktiven Prozesse auflisten, auch <strong>PlapperMaul</strong>. Überlegen Sie sich zuerst, was mit <strong>PlapperMaul</strong> geschieht, wenn Sie das Fenster schliessen: läuft <strong>PlapperMaul</strong> weiter? Was geschieht mit <strong>PlapperMaul</strong> wenn Sie sich ausloggen und wieder einloggen? Testen Sie Ihre Überlegungen, in dem Sie die entsprechenden Aktionen durchführen. Stimmen Ihre Überlegungen?</p></li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Starten Sie nun das Programm bzw. den Daemon <strong>MrTimeDaemon</strong>. Stellen Sie die gleichen Überlegungen an wie mit <strong>PlapperMaul</strong> und testen Sie wiederum, ob Ihre Überlegungen stimmen. Ob <strong>MrTimeDaemon</strong> noch läuft können Sie feststellen, indem Sie die Zeit abfragen oder den Befehl <code class="docutils literal notranslate"><span class="pre">ps</span> <span class="pre">ajx</span> <span class="pre">|</span> <span class="pre">grep</span> <span class="pre">MrTimeDaemon</span></code> eingeben: was fällt Ihnen am Output auf? Was schliessen Sie aus Ihren Beobachtungen?</p></li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Starten Sie <strong>MrTimeDaemon</strong> erneut, was geschieht?</p></li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Stoppen Sie nun <strong>MrTimeDaemon</strong> mit <code class="docutils literal notranslate"><span class="pre">killall</span> <span class="pre">MrTimeDaemon</span></code>.</p></li>
|
||||
<li><p>Starten Sie <strong>MrTimeDaemon</strong> und fragen Sie mit <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span> <span class="pre">localhost</span></code> oder mit <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span> <span class="pre">127.0.0.1</span></code> die aktuelle Zeit auf Ihrem Rechner ab.</p></li>
|
||||
</ol>
|
||||
<p><strong>Optional:</strong>
|
||||
Fragen Sie die Zeit bei einem Ihrer Kollegen ab. Dazu muss beim Server (dort wo <strong>MrTimeDaemon</strong> läuft) ev. die Firewall angepasst werden. Folgende Befehle müssen dazu mit <strong>root-Privilegien</strong> ausgeführt werden:</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>iptables-save > myTables.txt <span class="c1"># sichert die aktuelle Firewall</span>
|
||||
iptables -I INPUT <span class="m">1</span> -p tcp --dport <span class="m">65534</span> -j ACCEPT
|
||||
iptables -I OUTPUT <span class="m">2</span> -p tcp --sport <span class="m">65534</span> -j ACCEPT
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Nun sollten Sie über die IP-Nummer oder über den Rechner-Namen auf den <strong>TimeServer</strong> mit <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr</span></code> zugreifen können.
|
||||
Die Firewall können Sie mit folgendem Befehl wiederherstellen:</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>iptables-restore myTables.txt
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Studieren Sie <code class="docutils literal notranslate"><span class="pre">MrTimeDaemon.c</span></code>, <code class="docutils literal notranslate"><span class="pre">Daemonizer.c</span></code> und <code class="docutils literal notranslate"><span class="pre">TimeDaemon.c</span></code> und analysieren Sie, wie die Daemonisierung abläuft. Entfernen Sie die Kommentare im Macro <code class="docutils literal notranslate"><span class="pre">Out-PutPIDs</span></code> am Anfang des Moduls <code class="docutils literal notranslate"><span class="pre">Daemonizer.c</span></code>. Übersetzen Sie die Programme mit make und starten Sie <code class="docutils literal notranslate"><span class="pre">MrTimeDaemon</span></code> erneut. Analysieren Sie die Ausgabe, was fällt Ihnen auf? Notieren Sie alle für die vollständige Daemonisierung notwendigen Schritte.</p></li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic">
|
||||
<li><p>Setzen Sie beim Aufruf von <code class="docutils literal notranslate"><span class="pre">Daemonizer()</span></code> in <code class="docutils literal notranslate"><span class="pre">MrTimeDaemon.c</span></code> anstelle von <code class="docutils literal notranslate"><span class="pre">lock-FilePath</span></code> den Null-Zeiger <code class="docutils literal notranslate"><span class="pre">NULL</span></code> ein. Damit wird keine lock-Datei erzeugt. Übersetzen Sie die Programme und starten Sie erneut <code class="docutils literal notranslate"><span class="pre">MrTimedaemon</span></code>. Was geschieht bzw. wie können Sie feststellen, was geschehen ist?</p>
|
||||
<p><strong>Hinweis:</strong> lesen Sie das log-File: <code class="docutils literal notranslate"><span class="pre">/tmp/timeDaemon.log.</span></code></p>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Wenn Sie noch Zeit und Lust haben: messen Sie die Zeit, zwischen Start der Zeitanfrage und Eintreffen der Antwort. Dazu müssen Sie die Datei <code class="docutils literal notranslate"><span class="pre">WhatsTheTimeMr.c</span></code> entsprechend anpassen.</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="zusatzinformationen">
|
||||
<h2>4. Zusatzinformationen<a class="headerlink" href="#zusatzinformationen" title="Permalink to this headline">¶</a></h2>
|
||||
<hr class="docutils" />
|
||||
<section id="diese-implementation">
|
||||
<h3>4.1 Diese Implementation<a class="headerlink" href="#diese-implementation" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Dieser Daemon besteht aus den 3 Komponenten.</p>
|
||||
<p><strong>Hauptprogramm: MrTimeDaemon.c</strong></p>
|
||||
<p>Hier werden die Pfade für die lock-Datei, die log-Datei und der ”Aufenthaltsort” des Daemons gesetzt. Die lock-Datei wird benötigt um sicherzustellen, dass der Daemon nur einmal gestartet werden kann. In die lock-Datei schreibt der Daemon z.B. seine PID und sperrt sie dann für Schreiben. Wird der Daemon ein zweites Mal gestartet und will seine PID in diese Datei schreiben, erhält er eine Fehlermeldung und terminiert (es soll ja nur ein Daemon arbeiten). Terminiert der Daemon, wird die Datei automatisch freigegeben. Weil Daemonen sämtliche Kontakte mit ihrer Umwelt im Normalfall abbrechen und auch kein Kontrollterminal besitzen, ist es sinnvoll, zumindest die Ausgabe des Daemons in eine log-Datei umzuleiten. Dazu stehen einige Systemfunktionen für Logging zur Verfügung. Der Einfachheit halber haben wir hier eine normale Datei im Verzeichnis <code class="docutils literal notranslate"><span class="pre">/tmp</span></code> gewählt.</p>
|
||||
<blockquote>
|
||||
<div><p><strong>Anmerkung:</strong> die Wahl des Verzeichnisses <code class="docutils literal notranslate"><span class="pre">/tmp</span></code> für die lock- und log-Datei ist für den normalen Betrieb problematisch, weil der Inhalt dieses Verzeichnisses jederzeit gelöscht werden kann, bzw. darf. Wir haben dieses Verzeichnis gewählt, weil wir die beiden Dateien nur für die kurze Zeit des Praktikums benötigen.</p>
|
||||
</div></blockquote>
|
||||
<p>Der Daemon erbt sein Arbeitsverzeichnis vom Elternprozesse, er sollte deshalb in ein festes Verzeichnis des Systems wechseln, um zu verhindern, dass er sich in einem montierten (gemounteten) Verzeichnis aufhält, das dann beim Herunterfahren nicht demontiert werden könnte (wir haben hier wiederum <code class="docutils literal notranslate"><span class="pre">/tmp</span></code> gewählt).</p>
|
||||
<p><strong>Daemonizer: Daemonizer.c</strong></p>
|
||||
<p>Der Daemonizer macht aus dem aktuellen Prozess einen Daemon. Z.B. sollte er Signale (eine Art Softwareinterrupts) ignorieren: wenn Sie die CTRL-C Taste während dem Ausführen eines Vordergrundprozess drücken, erhält dieser vom Betriebssystem das Signal SIGINT und bricht seine Ausführung ab. Weiter sollte er die Dateierzeugungsmaske auf 0 setzen (Dateizugriffsrechte), damit kann er beim Öffnen von Dateien beliebige Zugriffsrechte verlangen (die Dateierzeugungsmaske erbt er vom Elternprozess). Am Schluss startet der Daemonizer das eigentliche Daemonprogramm: TimeDaemon.e.</p>
|
||||
<p><strong>Daemonprogramm: TimeDaemon.c</strong></p>
|
||||
<p>Das Daemonprogramm wartet in einer unendlichen Schleife auf Anfragen zur Zeit und schickt die Antwort an den Absender zurück. Die Datenkommunikation ist, wie schon erwähnt, mit Sockets implementiert, auf die wir aber im Rahmen dieses Praktikums nicht weiter eingehen wollen (wir stellen lediglich Hilfsfunktionen zur Verfügung).</p>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="zusatzinformation-zu-damon-prozessen">
|
||||
<h3>4.2 Zusatzinformation zu Dämon Prozessen<a class="headerlink" href="#zusatzinformation-zu-damon-prozessen" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Dämonen oder englisch Daemons sind eine spezielle Art von Prozessen, die vollständig unabhängig arbeiten, d.h. ohne direkte Interaktion mit dem Anwender. Dämonen sind Hintergrundprozesse und terminieren i.A. nur, wenn das System heruntergefahren wird oder abstürzt. Dämonen erledigen meist Aufgaben, die periodisch ausgeführt werden müssen, z.B. Überwachung von Systemkomponenten, abfragen, ob neue Mails angekommen sind, etc.</p>
|
||||
<p>Ein typisches Beispiel unter Unix ist der Printer Daemon <code class="docutils literal notranslate"><span class="pre">lpd</span></code>, der periodisch nachschaut, ob ein Anwender eine Datei zum Ausdrucken hinterlegt hat. Wenn ja, schickt er die Datei auf den Drucker.</p>
|
||||
<p>Hier wird eine weitere Eigenschaft von Daemons ersichtlich: meist kann nur ein Dämon pro Aufgabe aktiv sein: stellen Sie sich vor, was passiert, wenn zwei Druckerdämonen gleichzeitig arbeiten. Andererseits muss aber auch dafür gesorgt werden, dass ein Dämon wieder gestartet wird, falls er stirbt.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>5. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Punkte</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p></p></td>
|
||||
<td class="text-left"><p>Sie können die gestellten Fragen erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>1</p></td>
|
||||
<td class="text-left"><p>Dämon Prozesse</p></td>
|
||||
<td class="text-left"><p>4</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 11.01.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P07_Prozesse_und_Threads/README_P02.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,384 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>08 - Synchronisationsprobleme — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="09 - File Operations" href="../P09_File_Operations/README.html" />
|
||||
<link rel="prev" title="07 - Prozesse und Threads" href="../P07_Prozesse_und_Threads/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="synchronisationsprobleme">
|
||||
<h1>08 - Synchronisationsprobleme<a class="headerlink" href="#synchronisationsprobleme" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
<p><img alt="" src="../_images/synchronisationsprobleme.png" /></p>
|
||||
<p><a class="reference external" href="https://commons.wikimedia.org/wiki/File:Velgast-suedbahn.jpg">Quelle: https://commons.wikimedia.org/wiki/File:Velgast-suedbahn.jpg</a></p>
|
||||
<p>In diesem Praktikum lernen sie zuerst am Beispiel eines Kaffee-Automaten verschiedene grundlegende Synchronisationsprobleme kennen und mit Hilfe von Locks (Mutexes) und Semaphoren lösen:</p>
|
||||
<ul class="simple">
|
||||
<li><p>gegenseitiger Ausschluss mit einem Lock</p></li>
|
||||
<li><p>Erzwingen einer einfachen Reihenfolge</p></li>
|
||||
<li><p>Erzwingen einer erweiterten Reihenfolge</p></li>
|
||||
</ul>
|
||||
<p>Im zweiten Teil werden sie auf Basis dieser Grundlagen ein komplexeres Synchronisationsproblem bearbeiten, diesmal am Beispiel von Bank Transaktionen.</p>
|
||||
<hr class="docutils" />
|
||||
<section id="nachweis">
|
||||
<h3>1.1 Nachweis<a class="headerlink" href="#nachweis" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Dieses Praktikum ist eine leicht abgewandelte Variante des Sync Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.</p>
|
||||
<p>Als Autor des BSY Praktikums ist genannt: M. Thaler.</p>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In diesem Praktikum werden sie Synchronisationsprobleme lösen</p>
|
||||
<ul class="simple">
|
||||
<li><p>Sie wissen wie man systematisch Synchronisationsprobleme analysiert</p></li>
|
||||
<li><p>Sie wissen wann ein potentieller Deadlock entstehen kann</p></li>
|
||||
<li><p>Sie können Mutex mit Threads anwenden</p></li>
|
||||
<li><p>Sie können Semaphoren mit Prozessen anwenden</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="einfuhrung">
|
||||
<h2>3. Einführung<a class="headerlink" href="#einfuhrung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Das Lösen von Synchronisationsproblemen ist oft nicht einfach, weil Prozesse bzw. Threads gleichzeitig ablaufen, ihre Aktivitäten jedoch nach Vorgaben koordiniert werden müssen: man verliert schnell den Überblick. Systematisches Vorgehen mit Aufzeichnen der Abläufe und Synchronisationsbedingungen bewährt ich sich in diesem Fall.</p>
|
||||
<hr class="docutils" />
|
||||
<section id="wie-lost-man-synchronisationsprobleme">
|
||||
<h3>3.1 Wie löst man Synchronisationsprobleme?<a class="headerlink" href="#wie-lost-man-synchronisationsprobleme" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Gehen sie beim Lösen von Synchronisationsproblemen in folgenden Schritten vor:</p>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Schritt 1: Prozesse (Threads) der Problemstellung identifizieren.</strong><br />
|
||||
Prozesse sind die Aktivitäten, die gleichzeitig ausgeführt werden. In diesem Sinne sind sie eigenständige Ausführungs-Einheiten, deren zeitliches Verhalten synchronisiert werden muss.</p></li>
|
||||
<li><p><strong>Schritt 2: Ausführungsschritte der einzelnen Prozesse (Threads) ermitteln.</strong><br />
|
||||
Erstellen sie eine Liste mit einer Spalte für jeden Prozess. Notieren sie für jeden Prozess stichwortartig die wesentlichen Aktionen in der gewünschten zeitlichen Reihenfolge. Tragen sie noch keine Synchronisationsoperationen ein, sondern Texte wie warten auf Geld, etc. Übertragen sie anschliessend die Liste in einen Ablaufgraphen (Siehe Beispiel in Abbildung 1).</p></li>
|
||||
<li><p><strong>Schritt 3: Synchronisationsbedingungen ermitteln.</strong><br />
|
||||
Eine Synchronisationsbedingung ist eine zeitliche Beziehung (Abhängigkeit) zwischen Aktionen verschiedener Prozesse, die für das korrekte Arbeiten erforderlich ist. Zeichnen sie diese Beziehungen mit Pfeilen in den Ablaufgraphen aus Schritt 2 ein (Siehe Abbildung 1).</p></li>
|
||||
<li><p><strong>Schritt 4: Benötigte Semaphore definieren.</strong><br />
|
||||
Für jede Synchronisationsbedingung wird ein eigener Semaphor benötigt. Notieren sie für jeden Semaphor einen Namen und den Wert, mit dem er initialisiert werden muss.</p></li>
|
||||
<li><p><strong>Schritt 5: Prozesse mit Semaphore Operationen ergänzen.</strong><br />
|
||||
Erweitern sie nun alle Prozesse aus Schritt 2 mit den notwendigen Semaphore Operati-onen (Siehe Pseudocode in Abbildung 1).</p></li>
|
||||
<li><p><strong>Schritt 6: Implementation.</strong><br />
|
||||
Implementieren und testen sie das vollständige Programm.</p></li>
|
||||
</ul>
|
||||
<p><img alt="" src="../_images/coffee_customer.png" /></p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">coin</span> <span class="o">=</span> <span class="n">sem_open</span><span class="p">(...,</span><span class="mi">0</span><span class="p">);</span>
|
||||
<span class="n">coffee</span> <span class="o">=</span> <span class="n">sem_open</span><span class="p">(...,</span><span class="mi">0</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Ablaufgraph und Pseudocode für 2 Prozesse und zwei Semaphore<br />
|
||||
<img alt="" src="../_images/sequence_graph.png" /></p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="der-kaffee-automat">
|
||||
<h2>4. Der Kaffee-Automat<a class="headerlink" href="#der-kaffee-automat" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Als Beispiel verwenden wir einen Automaten, der Kaffee verkauft. Der Kunde muss zum Kauf eines Kaffees zuerst eine bzw. mehrere Münzen einwerfen und anschliessend den gewünsch-ten Kaffee wählen. Der Automat gibt dann das entsprechende Getränk aus.</p>
|
||||
<p>Im ersten Beispiel werden der Automat und die Kunden mit Threads modelliert und tauschen Daten über gemeinsame Speichervariablen aus. Im zweiten und dritten Beispiel werden der Automat und die Kunden mit Prozessen modelliert, dabei wird der Ablauf mit Hilfe von Sema-phoren gesteuert bzw. erzwungen.</p>
|
||||
<p><strong>Hinweis:</strong> die Programme zu den folgenden Aufgaben können alle mit <strong>startApp.e</strong> gestartet werden. Dieses Programm startet und stoppt Threads und Prozesse, alloziert und dealloziert die Ressourcen (Mutexes, Semaphore).</p>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-mutual-exclusion">
|
||||
<h3>4.1 Aufgabe: Mutual Exclusion<a class="headerlink" href="#aufgabe-mutual-exclusion" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Greifen mehrere Threads (oder Prozesse) auf gemeinsame Daten zu, können sogenannte Race Conditions entstehen. Das Resultat ist in diesem Fall abhängig von der Reihenfolge, in der die Threads (Prozesse) ausgeführt werden.</p>
|
||||
<p>Im vorliegenden Beispiel wirft der Kunde eine 1 Euro Münze ein und drückt anschliessend auf eine von zwei Kaffeewahltasten. Dabei wird die Anzahl Münzen (<em>coinCount</em>) und die gewählte Kaffeesorte (<em>selCount1</em>, <em>selCount2</em>) inkrementiert. Diese Variablen sind in der Datenstruktur <em>cData</em> abgelegt, auf die gemeinsam Kaffee-Automat und Kunden zugreifen können. Der Auto-mat überprüft, ob die Anzahl Münzen und die Anzahl der Kaffeewahlen gleich gross sind, falls nicht, wird eine Fehlermeldung ausgegeben und alle Zähler auf <em>Null</em> gesetzt.</p>
|
||||
<section id="aufgaben">
|
||||
<h4>Aufgaben<a class="headerlink" href="#aufgaben" title="Permalink to this headline">¶</a></h4>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Übersetzen sie die Programme im Verzeichnis <em>mutex</em> mit <em>make</em> und starten sie den Kaffee-Automaten mit <strong>startApp.e</strong> mehrmals hintereinander.
|
||||
Analysieren sie die Datenwerte in den Fehlermeldungen, beschreiben sie was die Gründe dafür sind bzw. sein können.</p></li>
|
||||
<li><p>Schützen sie nun den Zugriff auf die gemeinsamen Daten mit einem Mutex so, dass alle Threads eine konsistente Sicht der Daten haben.
|
||||
Wir haben für sie einen Mutex vorbereitet: die Datenstruktur <em>cData</em> enthält die Mutex-Variable <em>mutex</em>, die in <strong>startApp.c</strong> initialisiert wird. Die Funktionen für das Schliessen und das Öffnen des Mutex (Locks) aus der <em>pthread</em> Bibliothek sind:</p></li>
|
||||
</ol>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">pthread</span> <span class="n">mutex</span> <span class="n">lock</span><span class="p">(</span><span class="o">&</span><span class="p">(</span><span class="n">cD</span><span class="o">-></span><span class="n">lock</span><span class="p">));</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>und</p></li>
|
||||
</ul>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">pthread</span> <span class="n">mutex</span> <span class="n">unlock</span><span class="p">(</span><span class="o">&</span><span class="p">(</span><span class="n">cD</span><span class="o">-></span><span class="n">lock</span><span class="p">));</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Überprüfen sie, ob der Kaffee-Automat nun keine Fehlermeldungen mehr ausgibt. Erhö-hen sie dazu auch die Anzahl Kunden <em>CUSTOMERS</em> in <strong>commonDefs.h</strong>, z.B. auf 10.</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Im Thread des Kaffee-Automaten wird an verschiedenen Orten mehrmals auf die gemeinsamen Daten in <em>cD</em> zugegriffen. Wenn sie die gemeinsamen Daten in lokale Variablen kopieren und dann nur noch auf diese lokalen Variablen zugreifen würden, könn-ten sie dann auf die Synchronisation mit dem Mutex verzichten?</p></li>
|
||||
<li><p>Wie oft kann ein einzelner Kunde einen Kaffee beziehen, bis der nächste Kunde an die Reihe kommt? Hier reicht eine qualitative Aussage.</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
</section>
|
||||
<section id="aufgabe-einfache-reihenfolge">
|
||||
<h3>4.2 Aufgabe: Einfache Reihenfolge<a class="headerlink" href="#aufgabe-einfache-reihenfolge" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Wie sie im ersten Beispiel festgestellt haben, verhindert ein Mutex zwar, dass Race Conditions auftreten, die Verarbeitungsreihenfolge der Threads lässt sich jedoch nicht beeinflussen und ist zufällig.
|
||||
Im Folgenden soll eine erzwungene Verarbeitungsreihenfolge implementiert werden:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Ein Kunde benutzt den Automat für einen Kaffeekauf exklusiv, d.h. alle Schritte des Kunden werden innerhalb eines Mutexes ausgeführt. Ist ein Kunde an der Reihe, wartet er bis der Automat bereit ist, wirft eine Münze ein, wartet auf den Kaffee und gibt anschlies-send den Automaten für den nächsten Kunden frei.</p></li>
|
||||
<li><p>Der Automat meldet zuerst in einer Endlos-Schleife, dass er für die Geld-Eingabe bereit ist, wartet dann auf die Eingabe einer Münze, gibt den Kaffee aus und meldet anschliessend wieder, wenn er bereit ist, etc.</p></li>
|
||||
</ul>
|
||||
<p>Für die Lösung dieses Problems benötigen wir Semaphore, die, im Gegensatz zu Mutexes, auch in verschiedenen Prozessen gesetzt bzw. zurückgesetzt werden dürfen. Den Kaffee-Automat und die Kunden implementieren wir mit Prozessen. sie finden die entsprechenden Prozesse im Verzeichnis <strong>basicSequence</strong>.</p>
|
||||
<section id="id1">
|
||||
<h4>Aufgaben<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h4>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Beschreiben sie den Kaffee-Automaten mit Hilfe der 6 Schritte aus Abschnitt 3 auf Papier, dokumentieren sie dabei alle Schritte schriftlich.</p></li>
|
||||
<li><p>Implementieren sie nun den Kaffee-Automaten. Ergänzen sie dazu den <em>coffeeTeller</em> und den <em>customer</em> Prozess so mit vier Semaphoren, dass die vorgegebenen Ablaufbedingungen eingehalten werden. Mit welchen Werten müssen die Semaphore initialisiert werden?
|
||||
Wir haben für sie vier Semaphore vorbereitet: Achtung, sie sind aber noch auskommentiert (siehe commonDefs.h und startApp.c. Die benötigten Semaphor-Funktionen aus der POSIX Bibliothek sind:</p></li>
|
||||
</ol>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">sem_wait</span><span class="p">(</span><span class="o">&</span><span class="n">semaphor</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>und</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">sem_post</span><span class="p">(</span><span class="o">&</span><span class="n">semaphor</span><span class="p">);</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Analysieren sie die Ausgabe der Prozesse (mehrmals starten). Was fällt auf?</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Gibt Ihr Programm den Output in der korrekten Reihenfolge aus? Falls nicht, wie könnte das gelöst werden?</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
</section>
|
||||
<section id="aufgabe-erweiterte-reihenfolge">
|
||||
<h3>4.3 Aufgabe: Erweiterte Reihenfolge<a class="headerlink" href="#aufgabe-erweiterte-reihenfolge" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Die Preise steigen dauernd … auch der Kaffee wird immer teurer, er kostet nun 3 Euro. Da der Automat nur 1 Euro Stücke annehmen kann, muss der Kunde 3 Münzen einwerfen. Erweitern sie die Prozesse aus Aufgabe 4.2 so, dass eine vordefinierte Anzahl Münzen eingegeben werden muss (die Anzahl Münzen ist in <em>commonDefs.h</em> als <em>NUM_COINS</em> definiert). Verwenden sie keine zusätzlichen Semaphore, sondern nutzen sie, dass wir Counting Semaphore verwenden. Die vordefinierten Prozesse finden sie im Verzeichnis <em>advancedSequence</em>.</p>
|
||||
<section id="aufgabe">
|
||||
<h4>Aufgabe<a class="headerlink" href="#aufgabe" title="Permalink to this headline">¶</a></h4>
|
||||
<ul class="simple">
|
||||
<li><p>Passen sie den coffeeTeller und den customer Prozess so an, dass der Kunde mehrere Münzen einwerfen muss, bis der Automat einen Kaffee ausgeben kann.</p></li>
|
||||
</ul>
|
||||
<p><strong>Hinweis:</strong> POSIX Semaphore sind Counting Semaphore, können aber nicht auf vordefinierte Werte gesetzt werden (ausser bei der Initialisierung). Abhilfe schafft hier das mehrmalige Aufrufen von <em>sem_post()</em>, z.B. in einer for-Schleife.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="zusammenfassung">
|
||||
<h3>4.4 Zusammenfassung<a class="headerlink" href="#zusammenfassung" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Wir haben drei grundlegenden Typen von Synchronisationsproblemen kennen gelernt:</p>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Mutex</strong> nur ein Prozess bzw. Thread kann gleichzeitig auf gemeinsame Daten zugreifen.</p>
|
||||
<ul>
|
||||
<li><p>Beispiel: entweder liest der Kaffee-Automat die Daten oder ein Kunde verändert sie.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><strong>Einfache Reihenfolge</strong> ein Prozess wartet auf die Freigabe durch einen anderen Prozess.</p>
|
||||
<ul>
|
||||
<li><p>Beispiel: der Kaffee-Automat wartet auf die Eingabe einer Münze.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p><strong>Erweiterte Reihenfolge</strong> ein Prozess wartet auf mehrere Freigaben durch einen anderen Pro-zess.</p>
|
||||
<ul>
|
||||
<li><p>Beispiel: der Kaffee-Automat wartet auf die Eingabe von drei Münzen.</p></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="international-banking">
|
||||
<h2>5. International Banking<a class="headerlink" href="#international-banking" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die International Bank of Transfer (IBT) besitzt in 128 Ländern Filialen und stellt für 2048 spezielle Handels-Kunden in jeder Filiale ein Konto zur Verfügung. Gelder dieser Kunden werden dauernd zwischen den Filialen hin und her transferiert, dazu beschäftigt die Bank sogenannte Pusher. Pusher heben Geldbeträge von Konten in einer Filiale ab und buchen sie auf den entsprechenden Konten in irgendeiner (auch in der eigenen) Filiale wieder ein. Die Beträge liegen zwischen 1000 und 100’000 Dollar und werden zufällig ausgewählt, die Wahl der beiden Filialen ist ebenfalls zufällig.</p>
|
||||
<section id="implementation">
|
||||
<h3>5.1 Implementation<a class="headerlink" href="#implementation" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Im Folgenden arbeiten wir mit einer <em>pthread</em>-basierten Implementation der IBT, die Pusher werden dabei mit Threads implementiert. Die Filialen der Bank sind als Array von Strukturen implementiert, wobei pro Filiale ein Lock (<em>branchLock</em>) und ein Array von Konten (Accounts) definiert ist. Die Konten sind wiederum Strukturen mit dem Kontostand (<em>account</em>) und dem Lock (<em>acntLock</em>), siehe dazu auch den Source Code. Die Zugriffe auf die Gelder sind imple-mentiert (Funktionen <em>withdraw()</em>, <em>deposit()</em>, <em>transfer()</em>), aber nicht synchronisiert.
|
||||
<strong>Hinweis:</strong> es ist von Vorteil hier mit mehreren CPUs zu arbeiten. Falls sie eine VM verwenden, setzen sie die Anzahl CPUs auf das Maximum.</p>
|
||||
</section>
|
||||
<section id="aufgabe-konto-synchronisation">
|
||||
<h3>5.2 Aufgabe: Konto Synchronisation<a class="headerlink" href="#aufgabe-konto-synchronisation" title="Permalink to this headline">¶</a></h3>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Wechseln sie ins Verzeichnis <strong>banking/a1</strong>, übersetzen sie das Programm und starten sie es mit dem Skript <code class="docutils literal notranslate"><span class="pre">./startApp</span></code>. Analysieren und erklären sie die Resultate. Notie-ren sie sich zudem die Laufzeiten für 1, 2 und 4 Threads.</p></li>
|
||||
<li><p>Synchronisieren sie die Kontenzugriffe so, dass möglichst viele Zugriffe gleichzeitig ausgeführt werden können und die Zugriffe atomar sind. Sie dürfen nur eines der beiden Locks <em>branchLock</em> bzw. <em>acntLock</em> verwenden: welches wählen sie und wieso? Be-gründen sie ihre Antwort und testen sie ihre Lösung.</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
<section id="aufgabe-filialen-zugriff-in-critical-section">
|
||||
<h3>5.3 Aufgabe: Filialen Zugriff in Critical Section<a class="headerlink" href="#aufgabe-filialen-zugriff-in-critical-section" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Ihr Chef meint, dass es wohl aus Sicherheitsgründen besser wäre, sowohl die Filialen und die jeweiligen Kontenzugriffen zu ”locken”.</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Wechseln sie ins Verzeichnis banking/a2 und kopieren sie banking.c aus Aufgabe 5.2. Implementieren sie diese zusätzlichen Anforderungen. Analysieren sie die Resultate. Was stellen sie fest im Vergleich mit den Resultaten aus der Aufgabe 5.2? Was raten sie ihrem Chef?</p></li>
|
||||
<li><p>Ein Kollege meint, es wäre effizienter beim Abheben des Betrags zuerst das Konto zu locken und dann die Filiale, hingegen beim Einbuchen zuerst die die Filiale und dann das Konto. Was für eine Antwort geben sie ihrem Kollegen?<strong>Hinweis:</strong> falls sie nicht sicher sind: probieren sie es aus.</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
<section id="aufgabe-refactoring-der-synchronisation">
|
||||
<h3>5.4 Aufgabe: Refactoring der Synchronisation<a class="headerlink" href="#aufgabe-refactoring-der-synchronisation" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Das International Banking Committe (IBC) erlässt neue Richtlinien, die unter anderem fordern, dass die Gesamtbilanz einer Bank über sämtliche Filialen zu jeder Zeit konsistent sein muss.</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Erklären sie wieso die Implementationen aus Aufgabe 5.2 und 5.3 diese Anforderungen nicht erfüllen.</p></li>
|
||||
<li><p>Ihr Entwicklungsteam kommt zum Schluss, dass den Pushern neu nur noch eine Funktion <em>transfer()</em> für die Überweisung von Beträgen zwischen den Filialen und Konten zur Verfügung gestellt werden darf.
|
||||
Welche Locks bzw. welches Lock muss verwendet werden, damit die Forderung des IBC erfüllt werden kann? Wechseln sie ins Verzeichnis <em>banking/a3</em> und ergänzen sie die Funktion <em>transfer()</em> in banking.c um die entsprechenden Lock-Funktionen.
|
||||
Wichtiger
|
||||
<strong>Hinweis:</strong> es darf kein neues Lock eingeführt werden und die Gesamtbilanz über sämtliche Filialen muss jederzeit konsistent sein.</p></li>
|
||||
<li><p>Testen und analysieren sie das Programm und vergleichen sie die Resultate (Funktionalität, Laufzeit) mit den Lösungen aus Aufgabe 5.2 und 5.3. Notieren sie sich, was ihnen bei dieser Aufgabe wichtig erscheint.</p></li>
|
||||
<li></li>
|
||||
</ol>
|
||||
</section>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>6. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Gewicht</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p></p></td>
|
||||
<td class="text-left"><p>Sie können die gestellten Fragen erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>4</p></td>
|
||||
<td class="text-left"><p>4.1 Aufgabe: Mutual Exclusion<br>4.2 Aufgabe: Einfache Reihenfolge<br>4.3 Aufgabe: Erweiterte Reihenfolge</p></td>
|
||||
<td class="text-left"><p>4</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td class="text-left"><p>5</p></td>
|
||||
<td class="text-left"><p>5.2 Aufgabe: Konto Synchronisation<br>5.3 Aufgabe: Filialen Zugriff in Critical Section<br>5.4 Aufgabe: Refactoring der Synchronisation</p></td>
|
||||
<td class="text-left"><p>4</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<hr class="docutils" />
|
||||
<p>Version: 18.08.2021</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">08 - Synchronisationsprobleme</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#nachweis">1.1 Nachweis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#einfuhrung">3. Einführung</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#wie-lost-man-synchronisationsprobleme">3.1 Wie löst man Synchronisationsprobleme?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#der-kaffee-automat">4. Der Kaffee-Automat</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-mutual-exclusion">4.1 Aufgabe: Mutual Exclusion</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#aufgaben">Aufgaben</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-einfache-reihenfolge">4.2 Aufgabe: Einfache Reihenfolge</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#id1">Aufgaben</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-erweiterte-reihenfolge">4.3 Aufgabe: Erweiterte Reihenfolge</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="#aufgabe">Aufgabe</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#zusammenfassung">4.4 Zusammenfassung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#international-banking">5. International Banking</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#implementation">5.1 Implementation</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-konto-synchronisation">5.2 Aufgabe: Konto Synchronisation</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-filialen-zugriff-in-critical-section">5.3 Aufgabe: Filialen Zugriff in Critical Section</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="#aufgabe-refactoring-der-synchronisation">5.4 Aufgabe: Refactoring der Synchronisation</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">6. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P07_Prozesse_und_Threads/README.html" title="previous chapter">07 - Prozesse und Threads</a></li>
|
||||
<li>Next: <a href="../P09_File_Operations/README.html" title="next chapter">09 - File Operations</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P08_Sync/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,168 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>09 - File Operations — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="10 - IPC" href="../P10_IPC/README.html" />
|
||||
<link rel="prev" title="08 - Synchronisationsprobleme" href="../P08_Sync/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="file-operations">
|
||||
<h1>09 - File Operations<a class="headerlink" href="#file-operations" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-1">
|
||||
<h2>3. Aufgabe 1:<a class="headerlink" href="#aufgabe-1" title="Permalink to this headline">¶</a></h2>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>4. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Punkte</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p></p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>1</p></td>
|
||||
<td class="text-left"><p>-</p></td>
|
||||
<td class="text-left"><p>-</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 16.02.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">09 - File Operations</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-1">3. Aufgabe 1:</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P08_Sync/README.html" title="previous chapter">08 - Synchronisationsprobleme</a></li>
|
||||
<li>Next: <a href="../P10_IPC/README.html" title="next chapter">10 - IPC</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P09_File_Operations/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,165 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>10 - IPC — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="prev" title="09 - File Operations" href="../P09_File_Operations/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section class="tex2jax_ignore mathjax_ignore" id="ipc">
|
||||
<h1>10 - IPC<a class="headerlink" href="#ipc" title="Permalink to this headline">¶</a></h1>
|
||||
<hr class="docutils" />
|
||||
<section id="ubersicht">
|
||||
<h2>1. Übersicht<a class="headerlink" href="#ubersicht" title="Permalink to this headline">¶</a></h2>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="lernziele">
|
||||
<h2>2. Lernziele<a class="headerlink" href="#lernziele" title="Permalink to this headline">¶</a></h2>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="aufgabe-1">
|
||||
<h2>3. Aufgabe 1:<a class="headerlink" href="#aufgabe-1" title="Permalink to this headline">¶</a></h2>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="bewertung">
|
||||
<h2>4. Bewertung<a class="headerlink" href="#bewertung" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.</p>
|
||||
<table class="colwidths-auto docutils align-default">
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="text-left head"><p>Aufgabe</p></th>
|
||||
<th class="text-left head"><p>Kriterium</p></th>
|
||||
<th class="text-left head"><p>Punkte</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td class="text-left"><p></p></td>
|
||||
<td class="text-left"><p>Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.</p></td>
|
||||
<td class="text-left"><p></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td class="text-left"><p>1</p></td>
|
||||
<td class="text-left"><p>-</p></td>
|
||||
<td class="text-left"><p>-</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr class="docutils" />
|
||||
<p>Version: 16.02.2022</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="../index.html">
|
||||
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">10 - IPC</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#aufgabe-1">3. Aufgabe 1:</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../P09_File_Operations/README.html" title="previous chapter">09 - File Operations</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="../_sources/P10_IPC/README.md.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
|
||||
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
|
||||
<svg fill-opacity="1" xmlns:xlink="http://www.w3.org/1999/xlink" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" width="430" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="160 290 430 250" height="250" xmlns="http://www.w3.org/2000/svg" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto"
|
||||
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
|
||||
/><g
|
||||
><defs id="defs1"
|
||||
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath1"
|
||||
><path d="M0 0 L2147483647 0 L2147483647 2147483647 L0 2147483647 L0 0 Z"
|
||||
/></clipPath
|
||||
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath2"
|
||||
><path d="M0 0 L0 40 L250 40 L250 0 Z"
|
||||
/></clipPath
|
||||
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath3"
|
||||
><path d="M0 0 L0 40 L210 40 L210 0 Z"
|
||||
/></clipPath
|
||||
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath4"
|
||||
><path d="M0 0 L0 50 L120 50 L120 0 Z"
|
||||
/></clipPath
|
||||
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath5"
|
||||
><path d="M0 0 L0 60 L30 60 L30 0 Z"
|
||||
/></clipPath
|
||||
></defs
|
||||
><g font-family="sans-serif" font-size="14px" transform="translate(320,480)"
|
||||
><text x="5" xml:space="preserve" y="17.9688" clip-path="url(#clipPath2)" stroke="none"
|
||||
>Das Main Programm kombiniert die</text
|
||||
><text x="5" xml:space="preserve" y="33.9375" clip-path="url(#clipPath2)" stroke="none"
|
||||
>Komponenten nach obigen Vorgaben</text
|
||||
><text x="5" xml:space="preserve" y="49.9062" clip-path="url(#clipPath2)" stroke="none"
|
||||
>und startet die Abarbeitung von Eingaben</text
|
||||
><text x="5" xml:space="preserve" y="65.875" clip-path="url(#clipPath2)" stroke="none"
|
||||
>über die View.</text
|
||||
></g
|
||||
><g font-family="sans-serif" font-size="14px" transform="translate(320,400)"
|
||||
><text x="5" xml:space="preserve" y="17.9688" clip-path="url(#clipPath3)" stroke="none"
|
||||
>Control kennt Model,</text
|
||||
><text x="5" xml:space="preserve" y="33.9375" clip-path="url(#clipPath3)" stroke="none"
|
||||
>Model aber nicht Control.</text
|
||||
></g
|
||||
><g font-family="sans-serif" font-size="14px" transform="translate(320,320)"
|
||||
><text x="5" xml:space="preserve" y="17.9688" clip-path="url(#clipPath3)" stroke="none"
|
||||
>View kennt Control,</text
|
||||
><text x="5" xml:space="preserve" y="33.9375" clip-path="url(#clipPath3)" stroke="none"
|
||||
>Control aber nicht View</text
|
||||
></g
|
||||
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(180,470)" stroke-opacity="0" stroke="rgb(255,255,255)"
|
||||
><rect x="0.5" width="118.5" height="48.5" y="0.5" clip-path="url(#clipPath4)" stroke="none"
|
||||
/></g
|
||||
><g transform="translate(180,470)"
|
||||
><rect fill="none" x="0.5" width="118.5" height="48.5" y="0.5" clip-path="url(#clipPath4)"
|
||||
/><text x="19" font-size="30px" y="32.7917" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
|
||||
>Model</text
|
||||
></g
|
||||
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(180,390)" stroke-opacity="0" stroke="rgb(255,255,255)"
|
||||
><rect x="0.5" width="118.5" height="48.5" y="0.5" clip-path="url(#clipPath4)" stroke="none"
|
||||
/></g
|
||||
><g transform="translate(180,390)"
|
||||
><rect fill="none" x="0.5" width="118.5" height="48.5" y="0.5" clip-path="url(#clipPath4)"
|
||||
/><text x="11" font-size="30px" y="32.7917" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
|
||||
>Control</text
|
||||
></g
|
||||
><g fill="rgb(255,255,255)" fill-opacity="0" transform="translate(180,310)" stroke-opacity="0" stroke="rgb(255,255,255)"
|
||||
><rect x="0.5" width="118.5" height="48.5" y="0.5" clip-path="url(#clipPath4)" stroke="none"
|
||||
/></g
|
||||
><g transform="translate(180,310)"
|
||||
><rect fill="none" x="0.5" width="118.5" height="48.5" y="0.5" clip-path="url(#clipPath4)"
|
||||
/><text x="27" font-size="30px" y="32.7917" clip-path="url(#clipPath4)" font-family="sans-serif" stroke="none" xml:space="preserve"
|
||||
>View</text
|
||||
></g
|
||||
><g transform="translate(230,350)"
|
||||
><path fill="none" d="M10.5 39.5 L10.5 10.5" clip-path="url(#clipPath5)"
|
||||
/><path fill="none" d="M17 28.7417 L10.5 40 L4 28.7417" clip-path="url(#clipPath5)"
|
||||
/></g
|
||||
><g transform="translate(230,430)"
|
||||
><path fill="none" d="M10.5 39.5 L10.5 10.5" clip-path="url(#clipPath5)"
|
||||
/><path fill="none" d="M17 28.7417 L10.5 40 L4 28.7417" clip-path="url(#clipPath5)"
|
||||
/></g
|
||||
></g
|
||||
></svg
|
||||
>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 829 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 392 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 54 KiB |
@@ -0,0 +1,84 @@
|
||||
# 01 - Erste Schritte mit C
|
||||
|
||||
___
|
||||
## 1. Übersicht
|
||||
|
||||
In diesem Praktikum erstellen Sie mehrere kleine C-Programme, in denen Sie Input- und Output-Funktionen der C Standard Library verwenden.
|
||||
|
||||
Arbeiten Sie in Zweiergruppen und diskutieren Sie ihre Lösungsansätze miteinander, bevor Sie diese umsetzen.
|
||||
|
||||
Bevor Sie mit den Programmieraufgaben beginnen, setzen Sie eine virtuelle Maschine mit der vorbereiteten Praktikumsumgebung auf.
|
||||
|
||||
___
|
||||
## 2. Lernziele
|
||||
In diesem Praktikum schreiben Sie selbst von Grund auf einige einfache C-Programme und wenden verschiedene Kontrollstrukturen an.
|
||||
|
||||
- Sie können mit *#include* Funktionen der C Standard Library einbinden
|
||||
- Sie können mit *#define* Macros definieren und diese anwenden
|
||||
- Sie wenden die *Input-* und *Output-Funktionen* von C an, um Tastatur-Input einzulesen und formatierte Ausgaben zu machen.
|
||||
- Sie verwenden die Kommandozeile, um ihren Sourcecode in ein ausführbares Programm umzuwandeln.
|
||||
- Sie wenden for-und while-Loops sowie if-then-else-Verzweigungen an.
|
||||
- Sie setzen eine Programmieraufgabe selbständig in ein funktionierendes Programm um.
|
||||
|
||||
___
|
||||
## 3. Aufgabe 1: virtuelle Maschine
|
||||
Im Moodle-Kurs "Systemnahe Programmierung" finden Sie unter "Praktika" eine Installationsanleitung für die virtuelle Maschine, die wir Ihnen zur Verfügung stellen. Die virtuelle Maschine enthält ein Ubuntu Linux-Betriebssystem und die für das Praktikum benötigten Frameworks.
|
||||
|
||||
Folgen sie der Anleitung, um die virtuelle Maschine auf ihrem Rechner zu installieren.
|
||||
|
||||
___
|
||||
## 4. Aufgabe 2: Hello World
|
||||
Schreiben Sie ein C-Programm, das "Hello World" auf die Standardausgabe schreibt. Verwenden Sie die printf-Funktion aus der Standard Library. In den Vorlesungsfolien finden Sie bei Bedarf eine Vorlage.
|
||||
|
||||
Erstellen sie das Source-File mit einem beliebigen Editor, sie benötigen nicht unbedingt eine IDE. Speichern Sie das Source-File mit der Endung `.c`.
|
||||
|
||||
Um ihr Source-File zu kompilieren, verwenden Sie den GNU Compiler auf der Kommandozeile:
|
||||
``` sh
|
||||
$> gcc hello.c
|
||||
```
|
||||
|
||||
Der Compiler übersetzt ihr Programm in eine ausführbare Datei `a.out`, die Sie mit
|
||||
|
||||
``` sh
|
||||
$> ./a.out
|
||||
```
|
||||
|
||||
ausführen können. Sie können den Namen der ausführbaren Datei wählen, indem Sie die Option `-o` verwenden:
|
||||
|
||||
``` sh
|
||||
$> gcc hello.c -o hello
|
||||
```
|
||||
|
||||
erzeugt die ausführbare Datei `hello`.
|
||||
|
||||
Verwenden Sie die Option `-Wall`, um alle Warnungen des Compilers auszugeben. Dies weist Sie auf allfällige Programmierfehler hin.
|
||||
|
||||
___
|
||||
## 5. Aufgabe 3: Tabellenausgabe
|
||||
Schreiben Sie ein Programm in C, das von `stdin` einen Umrechnungsfaktor zwischen CHF und Bitcoin einliest und danach eine Tabelle von Franken- und Bitcoin-Beträgen ausgibt. Die Tabelle soll sauber formatiert sein, z.B. so:
|
||||
```
|
||||
Enter conversion rate (1.00 BTC -> CHF): 43158.47
|
||||
200 CHF <--> 0.00463 BTC
|
||||
400 CHF <--> 0.00927 BTC
|
||||
600 CHF <--> 0.01390 BTC
|
||||
800 CHF <--> 0.01854 BTC
|
||||
1000 CHF <--> 0.02317 BTC
|
||||
1200 CHF <--> 0.02780 BTC
|
||||
1400 CHF <--> 0.03244 BTC
|
||||
1600 CHF <--> 0.03707 BTC
|
||||
```
|
||||
|
||||
- Verwenden Sie eine Schleife und die `printf`-Funktion für die Tabellenausgabe
|
||||
- Definieren Sie ein Makro `NUM_ROWS`, um an zentraler Stelle im Source-Code zu definieren, wie viele Einträge die Tabelle in der Ausgabe haben soll.
|
||||
- Lesen Sie den Umrechnungsfaktor mit der `scanf`-Funktion als `double` von der Kommandozeile ein.
|
||||
|
||||
___
|
||||
## 6. Aufgabe 4: Zeichen und Wörter zählen
|
||||
Schreiben Sie ein C-Programm, welches die Zeichen und Wörter einer mit der Tastatur eingegebenen Zeile zählt. Wortzwischenräume sind entweder Leerzeichen (' ') oder Tabulatoren ('\t'). Die Eingabe der Zeile mit einem newline-character ('\n') abgeschlossen. Danach soll ihr Programm die Anzahl Zeichen und die Anzahl Wörter ausgeben und terminieren.
|
||||
- Verwenden Sie die `char getchar(void)` Funktion aus der `stdio.h` Library, um die Zeichen einzeln einzulesen. Die Funktion `getchar` kehrt nicht gleich bei Eingabe des ersten Zeichens zurück, sondern puffert die Daten, bis die Eingabe einer kompletten Zeile mit Return abgeschlossen wird. Dann wird das erste Zeichen aus dem Puffer zurückgegeben und mit weiteren Aufrufen von getchar können die nachfolgenden Zeichen aus dem Puffer gelesen werden. Gibt `getchar` das Zeichen `\n` zurück, ist die Zeile komplett zurückgegeben und der Puffer ist wieder leer.
|
||||
- Setzen Sie eine Schleife ein, die beim Zeichen '\n' terminiert.
|
||||
- Benutzen Sie if-then-else-Strukturen um die Wörter zu zählen.
|
||||
|
||||
___
|
||||
## 7. Bewertung
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
@@ -0,0 +1,228 @@
|
||||
# 02: Funktionen, Datentyp "enum"
|
||||
|
||||
___
|
||||
|
||||

|
||||
|
||||
(Copyright Bild: xkcd.com)
|
||||
|
||||
___
|
||||
## 1. Übersicht
|
||||
In diesem Praktikum sind zwei Themen im Fokus: Funktionen und der Datentyp enum.
|
||||
|
||||
Funktionen sind der wesentlichste Bestandteil der C Programmierung welcher eine strukturierte Programmierung ermöglicht:
|
||||
* Eine Funktion ein Teil eines C Codes, der eine spezielle Aufgabe ausführt. Sie kann aus dem Hauptprogramm, oder aus anderen Funktionen, aufgerufen werden.
|
||||
* Jede Funktion besitzt einen eindeutigen Namen, eine eindeutige Signatur (Typen und Reihenfolge der Parameter) und einen Rückgabewert (int falls nichts angegeben wird).
|
||||
* Eine Funktion kann Werte aus dem aufrufendem Kontext übernehmen und bei Bedarf einen Wert an den aufrufenden Kontext zurückliefern.
|
||||
Beispiel einer Additions-Funktion:
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
/* Funktionsdeklaration */
|
||||
int add(int a, int b);
|
||||
|
||||
int main(void) {
|
||||
int aa = 1, bb = 2, cc;
|
||||
printf("%aa + %bb = %cc", aa, bb, add(aa, bb););
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Funktionsdefinition */
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
Der Daten typt enum wird verwendet um die Lesbarkeit von Programmen zu erhöhen:
|
||||
|
||||
Beispiel eines enum:
|
||||
```
|
||||
enum Ampeln = {rot =1, gelb, gruen};
|
||||
|
||||
int main(void) {
|
||||
Ampeln ampel1;
|
||||
if (ampel1 == rot) {...}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
___
|
||||
## 2. Lernziele
|
||||
|
||||
In diesem Praktikum lernen Sie Funktionen zu definieren und aufzurufen, sowie enum anzuwenden.
|
||||
* Sie können ein Programm schreiben welches aus mehreren Funktionen besteht.
|
||||
* Sie können Funktionen deklarieren, definieren und aufrufen.
|
||||
* Sie können enum Typen definieren und deren Werte bestimmen und abfragen.
|
||||
|
||||
___
|
||||
## 3. Aufgaben
|
||||
|
||||
```{eval-rst}
|
||||
.. figure:: kalender-108_v-ARDFotogalerie.jpg
|
||||
:width: 600px
|
||||
:name: kalender-108_v-ARDFotogalerie
|
||||
:align: center
|
||||
```
|
||||
|
||||
(Copyright Bild: www.planet-wissen.de)
|
||||
|
||||
### 3.1 Aufgabe 1 Tage pro Monat
|
||||
In der ersten Aufgabe berechnen Sie die Tag pro Monat einer beliebigen Kombination Monat / Jahr.
|
||||
Erweitern Sie dazu das Programm um folgende Aspekte:
|
||||
* Bereichsprüfung von Jahr und Monat
|
||||
* Funktion istSchaltjahr, welche berechnet, ob das Jahr eine Schaljahr ist
|
||||
* Funktion tageProMonat, welche die Anzahl Tage des gegebenen Monats und Jahres berechnet.
|
||||
|
||||
Vorgaben:
|
||||
* Die Funktion istSchaltjahr nimmt ein Integer (jahr) entgegen und gibt 1 im Falle eiens Schltjahres und 0 im andreren Fall zurück
|
||||
* Die Funktion tageProMonat nimmt zwei integer (monat und jahr) entgegeben und gibt die Anzahl Tage als Integer zurück
|
||||
* Die Jahreszahl, welche den Funktionen übergeben wird, muss überprüft werden und grösser gleich 1599 und kleiner als 10000 sein
|
||||
* Der übergebene Monat muss grösser als 0 und kleine als 13 sein.
|
||||
|
||||
Die Regeln für die Schaltjahrberechnung:
|
||||
* Schaltjahre sind alle Jahre, die durch 4 teilbar sind.
|
||||
* Eine Ausnahme bilden die Jahrhunderte (1600, 1700…). Diese sind keine Schltjahre.
|
||||
* zu den 100er gibt es ebenfalls Ausnahmen: Diese sind immer Schaltjahre, wenn sie durch 400 teilbar sind
|
||||
... also zum Beispiel 1600 ist eines, nicht jedoch 1700. Weiterführende Details finden Sie unter https://de.wikipedia.org/wiki/Gregorianischer_Kalender
|
||||
|
||||
Gegeben ist die main Funktion des Programms. Ergänzen Sie die enum Definition und die fehlenden Funktionen:
|
||||
* gibIntWert: Die Funktion soll einen Int Wert zurückgeben. Der Bereich, wie auch Fehleingaben sollen sollen berücksichtigt werden. (atoi unfd fgets sind hier hilfreich)
|
||||
* istSchaltjahr: Die Funktion gibt 1 im Falle eines Schltjahr und o im anderen Falle zurück.
|
||||
* tageProMonat: Die Funktion gibt den die Tage des Monats für das definierte Jahr zurück. Verwenden Sie die Switchanweisung , sowie den enum Datentypen
|
||||
|
||||
```
|
||||
int main (int argc, char *argv[]) {
|
||||
|
||||
int monat, jahr;
|
||||
|
||||
// Monat einlesen und Bereich ueberpruefen
|
||||
monat = gibIntWert("Monat", 1, 12);
|
||||
jahr = gibIntWert("Jahr", 1600, 9999);
|
||||
|
||||
// Ausgabe zum Test
|
||||
printf("Monat: %d, Jahr: %d \n", monat, jahr);
|
||||
|
||||
// Ausgabe zum Test (hier mit dem ternaeren Operator "?:")
|
||||
printf("%d ist %s Schaltjahr\n", jahr, istSchaltjahr(jahr) ? "ein" : "kein");
|
||||
|
||||
// Ausgabe
|
||||
printf("Der Monat %02d-%d hat %d Tage.\n", monat, jahr, tageProMonat(jahr, monat));
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Tipp: Angenommen Sie verwenden den enum month_t { JAN=1, FEB, MAR, APR, MAI, JUN, JUL, AUG, SEP, OKT, NOV, DEZ };
|
||||
Dann können Sie im Programm direkt die Konstanten verwenden:
|
||||
```
|
||||
if (m == 2) ... // schlecht lesbar
|
||||
if (monat == 2) ... // besserer Variablenname
|
||||
if (monat == FEB) ... // am besten lesbar
|
||||
```
|
||||
|
||||
|
||||
Als Abnahme müssen die Tests unverändert ohne Fehler ausgeführt werden (`make test`)
|
||||
___
|
||||
### 3.2 Aufgabe 2 Bestimmen des Wochentags
|
||||
Erweitern Sie das vorgegebene zweite Programm Gerüst an den bezeichneten Stellen so, dass das Programm von der Kommando Zeile ein Argument entgegennimmt, es auf Gültigkeit überprüft und schliesslich den Wochentag für das gegebene Datum berechnet und ausgibt.
|
||||
Prüfen Sie die Umsetzung beider Teilaufgaben mittels make test.
|
||||
#### 3.2.1 Teilaufgabe Argumente Parsen und auf Korrektheit prüfen
|
||||
Das Argument stellt ein gültiges Datum unseres Gregorianischen Kalenders dar (d.h. ein Datum ab Donnerstag, den 15. Oktober 1582, mit der Gregorianischen Schaltjahr Regel).
|
||||
Wenn kein Argument gegeben ist oder wenn das eingegebene Datum nicht gültig ist, soll das Programm einem Hilfetext auf stderr ausgeben und mit EXIT_FAILURE Exit Code terminieren. Wenn ein gültiges Datum erkannt wurde terminiert das Programm mit Exit Code EXIT_SUCCESS.
|
||||
##### 3.2.1.1 Argument Format
|
||||
Das Format des Kommando Zeilen Arguments soll yyyy-mm-dd sein, wobei yyyy für das vier-stellige Jahr, mm für einen 1-2-stelligen Monat (1…12) und dd für einen Tag des Monats, begin-nend mit 01. Z.B. 2020-02-29.
|
||||
##### 3.2.1.2 Korrektes Datum
|
||||
Das Datum muss alle folgenden Bedingungen erfüllen damit es als korrekt erkannt wird:
|
||||
* Obergrenze für ein «sinnvolles» Datum ist das Jahr 9999
|
||||
* es muss Gregorianisch sein, d.h. ab 15. Oktober 1582 (inklusive)
|
||||
* es darf nur Monate von 1 für Januar bis 12 für Dezember beinhalten
|
||||
* der Tag muss grösser oder gleich 1 sein
|
||||
* der Tag darf nicht grösser als 31 sein für Monate mit einer Länge von 31 Tagen
|
||||
* der Tag darf nicht grösser als 30 sein für Monate mit einer Länge von 30 Tagen
|
||||
* der Tag darf für den Februar nicht grösser sein als 29 für ein Schaltjahr
|
||||
* der Tag darf für den Februar nicht grösser sein als 28 für ein Nicht-Schaltjahr
|
||||
|
||||
##### 3.2.1.3 Vorgaben an die Umsetzung
|
||||
1. Definieren Sie einen enum Typen mit (typedef) Namen month_t dessen Werte die Englischen 3-Zeichen Abkürzungen der Monate sind, nämlich Jan, Feb, … Dec und stellen Sie sicher dass die Abkürzungen für die uns geläufigen Monatsnummer stehen.
|
||||
2. Definierend Sie einen struct Typen mit (typedef) Namen date_t und den int Elementen year, month, day. Lesen Sie das Argument (falls vorhanden) via sscanf und dem Formatstring "%d-%d-%d" in die drei Elemente einer Date Variable. Siehe dazu die Hinweise im Anhang.
|
||||
3. Für die Berechnung der Monatslänge implementieren Sie die Hilfsfunktion is_leap_year(date_t date) (nach obigen Vorgaben). Der Return Wert 0 bedeutet «Kein Schaltjahr», 1 bedeutet «Schaltjahr».
|
||||
4. Implementieren Sie die Funktion `int get_month_length(date_t date)`. Diese soll für den Monat des Datums die Monatslänge (was dem letzten Tag des Monats ent-spricht) ausgeben – geben Sie 0 für ungültige Monatswerte zurück.
|
||||
5. Schliesslich implementieren Sie die Funktion int is_gregorian_date(date_t date) welche prüft, ob ein gegebenes Datum im Bereich 15. Oktober 1582 und dem Jahr 9999 ist (0 = nein, 1 = ja).
|
||||
6. Implementieren Sie eine Funktion int is_valid_date(date_t date), welche obige Bedingungen für ein gültiges Datum umsetzt. Der Return Wert 0 bedeutet «Kein gültiges Datum», 1 bedeutet «Gültiges Datum». Benutzen Sie für die Prüfung des Datums die `month_t` Werte wo immer möglich und sinnvoll. Verwenden Sie die oben implemen-tierten Hilfsfunktionen.
|
||||
##### 3.2.1.4 Hinweise
|
||||
Beachten Sie die Kommentare im Code für die geforderten Implementierungs-Details.
|
||||
#### 3.2.2 Teilaufgabe Wochentag Berechnung
|
||||
Schreiben Sie eine Funktion welche zu einem Datum den Wochentag berechnet.
|
||||
Die Formel wird Georg Glaeser zugeschrieben, möglicherweise angelehnt an eine Formel von Carl Friedrich Gauss.
|
||||
|
||||
```{eval-rst}
|
||||
.. figure:: Wochentagsberechnung.jpg
|
||||
:width: 600px
|
||||
:name: Wochentagsberechnung
|
||||
:align: center
|
||||
```
|
||||
(Quelle: https://de.wikipedia.org/wiki/Wochentagsberechnung)
|
||||
|
||||
Hier ist eine für C abgewandelte Variante davon.
|
||||
```
|
||||
weekday = ((day + (13 * m - 1) / 5 + y + y / 4 + c / 4 - 2 * c) % 7 + 7) % 7
|
||||
alle Zahlen sind int Werte und alles basiert auf int-Arithmetik
|
||||
m = 1 + (month + 9) % 12
|
||||
a = year - 1 (für month < Mar), ansonsten year
|
||||
y = a % 100
|
||||
c = a / 100
|
||||
```
|
||||
Erweitern sie das Programm so, dass vor dem erfolgreichen Terminieren des Programms fol-gende Zeile (inklusive Zeilenumbruch) ausgegeben wird: yyyy-mm-dd is a Ddd, wobei yyyy für das Jahr, mm für die Nummer des Monats (01…12) und dd für den Tag im Monat (01…). Z.B. 2020-02-29 is a Sat.
|
||||
Vorgaben an die Umsetzung
|
||||
1. Definieren Sie einen enum Typen mit (typedef) Namen weekday_t dessen Werte die Englischen 3-Zeichen Abkürzungen der Tage sind, nämlich Sun, Mon, … Sat und stel-len Sie sicher dass die Abkürzungen für die Werte 0…6 stehen.
|
||||
2. Schreiben Sie eine Funktion weekday_t calculate_weekday(date_t date) nach der Beschreibung der obigen Formel. Das date Argument ist als gültig angenom-men, d.h. es ist ein Programmier-Fehler, wenn das Programm diese Funktion mit einem ungültigen Datum aufruft. Machen Sie dafür als erste Codezeile in der Funktion eine Zu-sicherung (assert(is_valid_date(date));)
|
||||
3. Schreiben Sie eine Funktion void print_weekday(weekday_t day), welche für jeden gülteigen Tag eine Zeile auf stdout schreibt mit den Englischen 3-Zeichen Ab-kürzungen für den Wochentag, z.B. Sonntag: Sun, Montag: Mon, etc. Wenn ein ungülti-ger Wert für day erkannt wird, soll assert(!"day is out-of-range"); aufgeru-fen werden.
|
||||
Hinweise
|
||||
• Für interessierte, siehe: https://de.wikipedia.org/wiki/Wochentagsberechnung
|
||||
|
||||
|
||||
___
|
||||
## 4. Bewertung
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden können.
|
||||
| Aufgabe | Kriterium | Gewicht |
|
||||
| :-- | :-- | :-- |
|
||||
| alle | Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären. | |
|
||||
| gibIntWert | Eingabe, Bereichsüberprüfung korrekt | 1 |
|
||||
| istSchaltjahr | Funktion korrekt | 1 |
|
||||
| TageProMonat | Funktion korrekt | 1 |
|
||||
| Aufgabe 2 | Fehlenden Teile ergänzt und lauffähig | 1 |
|
||||
___
|
||||
## 5. Anhang
|
||||
|
||||
### 5.1 Sprach Element
|
||||
|
||||
```int main(int argc, char *argv[]) {
|
||||
...
|
||||
} argc: Anzahl Einträge in argv.
|
||||
argv: Array von Command Line Argumenten.
|
||||
argv[0]: wie das Programm gestartet wurde
|
||||
argv[1]: erstes Argument
|
||||
…
|
||||
argv[argc-1]: letztes Argument
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
int res = sscanf(argv[1]
|
||||
, "%d-%d-%d"
|
||||
, &a, &b, &c
|
||||
);
|
||||
if (res != 3) {
|
||||
// Fehler Behandlung...
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Beschreibung
|
||||
Siehe man 3 sscanf.
|
||||
Die Funktion sscanf gibt die Anzahl erfolgreich erkannte Argumente zurück. Unbedingt prüfen und angemessen darauf reagieren.
|
||||
Die gelesenen Werte werden in a, b und c, gespeichert, dazu müssen Sie die Adresse der Variablen übergeben. Mehr Details dazu werden später erklärt.
|
||||
fprintf(stderr, "Usage: %s…\n", argv[0]); Siehe man 3 fprintf.
|
||||
Schreibt formatierten Text auf den stderr Stream.
|
||||
|
||||
___
|
||||
Version: 15.02.2022
|
||||
@@ -0,0 +1,125 @@
|
||||
|
||||
# Lösungsskizzen
|
||||
## Aufgabe 1
|
||||
```
|
||||
/**
|
||||
* Tage Pro Monat
|
||||
*
|
||||
* Das Programm liest einen Monat (1-12) und ein Jahr (1600-2400) ein und
|
||||
* gibt die Anzahl der Tage dieses Monats aus.
|
||||
*
|
||||
* @author Gerrit Burkert, Adaptation bazz
|
||||
* @version 15-FEB-2013, 16-OCT-2017, 17-OCT-2019, 16-FEB-2022
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ERROR_IN_MONTH 1
|
||||
#define ERROR_IN_YEAR 2
|
||||
|
||||
///// Student Code
|
||||
|
||||
|
||||
|
||||
// Konstante Werte fuer die Monate
|
||||
// ===============================
|
||||
|
||||
enum { JAN=1, FEB, MAR, APR, MAI, JUN, JUL, AUG, SEP, OKT, NOV, DEZ };
|
||||
|
||||
|
||||
// Eingabe pruefen (0 ist vom atoi als Fehelcode verwendet und darf nicht verwendet werden)
|
||||
// ===============
|
||||
|
||||
int gibIntWert(char *name, int von, int bis) {
|
||||
|
||||
int wert;
|
||||
char wertS[20]; //
|
||||
|
||||
do {
|
||||
printf("%s: ", name);
|
||||
fgets(wertS, 20, stdin);
|
||||
wert = atoi(wertS);
|
||||
if (wert < von || wert > bis) {
|
||||
printf("Der Wert muss zwischen %d und %d sein.\n", von, bis);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
return wert;
|
||||
}
|
||||
|
||||
|
||||
// Schaltjahr bestimmen
|
||||
// ====================
|
||||
|
||||
int istSchaltjahr(int jahr){
|
||||
|
||||
if ( (jahr % 400 == 0) || ( (jahr %100 != 0) && (jahr % 4 ==0) ) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Berechnung Anzahl Tage pro Monat
|
||||
// ================================
|
||||
|
||||
int tageProMonat(int jahr, int monat) {
|
||||
|
||||
int anzTage;
|
||||
|
||||
// Tage pro Monat bestimmen
|
||||
switch (monat) {
|
||||
|
||||
// Monate mit 31 Tagen
|
||||
case JAN: case MAR: case MAI: case JUL: case AUG: case OKT: case DEZ:
|
||||
anzTage = 31;
|
||||
break;
|
||||
|
||||
// Monate mit 30 Tagen
|
||||
case APR: case JUN: case SEP: case NOV:
|
||||
anzTage = 30;
|
||||
break;
|
||||
|
||||
// Februar: 28 oder 29 Tage
|
||||
case FEB:
|
||||
|
||||
if (istSchaltjahr(jahr)) {
|
||||
anzTage = 29;
|
||||
} else {
|
||||
anzTage = 28;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return anzTage;
|
||||
}
|
||||
|
||||
///// END Student Code
|
||||
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
|
||||
int monat, jahr;
|
||||
|
||||
// Monat einlesen und Bereich ueberpruefen
|
||||
monat = gibIntWert("Monat", 1, 12);
|
||||
jahr = gibIntWert("Jahr", 1600, 9999);
|
||||
|
||||
// Ausgabe zum Test
|
||||
printf("Monat: %d, Jahr: %d \n", monat, jahr);
|
||||
|
||||
// Ausgabe zum Test (hier mit dem ternaeren Operator "?:")
|
||||
printf("%d ist %s Schaltjahr\n", jahr, istSchaltjahr(jahr) ? "ein" : "kein");
|
||||
|
||||
// Ausgabe
|
||||
printf("Der Monat %02d-%d hat %d Tage.\n", monat, jahr, tageProMonat(jahr, monat));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
## Aufgabe 2
|
||||
Alter bestehender Boilerplate Code
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
# 03 - Bit Operationen, Struct, Typedef
|
||||
|
||||
|
||||
## 1. Bit Operationen
|
||||
|
||||

|
||||
|
||||
|
||||
Bit Operationen sind allgegenwärtig in den Computer-Wissenschaften und finden in vielen Disziplinen Anwendung. Folgend ein kleiner Auszug aus den wichtigsten Themen:
|
||||
- **Bit Felder**: Sind die effizienteste Art, etwas darzustellen, dessen Zustand durch mehrere "wahr" oder "falsch" definiert werden kann. Besonders auf Systemen mit begrenzten Ressourcen sollte jede überflüssige Speicher-Allozierung vermieden werden.
|
||||
|
||||
Beispiel:
|
||||
```c
|
||||
// primary colors
|
||||
#define BLUE 0b100
|
||||
#define GREEN 0b010
|
||||
#define RED 0b001
|
||||
|
||||
// mixed colors
|
||||
#define BLACK 0 /* 000 */
|
||||
#define YELLOW (RED | GREEN) /* 011 */
|
||||
#define MAGENTA (RED | BLUE) /* 101 */
|
||||
#define CYAN (GREEN | BLUE) /* 110 */
|
||||
#define WHITE (RED | GREEN | BLUE) /* 111 */
|
||||
```
|
||||
[https://de.wikipedia.org/wiki/Bitfeld](https://de.wikipedia.org/wiki/Bitfeld)
|
||||
|
||||
- **Kommunikation**:
|
||||
- **Prüfsummen/Paritätsbit**: Übertragungsfehler und Integrität können bis zu einem definiertem Grad erkannt werden. Je nach Komplexität der Berechnung können mehrere Fehler erkannt oder auch korrigiert werden.
|
||||
[https://de.wikipedia.org/wiki/Parit%C3%A4tsbit](https://de.wikipedia.org/wiki/Parit%C3%A4tsbit), [https://de.wikipedia.org/wiki/Pr%C3%BCfsumme](https://de.wikipedia.org/wiki/Pr%C3%BCfsumme)
|
||||
- **Stoppbit**: Markieren bei asynchronen seriellen Datenübertragungen das Ende bzw. Start eines definierten Blocks.
|
||||
[https://de.wikipedia.org/wiki/Stoppbit](https://de.wikipedia.org/wiki/Stoppbit)
|
||||
- **Datenflusssteuerung**: Unterschiedliche Verfahren, mit denen die Datenübertragung von Endgeräten an einem Datennetz, die nicht synchron arbeiten, so gesteuert wird, dass eine möglichst kontinuierliche Datenübermittlung ohne Verluste erfolgen kann.
|
||||
[https://de.wikipedia.org/wiki/Datenflusssteuerung](https://de.wikipedia.org/wiki/Datenflusssteuerung)
|
||||
- ...
|
||||
|
||||
- **Datenkompression**: Bei der Datenkompression wird versucht, redundante Informationen zu entfernen. Dazu werden die Daten in eine Darstellung überführt, mit der sich alle – oder zumindest die meisten – Information in kürzerer Form darstellen lassen.
|
||||
[https://de.wikipedia.org/wiki/Datenkompression](https://de.wikipedia.org/wiki/Datenkompression)
|
||||
- **Kryptographie**: Konzeption, Definition und Konstruktion von Informationssystemen, die widerstandsfähig gegen Manipulation und unbefugtes Lesen sind. [https://de.wikipedia.org/wiki/Verschl%C3%BCsselung](https://de.wikipedia.org/wiki/Verschl%C3%BCsselung)
|
||||
- **Grafik-Programmierung**: XOR (oder ^) ist hier besonders interessant, weil eine zweite Eingabe derselben Eingabe die erste rückgängig macht (ein Beispiel dazu weiter unten: "Variablen tauschen, ohne Dritt-Variable
|
||||
"). Ältere GUIs verwendeten dies für die Hervorhebung von Auswahlen und andere Überlagerungen, um kostspielige Neuzeichnungen zu vermeiden. Sie sind immer noch nützlich in langsamen Grafikprotokollen (z. B. Remote-Desktop).
|
||||
|
||||
### 1.1 Übungen
|
||||
|
||||
#### 1. Basis Operationen
|
||||
Manipulationen von einzelnen Bits gehören zu den Basis Operationen und dienen als Grundlagen um weitere komplexere Konstrukte zu schaffen. Verfollständigen sie folgendes Beispiel mit den drei Basis Operationen:
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
unsigned int number;
|
||||
unsigned int bit = 3; // bit at position 3
|
||||
|
||||
// Setting a bit
|
||||
number = ...; // solution: number |= 1 << bit;
|
||||
|
||||
// Clearing a bit
|
||||
number = ...; // solution: number &= ~(1 << bit);
|
||||
|
||||
// Toggling a bit
|
||||
number = ...; // solution; number ^= 1 << bit;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Variablen tauschen (ohne Dritt-Variable)
|
||||
Zwei Variablen zu vertauschen scheint ein einfach lösbares Problem zu sein. Eine offensichtliche Variante wäre mittels einer temporären Variablen:
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(){
|
||||
int a = 3;
|
||||
int b = 4;
|
||||
printf("a: %d; b: %d\n", a, b);
|
||||
|
||||
int temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
|
||||
printf("a: %d; b: %d\n", a, b);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
Es gibt aber auch eine Variante, die ohne zusätzliche Variable auskommt. Dabei wird die Tatsache, dass eine zweite XOR Operation eine erste XOR Operation rückgängig macht:
|
||||
|
||||
*0011 XOR 0100 = 0111*
|
||||
|
||||
*0111 XOR 0100 = 0011*
|
||||
|
||||
Somit kommt man von einem XOR Resultat (*0111*) wieder auf beide Anfangs Operanden zurück indem man einfach ein zweites Mal mit einem Operanden eine XOR Verknüpfung macht. Damit kann ein Operand als Zwischenspeicher dienen und man muss nicht extra eine Zusatzvariable verwenden.
|
||||
|
||||
Überlegen sie sich wie sie damit zwei Variablen vertauschen können ohne Zusatzvariable:
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(){
|
||||
int a = 3;
|
||||
int b = 4;
|
||||
printf("a: %d; b: %d\n", a, b);
|
||||
|
||||
|
||||
...
|
||||
|
||||
/* Solutions:
|
||||
// a == 0011; b == 0100
|
||||
a ^= b; // a == 0111; b == 0100
|
||||
b ^= a; // a == 0111; b == 0011
|
||||
a ^= b; // a == 0100; b == 0011
|
||||
*/
|
||||
|
||||
printf("a: %d; b: %d\n", a, b);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Lower- / Uppercase
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(){
|
||||
char word[8] = "sREedEv";
|
||||
char *wordptr = &word[0];
|
||||
|
||||
while(wordptr < &word[7]) {
|
||||
printf("UPPERCASE: %c\n", *wordptr & '_'); // converts the char into uppercase regardless of the current casing
|
||||
printf("LOWERCASE: %c\n", *wordptr | ' '); // converts the char into lowercase regardless of the current casing
|
||||
wordptr++;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Prüfen auf 2-er Potenz
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(){
|
||||
int a=32;
|
||||
if(a > 0 && (a & (a - 1)) == 0){
|
||||
printf("%d is a power of 2", a);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
___
|
||||
## 2. Struct & typedef
|
||||
|
||||
### 2.1 Übungen
|
||||
|
||||
#### 1. Bit Operationen Rechner
|
||||
- Bitweise Operationen mit 2 Operanden
|
||||
- Rechnung wird als ein String über scanf dem Programm übergeben
|
||||
- String wird in Token zerstückelt und in struct gespeichert:
|
||||
```c
|
||||
typedef struct {
|
||||
unsigned int operand_1;
|
||||
unsigned int operand_2;
|
||||
char operation;
|
||||
} Expression;
|
||||
```
|
||||
- Ausgabe in 3 verschiedenen Formaten:
|
||||
```
|
||||
Bin:
|
||||
0000'0000'0000'0001
|
||||
& 0000'0000'0000'0011
|
||||
-------------------
|
||||
0000'0000'0000'0001
|
||||
|
||||
Hex
|
||||
0x01 & 0x03 = 0x01
|
||||
|
||||
Dec
|
||||
1 & 3 = 1
|
||||
```
|
||||
|
||||
___
|
||||
## 4. Bewertung
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden können.
|
||||
| Aufgabe | Kriterium | Gewicht |
|
||||
| :-- | :-- | :-- |
|
||||
| alle | Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären. | |
|
||||
| gibIntWert | Eingabe, Bereichsüberprüfung korrekt | 1 |
|
||||
| istSchaltjahr | Funktion korrekt | 1 |
|
||||
| TageProMonat | Funktion korrekt | 1 |
|
||||
| Aufgabe 2 | Fehlenden Teile ergänzt und lauffähig | 1 |
|
||||
@@ -0,0 +1,532 @@
|
||||
# 04 - Modularisieren von C Code
|
||||
|
||||
```{eval-rst}
|
||||
.. figure:: zhaw_neg_P2945.jpg
|
||||
:width: 100px
|
||||
:name: logo
|
||||
:align: right
|
||||
```
|
||||
|
||||
___
|
||||
|
||||
```{eval-rst}
|
||||
.. figure:: modularisieren_von_c_code.JPG
|
||||
:width: 500px
|
||||
:name: logo
|
||||
:align: center
|
||||
```
|
||||
|
||||
|
||||
___
|
||||
|
||||
## Inhalt
|
||||
|
||||
{ref}`04_introduction`
|
||||
|
||||
{ref}`04_learning_objectives`
|
||||
|
||||
{ref}`04_task_01`
|
||||
|
||||
{ref}`04_task_02`
|
||||
|
||||
{ref}`04_grading`
|
||||
|
||||
{ref}`04_appendix`
|
||||
|
||||
___
|
||||
|
||||
(04_introduction)=
|
||||
## 1. Übersicht
|
||||
|
||||
In diesem Praktikum üben Sie modulare Programmierung indem Sie ein
|
||||
Java Programm (bestehend aus drei Java Files) in ein entsprechendes C
|
||||
Programm aus drei Modulen (aus je einem Header- und Implementations-
|
||||
File) übersetzen. Sie passen das Makefile so an, dass die
|
||||
entsprechenden Module mit kompiliert werden.
|
||||
|
||||
In der zweiten Aufgabe erstellen Sie Makefile Regeln für die drei
|
||||
Schritte von den C Source Files zur graphischen Darstellung der
|
||||
Abhängigkeiten.
|
||||
|
||||
```{eval-rst}
|
||||
.. figure:: uebersicht.png
|
||||
:width: 500px
|
||||
:name: uebersicht
|
||||
:align: center
|
||||
```
|
||||
|
||||
|
||||
Im Anhang ist eine Übersicht über die verwendeten File Formate gegeben.
|
||||
|
||||
|
||||
(04_learning_objectives)=
|
||||
## 2. Lernziele
|
||||
|
||||
In diesem Praktikum lernen Sie die Handgriffe um ein Programm zu modularisieren, d.h. in mehrere Module aufzuteilen.
|
||||
|
||||
* Sie wissen, dass ein Modul aus einem C-File und einem passenden
|
||||
H-File besteht.
|
||||
* Sie können Header Files korrekt strukturieren.
|
||||
* Sie deklarieren im Header-File die öffentlichen Typen und Funktionen
|
||||
eines Moduls.
|
||||
* Sie wissen wie **Include Guards** anzuwenden sind.
|
||||
* Sie können Module im `Makefile` zur Kompilation hinzufügen.
|
||||
* Sie können `Makefile` Regeln schreiben.
|
||||
|
||||
Die Bewertung dieses Praktikums ist am Ende angegeben.
|
||||
|
||||
Erweitern Sie die vorgegebenen Code Gerüste, welche im `git`
|
||||
Repository `snp-lab-code` verfügbar sind.
|
||||
|
||||
|
||||
(04_task_01)=
|
||||
## 3. Aufgabe 1: Modularisieren
|
||||
Das zu ergänzende Programm dep2dot hat folgende Funktionalität:
|
||||
|
||||
Ergänzen Sie in **`modularize/src`** den Code in **`triangle.c`**,
|
||||
**`read.h`**, **`read.c`**, **`rectang.h`** und **`rectang.c`** so
|
||||
dass die Tests erfolgreich durchlaufen. Die C Implementation soll
|
||||
dieselbe Funktionalität haben wie die gegebenen Java Files. Lehnen Sie
|
||||
sich so nahe wie möglich an die Java Files an.
|
||||
|
||||
1. In den Header-Files implementieren Sie den Include-Guard und
|
||||
deklarieren Sie die öffentlichen Funktionen und gegebenenfalls
|
||||
**`#define`**.
|
||||
2. In den Implementations-Files implementieren Sie die Funktionen.
|
||||
|
||||
Die drei Java Files liegen in **`modularize/java`**.
|
||||
|
||||
### Tipps
|
||||
|
||||
* Implementieren Sie die Symbole welche vollständig in Grossbuchstaben
|
||||
geschrieben sind als **`#define`**.
|
||||
* **`EOF`** kommt schon aus **`stdio.h`** und sollte deshalb nicht
|
||||
mehr definiert werden.
|
||||
* Jene **`#define`** welche von andern Modulen verwendet werden
|
||||
kommen ins Header-File, die andern ins Implementations-File.
|
||||
* Ein Grossteil des Java Codes aus den Methoden Bodies kann
|
||||
eins-zu-eins in C übernommen werden. Listen Sie auf welche
|
||||
Unterschiede es gibt:
|
||||
|
||||
<table>
|
||||
<style>
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th:first-of-type {
|
||||
width: 50%;
|
||||
}
|
||||
table th:nth-of-type(2) {
|
||||
width: 50%;
|
||||
}
|
||||
</style>
|
||||
<tr><th>Java</th><th>C</th></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
byte
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
boolean
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
|
||||
```Java
|
||||
true
|
||||
```
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
false
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
System.out.print(…)
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
System.out.println(…)
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
System.in.read()
|
||||
```
|
||||
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
byte[] buffer = new byte[BUFFERSIZE];
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
public class rectang {
|
||||
public boolean Rectangular(…)
|
||||
{ … }
|
||||
}
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
public class read {
|
||||
public int getInt(...)
|
||||
throws java.io.IOException
|
||||
{ ... }
|
||||
}
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
class triangle {
|
||||
public static void main(String[] args)
|
||||
throws java.io.IOException
|
||||
{ ... }
|
||||
}
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
read ReadInt = new read();
|
||||
...
|
||||
word = ReadInt.getInt(MAX_NUMBER);
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```Java
|
||||
rectang Rect = new rectang();
|
||||
...
|
||||
if (Rect.Rectangular(a, b, c) == true) { ... }
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
<tr><td>
|
||||
|
||||
```
|
||||
System.out.println(
|
||||
"-> Dreieck " + a + "-" + b + "-" + c
|
||||
+ " ist rechtwinklig");
|
||||
```
|
||||
|
||||
</td><td></td></tr>
|
||||
</table>
|
||||
|
||||
(04_task_02)=
|
||||
## 4. Aufgabe 2: Makefile Regeln
|
||||
|
||||
Die folgenden drei Schritte erstellen von einem C Source File eine
|
||||
graphische Darstellung der Abhängigkeiten:
|
||||
|
||||
1. `gcc ... -H .. file.c ... 2> file.dep` (Regeln im Makefile bereits vorhanden)
|
||||
2. `dep2dot file.c <file.dep >file.dot` (in dieser Aufgabe zu erstellen)
|
||||
3. `dot -Tpng file.dot >file.png` (in dieser Aufgabe zu erstellen)
|
||||
|
||||
Sie sollen für die Compiler-ähnlichen Programme `dep2dot` und `dot`
|
||||
Makefile Regeln schreiben.
|
||||
|
||||
```{eval-rst}
|
||||
.. figure:: uebersicht.png
|
||||
:width: 500px
|
||||
:name: uebersicht
|
||||
:align: center
|
||||
```
|
||||
|
||||
|
||||
Das Programm `dep2dot` hat folgende Funktionalität:
|
||||
|
||||
|
||||
1. Es liest von `stdin` die vom Compiler generierten
|
||||
Abhängigkeits-Daten in Form des `dep` Formates ein.
|
||||
2. Das erste und einzige Command Line Argument gibt das File an für
|
||||
welches die von `stdin` gelesenen Abhängigkeiten gelten.
|
||||
3. Auf `stdout` werden die Abhängigkeiten von `stdin` übersetzt als
|
||||
`dot`-File Format ausgegeben.
|
||||
|
||||
Das Programm `dot` hat folgende Funktionalität:
|
||||
1. Es liest die textuelle Beschreibung eines Graphen aus der
|
||||
übergebenen Datei (erstes Argument) ein.
|
||||
2. Auf `stdout` wird die grafische Darstellung der Beschreibung der
|
||||
Eingabe-Datei im `png`-File Format ausgegeben.
|
||||
|
||||
Das `dep`-Format und das `dot`-Format sind im Anhang beschrieben.
|
||||
|
||||
Sie können die Funktionalität des Programms `dep2dot` kennen lernen,
|
||||
indem Sie folgende Zeilen auf der Bash Shell ausführen. Das
|
||||
`dep.input` File ist Teil der automatisierten Test Suite im
|
||||
Verzeichnis `tests`:
|
||||
|
||||
|
||||
```bash
|
||||
bin/dep2dot dir/file <tests/dep.input >dep.dot
|
||||
dot -Tpng dep.dot >dep.png
|
||||
firefox dep.png
|
||||
```
|
||||
|
||||
Als Resultat sollte Firefox folgende Graphik darstellen:
|
||||
|
||||
|
||||
```{eval-rst}
|
||||
.. figure:: dep_dot.png
|
||||
:width: 150px
|
||||
:name: dep_dot
|
||||
:align: center
|
||||
```
|
||||
|
||||
|
||||
|
||||
Definieren Sie im `Makefile` Regeln, welche die einzelnen Schritte von
|
||||
den Source Files zu den `png` Files ausführen.
|
||||
|
||||
|
||||
Prüfen Sie schliesslich die Umsetzung Aufgabe mittels `make dep-clean
|
||||
dep && firefox src/*.png.`
|
||||
|
||||
|
||||
### 4.1 Neue Regeln hinzufügen
|
||||
|
||||
|
||||
Führen Sie im `Makefile` an den angegebenen Stellen folgende
|
||||
Ergänzungen durch
|
||||
|
||||
* definieren Sie eine Variable `DEPFILES` deren Inhalt die Liste alle
|
||||
Einträge der Variable `SOURCES` ist, wobei bei allen die Endung `.c`
|
||||
durch die Endung `.c.png` ersetzt ist
|
||||
* fügen Sie zum `Pseudo-Target .PHONEY` das Target `dep` dazu – dies
|
||||
besagt, dass das später folgenden Target `dep` nicht ein File
|
||||
repräsentiert (ohne dieses Setting würde make gegebenenfalls nach
|
||||
einem File mit Namen `dep` suchen um zu entscheiden ob es
|
||||
inkrementell gebildet werden muss)
|
||||
* schreiben Sie das Target `dep` gemäss der Beschreibung im Makefile
|
||||
* schreiben Sie die Suffix Regel für die Übersetzung von `.png <-
|
||||
.dot` gemäss Vorgabe im `Makefile` (als Inspiration, siehe auch die
|
||||
`%.c.dep: %.c` Suffix Regel weiter unten im `Makefile`) – erklären
|
||||
Sie was die Regel macht
|
||||
* schreiben Sie die Suffix Regel für die Übersetzung von` .dot <-
|
||||
.dep` gemäss Vorgabe im `Makefile` – erklären Sie was die Regel
|
||||
macht
|
||||
|
||||
Die Umsetzung der obigen Änderungen sind erfolgreich, wenn Sie
|
||||
folgende Shell Command Line erfolgreich ausführen können und in
|
||||
Firefox die Abhängigkeiten der C-Files von den Inclu-de Files
|
||||
dargestellt wird.
|
||||
|
||||
`make dep-clean dep && firefox src/*.png.`
|
||||
|
||||
|
||||
|
||||
|
||||
(04_grading)=
|
||||
## 5. Bewertung
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
| Aufgabe | Kriterium | Punkte |
|
||||
| :-- | :-- | :-- |
|
||||
| 1 | Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären. | |
|
||||
| 1 | Module einbinden, Header Files schreiben | 2 |
|
||||
| 2 | Sie können das funktionierende Makefile demonstrieren und erklären. | |
|
||||
| 2 | Neue Regeln hinzufügen | 2 |
|
||||
|
||||
|
||||
|
||||
|
||||
(04_appendix)=
|
||||
## 6. Anhang
|
||||
|
||||
|
||||
|
||||
|
||||
### 6.1 Verwendete zusätzliche Sprach Elemente
|
||||
|
||||
<table><tr><td>
|
||||
|
||||
**Sprach Element**
|
||||
|
||||
</td><td>
|
||||
|
||||
**Beschreibung**
|
||||
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
|
||||
|
||||
|
||||
```C
|
||||
fprintf(stderr, "v=%d", v)
|
||||
```
|
||||
|
||||
</td><td>
|
||||
|
||||
Formatierte Ausgabe auf den Standard Error Stream. Siehe ***man 3
|
||||
stderr*** und ***man 3 fprintf***.
|
||||
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
### 6.2 Verarbeitung und verwendete File Formate <a name="file_formats"></a>
|
||||
|
||||
Das Programm in diesem Praktikum ist Teil für die graphische
|
||||
Darstellung von `#include` File Abhängigkeit von C Files.
|
||||
|
||||
Den ersten Schritt für die Darstellung der `#include` File
|
||||
Abhängigkeiten bietet der Compiler. Der Compiler kann mittels der `-H`
|
||||
Command Line Option auf `stderr` ein Text File generieren, welches die
|
||||
tatsächlich verwendeten Header Files auflistet. Zusätzlich wird im
|
||||
Resultat die Verschachtelungstiefe der Includes angegeben.
|
||||
|
||||
Im zweiten Schritt übersetzt das Programm (`dep2dot`) dieses
|
||||
Praktikums solche Dependency Files (`dep`) in eine Text Repräsentation
|
||||
der Abhängigkeiten (`dot`) welche in graphische Darstel-lung (`png`)
|
||||
übersetzt werden kann.
|
||||
|
||||
Als Tool zur Übersetzung der `dot` Files in das `png` Format dient das
|
||||
`dot` Tool. Dieses Tool muss gegebenenfalls installiert werden:
|
||||
|
||||
```sudo apt install graphviz```
|
||||
|
||||
Die `png` Files können dann z.B. in der Programm Dokumentation
|
||||
integriert werden (Darstellung zu Test Zwecken z.B. mittels `firefox
|
||||
file.png`).
|
||||
|
||||
|
||||
#### 6.2.1 dep File
|
||||
|
||||
|
||||
Siehe: `man gcc`
|
||||
|
||||
```bash
|
||||
-H Print the name of each header file used, in addition to other
|
||||
normal activities. Each name is indented to show how deep in the
|
||||
#include stack it is. [...]
|
||||
```
|
||||
|
||||
Das File wird auf `stderr` ausgegeben.
|
||||
|
||||
**Beispiel File** (für Abhängigkeiten des `main.c` Files des `dep2dot` Programms)
|
||||
|
||||
```bash
|
||||
. /usr/include/stdio.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/libc-header-start.h
|
||||
... /usr/include/features.h
|
||||
.... /usr/include/x86_64-linux-gnu/sys/cdefs.h
|
||||
..... /usr/include/x86_64-linux-gnu/bits/wordsize.h
|
||||
..... /usr/include/x86_64-linux-gnu/bits/long-double.h
|
||||
.... /usr/include/x86_64-linux-gnu/gnu/stubs.h
|
||||
..... /usr/include/x86_64-linux-gnu/gnu/stubs-64.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/types.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/wordsize.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/typesizes.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/types/__FILE.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/types/FILE.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/libio.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/_G_config.h
|
||||
.... /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
.... /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h
|
||||
... /usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/stdio_lim.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/sys_errlist.h
|
||||
. /usr/include/stdlib.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/libc-header-start.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/floatn.h
|
||||
... /usr/include/x86_64-linux-gnu/bits/floatn-common.h
|
||||
.... /usr/include/x86_64-linux-gnu/bits/long-double.h
|
||||
.. /usr/include/x86_64-linux-gnu/bits/stdlib-float.h
|
||||
. src/error.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
. src/data.h
|
||||
.. /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h
|
||||
. src/output.h
|
||||
Multiple include guards may be useful for:
|
||||
/usr/include/x86_64-linux-gnu/bits/stdlib-float.h
|
||||
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h
|
||||
/usr/include/x86_64-linux-gnu/bits/typesizes.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs.h
|
||||
```
|
||||
|
||||
|
||||
#### 6.2.2 dot File
|
||||
|
||||
**Graphviz** ist ein mächtiges Tool-Set welches Graphen, definiert in
|
||||
einem `dot`-Text File, automatisch anordnet und in `png`, `gif` und
|
||||
andere Formate übersetzt.
|
||||
|
||||
Siehe die offizielle Web-Page
|
||||
[https://www.graphviz.org/](https://www.graphviz.org/).
|
||||
|
||||
Es gibt als Teil dieses Tool-Sets verschiedene Übersetzer. Der hier
|
||||
verwendete ist der Basis-übersetzer: `dot`.
|
||||
|
||||
Das `dot`-File Format kennt viele Möglichkeiten die Knoten und Kanten
|
||||
eines Graphen und de-ren Anordnung anzugeben.
|
||||
|
||||
Der Vorteil eines solchen Tool-Sets ist, dass man den Inhalt (den
|
||||
Graphen) einfach definieren kann und sich nicht um das komplexe
|
||||
Problem der ansprechenden Visualisierung kümmern muss.
|
||||
|
||||
**Beispiel File** (`dot -Tpng sample.dot > sample.png`)
|
||||
|
||||
```C
|
||||
digraph G {
|
||||
node [shape=box]
|
||||
A [label="a.c"];
|
||||
B [label="a.h"];
|
||||
C [label="b.h"];
|
||||
|
||||
subgraph cluster_c0 {
|
||||
label="main"; color=black;
|
||||
A;
|
||||
}
|
||||
|
||||
subgraph cluster_c1 {
|
||||
label="others"; style=filled; col-or=lightgrey;
|
||||
{ B; C; rank=same; }
|
||||
}
|
||||
|
||||
A -> B;
|
||||
A -> C;
|
||||
B -> C;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 6.2.3 png File
|
||||
|
||||
Das `png` Format ist ein verlustfrei komprimiertes Raster Graphik
|
||||
Format. Es wird oft in Web Pages verwendet.
|
||||
|
||||
|
||||
___
|
||||
Version: 15.02.2022
|
||||
@@ -0,0 +1,127 @@
|
||||
# 04 - Modularisieren von C Code
|
||||
|
||||
___
|
||||
## 1. Übersicht
|
||||
|
||||
In diesem Praktikum wird eine kleine Sammlung von Funktionen als Modul erstellt.
|
||||
|
||||
In der ersten Aufgabe schreiben Sie zu einem bestehenden C Programm die notwendigen Header Files plus passen das Makefile so an, dass die entsprechenden Module mit kompiliert werden.
|
||||
|
||||
In der zweiten Aufgabe erstellen Sie Makefile Regeln um aus Konfigurationsdateien graphischen Darstellungen zu erzeugen.
|
||||
|
||||
___
|
||||
## 2. Lernziele
|
||||
|
||||
In diesem Praktikum lernen Sie die Handgriffe um ein Programm zu modularisieren, d.h. in mehrere Module aufzuteilen.
|
||||
|
||||
- Sie wissen, dass ein Modul aus einem C-File und einem passenden H-File bestehen.
|
||||
- Sie können Header Files korrekt strukturieren.
|
||||
- Sie wissen wie **Include Guards** anzuwenden sind.
|
||||
- Sie können Module im **Makefile** zur Kompilation hinzufügen.
|
||||
- Sie können anhand einer Beschreibung Typen und Funktionen in den passenden Header Files deklarieren.
|
||||
- Sie können **Makefile** Regeln schreiben.
|
||||
|
||||
Die Bewertung dieses Praktikums ist am Ende angegeben.
|
||||
|
||||
Erweitern Sie die vorgegebenen Code Gerüste, welche im **git** Repository **snp-lab-code** verfügbar sind.
|
||||
|
||||
___
|
||||
## 3. Aufgabe 1: Modularisieren
|
||||
|
||||

|
||||
|
||||
### 3.1 Teilaufgabe Modules einbinden, Header Files schreiben
|
||||
|
||||
- src/objects.h
|
||||
- 2 Datenstukturen definieren
|
||||
- `struct point` mit 2 double für x und y Koordinate
|
||||
- `struct line` mit 2 point
|
||||
- src/functions.h und .c
|
||||
- 2 Funktionen deklarieren und definieren
|
||||
- Berechnung der Länge `get_length`einer Linie (Annahme: Koordinaten sind alle positiv)
|
||||
- l = sqrt(h^ 2 + b^ 2)
|
||||
- ev. muss hier in den Anhang `#include <math.h>`
|
||||
- Berechnung der Steigung `get_slope` der Linie gegenüber dem Koordinatensystem
|
||||
- m = h / b
|
||||
- tests vorgeben
|
||||
|
||||
- src/objects.h
|
||||
- Include Guard
|
||||
- Includes
|
||||
- Struct für Punkt und Linie
|
||||
- Include Guard
|
||||
- src/functions.h
|
||||
- Include Guard
|
||||
- Includes
|
||||
- Deklarationen der Funktionen für Berechnung der Länge und Steigung
|
||||
- Include Guard
|
||||
- src/functions.c
|
||||
- Includes
|
||||
- Definitionen der Funktionen für Berechnung der Länge und Steigung
|
||||
- Include Guard
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
___
|
||||
## 4. Aufgabe 2: Makefile Regeln
|
||||
|
||||
Makefile ergänzen, damit Modul `functions` korrekt eingebunden und kompiliert wird.
|
||||
|
||||
1. Kompilieren Sie das ganze mittels **make clean default**. Es sollten keine Compiler Fehler auftreten.
|
||||
|
||||
### 4.1 Neue Regeln hinzufügen
|
||||
|
||||
- Vorraussetzung: tab2svg.sh aus Praktikum 3 wird um die Möglichkeit erweitert eine Linie zu zeichnen (`line:x1:y1:x2:y2:color`)
|
||||
- Studierende erstellen
|
||||
- mind. 2 Files `long.line` und `short.line` mit 2 unterschiedlichen Linien
|
||||
- Makefile Regeln um aus einem File `.line` ein File `.svg` mit Hilfe des Scripts zu erstellen
|
||||
- PHONY Regel `display` um beide `.svg` mit Firefox darzustellen
|
||||
- Vorgabe: sie sollen eine Variable für die Input-Dateien nutzen
|
||||
|
||||
Nachdem das Programm in Aufgabe 1 umgesetzt ist, geht es nun darum, im **Makefile** Regeln zu definieren welche die einzelnen Schritte von den Source Files zu den **png** Files ausführen.
|
||||
|
||||
Prüfen Sie schliesslich die Umsetzung mittels `make display`.
|
||||
|
||||
___
|
||||
## 5. Aufgabe 3
|
||||
- Studierende sollen Ausgabe von `make doc` analysieren und die Include Diagramme erklären können
|
||||
```
|
||||
make doc
|
||||
firefox doc/index.html &
|
||||
```
|
||||
|
||||
___
|
||||
## 6. Bewertung
|
||||
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
___
|
||||
## 7. Erweiterung Doxyfile für Abhängigkeitsanalyse
|
||||
|
||||
```
|
||||
--- /home/vagrant/huno/snp-new/snp/praktika/Shared/work/Doxyfile 2022-02-07 21:16:42.343302707 +0100
|
||||
+++ /home/vagrant/snp/Doxyfile 2022-02-07 22:22:36.266839126 +0100
|
||||
@@ -297,14 +297,14 @@
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
-INCLUDE_GRAPH = NO
|
||||
-INCLUDED_BY_GRAPH = NO
|
||||
+INCLUDE_GRAPH = YES
|
||||
+INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
-GRAPHICAL_HIERARCHY = NO
|
||||
-DIRECTORY_GRAPH = NO
|
||||
+GRAPHICAL_HIERARCHY = YES
|
||||
+DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
-INTERACTIVE_SVG = NO
|
||||
+INTERACTIVE_SVG = YES
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
```
|
||||
@@ -0,0 +1,272 @@
|
||||
05 - SNP: TicTacToe
|
||||
##############
|
||||
|
||||
|
||||
|
||||
.. image:: zhaw_neg_P2945.jpg
|
||||
:width: 100px
|
||||
:height: 100px
|
||||
:scale: 25 %
|
||||
:align: right
|
||||
|
||||
.. contents::
|
||||
|
||||
|
||||
|
||||
Übersicht
|
||||
*********
|
||||
In diesem Praktikum erweitern Sie einen Programm Rahmen zu einem funktionierenden TicTacToe Spiel. Bei TicTacToe legen zwei Spieler abwechselnd auf einem 3x3 Brett einen Stein, bis ein Spieler mit einer horizontalen, vertikalen oder diagonalen Linie gewinnt, oder alle Felder besetzt sind.
|
||||
|
||||
.. image:: TicTacToe.svg
|
||||
|
||||
In der Aufgabe implementieren Sie die fehlenden Funktionen bis alle Tests erfolgreich durchlau-fen. Die gewählte Vorgehensweise ist somit TDD – Test-Driven-Development: es existieren zuerst Tests welche alle fehlschlagen. Schrittweise werden die Funktionen implementiert bis alle Tests erfolgreich durchlaufen.
|
||||
|
||||
Wenn die Tests erfolgreich durchlaufen, wird auch das Programm funktionieren und Sie können jemanden mit dem Spiel herausfordern 😉.
|
||||
|
||||
|
||||
|
||||
Lernziele
|
||||
*********
|
||||
In diesem Praktikum lernen Sie den Zugriff auf Arrays.
|
||||
|
||||
* Sie können anhand einer Beschreibung im Code die fehlenden Funktionen implementieren wo auf Arrays zugegriffen wird.
|
||||
|
||||
Die Bewertung dieses Praktikums ist am Ende angegeben.
|
||||
|
||||
Erweitern Sie die vorgegebenen Code Gerüste, welche im git Repository snp-lab-code verfügbar sind.
|
||||
|
||||
|
||||
Aufgabe: TicTacToe
|
||||
******************
|
||||
Das zu ergänzende Programm tic-tac-toe hat folgende Funktionalität:
|
||||
#. es stellt ein 3x3 TicTacToe Spielbrett auf dem Terminal dar
|
||||
#. es liest von stdin eine Ziffer 0…9 ein, wobei 0 für Programm-Terminieren, die übrigen Ziffern für die Wahl eines Feldes stehen
|
||||
#. der erste Spielzug wird von Spieler A geführt, danach wechselt das Programm zwischen den Spielern A und B
|
||||
# bei Gewinn oder bei vollem Brett ist das Spiel vorbei
|
||||
|
||||
Wenn die Aufgabe erfolgreich umgesetzt ist, können Sie das Spiel ausführen:
|
||||
```bash
|
||||
bin/tic-tac-toe
|
||||
```
|
||||
|
||||
Als Abnahme müssen die Tests unverändert ohne Fehler ausgeführt werden (``make test``).
|
||||
|
||||
Die Architektur des Programms folgt dem MVC – Model-View-Control Paradigma. Dieses Paradigma besagt, dass die View (Eingabe und Darstellung) über Control (Vermittler) das Modell (die eigentliche Programm-Logik) steuert und darstellt. Dabei sind folgende Abhängigkeiten gegeben:
|
||||
|
||||
.. image:: MVC_pattern.svg
|
||||
|
||||
|
||||
|
||||
Test-Driven-Development
|
||||
=======================
|
||||
|
||||
Das Programm besteht aus folgenden Files:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Datei
|
||||
- ToDo
|
||||
* - Makefile
|
||||
- -
|
||||
* - tests/tests.c
|
||||
- -
|
||||
* - src/main.c
|
||||
- -
|
||||
* - src/view.h
|
||||
- -
|
||||
* - src/view.c
|
||||
- -
|
||||
* - src/control.h
|
||||
- -
|
||||
* - src/control.c
|
||||
- -
|
||||
* - src/model.h
|
||||
- -
|
||||
* - src/model.c
|
||||
- siehe unten
|
||||
|
||||
|
||||
1. Führen Sie ``make test`` aus::
|
||||
|
||||
Suite: lab test
|
||||
Test: test_model_init
|
||||
init_model:... 0/0 FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_get_state ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_get_winner ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_can_move ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_move ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_get_win_line ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
|
||||
Run Summary: Type Total Ran Passed Failed Inactive
|
||||
suites 1 1 n/a 0 0
|
||||
tests 6 6 0 6 0
|
||||
asserts 6 6 0 6 n/a
|
||||
|
||||
|
||||
|
||||
2. Konzentrieren Sie sich auf den ersten Test der fehlschlägt. Dies ist ein Unit Test, welcher die Funktion **model_init()** prüft. Suchen Sie die Funktion in **src/model.h** und **src/model.c**.
|
||||
Was ist die geforderte Funktionalität und wie ist sie implementiert?
|
||||
Suchen Sie die darin aufgerufene **model_init()** Funktion und implementieren Sie diese.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void model_init(model_t *instance) {
|
||||
assert(instance);
|
||||
// Instructions to the students:
|
||||
// set all fields of the board to model_state_none
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE }
|
||||
|
||||
|
||||
|
||||
|
||||
3. Führen Sie ``make test`` und korrigieren Sie obige Funktion, bis der Test nicht mehr fehlschlägt.
|
||||
|
||||
|
||||
|
||||
3.2 test_model_init
|
||||
===================
|
||||
|
||||
Gehen Sie analog zur ersten Teilaufgabe vor:
|
||||
1. Führen Sie ``make test`` aus.
|
||||
2. Suchen Sie die Funktion **model_get_state()** in **model.h** und **model.c**.
|
||||
3. Implementieren Sie die intern benutzte Funktion **get_state()** gemäss der Anleitung im Code.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
model_state_t model_get_state(model_t *instance, model_pos_t pos)
|
||||
{
|
||||
assert(instance);
|
||||
assert_pos(pos);
|
||||
|
||||
// Instructions to the students:
|
||||
// replace the stub implementation my access to the field at the given position.
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
|
||||
return model_state_none; // stub
|
||||
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE
|
||||
}
|
||||
|
||||
4. Führen Sie ``make test`` und korrigieren Sie, bis die beiden Tests nicht mehr fehlschlagen.
|
||||
|
||||
|
||||
|
||||
3.3 test_model_get_state test_model_get_winner
|
||||
==============================================
|
||||
|
||||
Gehen Sie analog zur ersten Teilaufgabe vor:
|
||||
1. Führen Sie ``make test`` aus.
|
||||
2. Suchen Sie die Funktion **model_get_state()** in **model.h** und **model.c**.
|
||||
3. Implementieren Sie die intern benutzte Funktion **get_state()** gemäss der Anleitung im Code.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
model_state_t model_get_state(model_t *instance, model_pos_t pos)
|
||||
{
|
||||
assert(instance);
|
||||
assert_pos(pos);
|
||||
|
||||
// Instructions to the students:
|
||||
// replace the stub implementation my access to the field at the given position.
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
|
||||
return model_state_none; // stub
|
||||
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3.4 test_model_can_move
|
||||
=======================
|
||||
|
||||
Gehen Sie analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion **model_can_move()**.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int model_can_move(model_t *instance){
|
||||
assert(instance);
|
||||
if (model_get_winner(instance) == model_state_none) {
|
||||
// Instructions to the students:
|
||||
// scan all fields: return 1 with first field which equals model_state_none
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE}
|
||||
return 0;}
|
||||
|
||||
|
||||
|
||||
|
||||
3.5 test_model_move test_model_get_win_line
|
||||
===========================================
|
||||
|
||||
Schliesslich gehen Sie auch hier analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion **set_state()**.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/**
|
||||
* @brief Sets the field on the board to the given state.
|
||||
* @param instance [INOUT] The instance which holds the state.
|
||||
* @param pos [IN] The affected field.
|
||||
* @param state [IN] The new state of the field.
|
||||
*/
|
||||
static void set_state(model_t *instance, model_pos_t pos, model_state_t state)
|
||||
{
|
||||
assert_pos(pos);
|
||||
|
||||
// Instructions to the students:
|
||||
// set the field of the board to the new state
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE
|
||||
}
|
||||
|
||||
|
||||
|
||||
Wenn die beiden obigen Teilaufgaben erfolgreich umgesetzt sind, laufen die Tests ohne Fehler durch und das Spiel kann gespielt werden.
|
||||
|
||||
|
||||
4. Bewertung
|
||||
******************
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 0
|
||||
|
||||
* - Aufgabe
|
||||
- Kriterium
|
||||
- Gewicht
|
||||
* - TicTacToe
|
||||
- Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären.
|
||||
-
|
||||
* - TicTacToe
|
||||
- Teilaufgabe test_model_init
|
||||
- 1
|
||||
* - TicTacToe
|
||||
- Teilaufgabe test_model_get_state und test_model_get_winner
|
||||
- 1
|
||||
* - TicTacToe
|
||||
- Teilaufgabe test_model_can_move
|
||||
- 1
|
||||
* - TicTacToe
|
||||
- Teilaufgabe test_model_move und test_model_get_win_line
|
||||
- 1
|
||||
|
||||
|
||||
Version: 15.02.2022
|
||||
@@ -0,0 +1,205 @@
|
||||
# 05 - Arrays/Strings/TicTacToe
|
||||
___
|
||||
|
||||
## 1. Übersicht
|
||||
In diesem Praktikum werden Sie in der ersten Aufgabe ein Programm zum Einlesen, Sortieren und Ausgeben von Strings von Grund auf entwickeln.
|
||||
|
||||
In der zweiten Aufgabe werden Sie einen Programmrahmen zu einem funktionierenden TicTacToe-Spiel erweitern. Sie implementieren hierbei die fehlenden Funktionen bis alle Tests erfolgreich durchlaufen. Die gewählte Vorgehensweise entspricht somit Test-Driven-Development (TDD). D.h. es existieren zuerst Tests, welche alle fehlschlagen. Schrittweise werden die Funktionen implementiert bis alle Tests erfolgreich durchlaufen. Wenn die Tests erfolgreich durchlaufen, wird auch das Programm funktionieren.
|
||||
|
||||
___
|
||||
|
||||
## 2. Lernziele
|
||||
In diesem Praktikum schreiben Sie selbst von Grund auf ein C-Programme, das mit Strings operiert. Ferner ergänzen Sie ein bestehendes und lernen dabei den Zugriff auf Arrays.
|
||||
|
||||
* Sie können mit Arrays von Strings umgehen.
|
||||
* Sie können String-Funktionen aus der Standard Library verwenden.
|
||||
* Sie können anhand einer Beschreibung im Code die fehlenden Funktionen die auf Arrays zugreifen implementieren.
|
||||
|
||||
___
|
||||
|
||||
## 3. Aufgabe 1: Sortieren von Strings
|
||||
Schreiben Sie ein C-Programm, das bis zu 10 Wörter mit einer maximalen Länge von jeweils 20 char von der Tastatur einliest, diese in Grossbuchstaben umwandelt, in einem Array der Reihe nach ablegt und zum Schluss im Array alphabetisch sortiert und ausgibt. Wiederholt eingegebene Wörter sollen dabei ignoriert werden. Das Ende der Eingabe soll durch das Erreichen der zehn unterschiedlichen Wörter oder durch die Eingabe von „ZZZ“ erfolgen. Die Ausgabe der sortierten Wörter soll direkt nach Beendigung der Eingabe erfolgen.
|
||||
|
||||
Hinweise:
|
||||
- Zur Speicherung der Wörter sollten Sie ein zweidimensionales Array verwenden.
|
||||
- Verwenden Sie die String-Funktionen der C Standard Library (include <string.h>), z.B. um Strings alphabetisch zu vergleichen.
|
||||
- Wenn Sie aus anderen Vorlesungen bereits einen effizienten Sortieralgorithmus kennen, können Sie diesen natürlich verwenden. Sonst erfinden Sie einfach einen eigenen.
|
||||
- Strukturieren Sie das Programm durch geeignete Funktionen.
|
||||
|
||||
___
|
||||
|
||||
## 4. Aufgabe 2: TicTacToe
|
||||
Das zu ergänzende Programm tic-tac-toe hat folgende Funktionalität:
|
||||
1. es stellt ein 3x3 TicTacToe Spielbrett auf dem Terminal dar
|
||||
2. es liest von stdin eine Ziffer 0…9 ein, wobei 0 für Programm-Terminieren, die übrigen Ziffern für die Wahl eines Feldes stehen
|
||||
3. der erste Spielzug wird von Spieler A geführt, danach wechselt das Programm zwischen den Spielern A und B
|
||||
4. bei Gewinn oder bei vollem Brett ist das Spiel vorbei
|
||||
|
||||
Erweitern Sie die vorgegebenen Code Gerüste, welche im git Repository snp-lab-code verfügbar sind.
|
||||
|
||||
Wenn die Aufgabe erfolgreich umgesetzt ist, können Sie das Spiel ausführen:
|
||||
```bash
|
||||
bin/tic-tac-toe
|
||||
```
|
||||
|
||||
|
||||

|
||||
|
||||
Als Abnahme müssen die Tests unverändert ohne Fehler ausgeführt werden (`make test`).
|
||||
|
||||
Die Architektur des Programms folgt dem MVC – Model-View-Control Paradigma. Dieses Paradigma besagt, dass die View (Eingabe und Darstellung) über Control (Vermittler) das Modell (die eigentliche Programm-Logik) steuert und darstellt. Dabei sind folgende Abhängigkeiten gegeben:
|
||||
|
||||
|
||||

|
||||
___
|
||||
|
||||
### 4.1 Teilaufgabe test_model_init
|
||||
Das Programm besteht aus folgenden Files:
|
||||
| Datei | ToDo |
|
||||
| :-- | :-- |
|
||||
|Makefile | -> gegeben, d.h. nichts anzupassen |
|
||||
|tests/tests.c| -> gegeben, d.h. nichts anzupassen |
|
||||
|src/main.c| -> gegeben, d.h. nichts anzupassen |
|
||||
|src/view.h| -> gegeben, d.h. nichts anzupassen |
|
||||
|src/view.c| -> gegeben, d.h. nichts anzupassen |
|
||||
|src/control.h| -> gegeben, d.h. nichts anzupassen |
|
||||
|src/control.c| -> gegeben, d.h. nichts anzupassen |
|
||||
|src/model.h| -> gegeben, d.h. nichts anzupassen |
|
||||
|src/model.c| -> **anzupassen:** umsetzen gemäss den Angaben unten |
|
||||
|
||||
1. Führen Sie `make test` aus
|
||||
```bash
|
||||
Suite: lab test
|
||||
Test: test_model_init ...
|
||||
init_model:... 0/0 FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_get_state ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_get_winner ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_can_move ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_move ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
Test: test_model_get_win_line ...FAILED
|
||||
1. tests/tests.c:62 - CU_ASSERT_EQUAL_FATAL(instance->board[row][col],model_state_none)
|
||||
|
||||
Run Summary: Type Total Ran Passed Failed Inactive
|
||||
suites 1 1 n/a 0 0
|
||||
tests 6 6 0 6 0
|
||||
asserts 6 6 0 6 n/a
|
||||
|
||||
```
|
||||
2. Konzentrieren Sie sich auf den ersten Test der fehlschlägt. Dies ist ein Unit Test, welcher die Funktion **model_init()** prüft. Suchen Sie die Funktion in **src/model.h** und **src/model.c**.
|
||||
3. Was ist die geforderte Funktionalität und wie ist sie implementiert?
|
||||
|
||||
Suchen Sie die darin aufgerufene **model_init()** Funktion und implementieren Sie diese.
|
||||
```c
|
||||
void model_init(model_t *instance)
|
||||
{
|
||||
assert(instance);
|
||||
|
||||
// Instructions to the students:
|
||||
// set all fields of the board to model_state_none
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE
|
||||
}
|
||||
|
||||
```
|
||||
3. Führen Sie `make test` und korrigieren Sie obige Funktion, bis der Test nicht mehr fehlschlägt.
|
||||
|
||||
___
|
||||
|
||||
### 4.2 Teilaufgabe test_model_get_state und test_model_get_winner
|
||||
Gehen Sie analog zur ersten Teilaufgabe vor:
|
||||
1. Führen Sie `make test` aus.
|
||||
2. Suchen Sie die Funktion **model_get_state()** in **model.h** und **model.c**.
|
||||
3. Implementieren Sie die intern benutzte Funktion **get_state()** gemäss der Anleitung im Code.
|
||||
|
||||
```c
|
||||
model_state_t model_get_state(model_t *instance, model_pos_t pos)
|
||||
{
|
||||
assert(instance);
|
||||
assert_pos(pos);
|
||||
|
||||
// Instructions to the students:
|
||||
// replace the stub implementation my access to the field at the given position.
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
|
||||
return model_state_none; // stub
|
||||
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
___
|
||||
|
||||
### 4.3 Teilaufgabe test_model_can_move
|
||||
Gehen Sie analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion **model_can_move()**.
|
||||
```c
|
||||
int model_can_move(model_t *instance)
|
||||
{
|
||||
assert(instance);
|
||||
if (model_get_winner(instance) == model_state_none) {
|
||||
// Instructions to the students:
|
||||
// scan all fields: return 1 with first field which equals model_state_none
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
___
|
||||
|
||||
### 4.4 Teilaufgabe test_model_move und test_model_get_win_line
|
||||
Schliesslich gehen Sie auch hier analog den obigen Teilaufgaben vor und implementieren Sie, gemäss Vorgaben im Code, die Funktion **set_state()**.
|
||||
```c
|
||||
/**
|
||||
* @brief Sets the field on the board to the given state.
|
||||
* @param instance [INOUT] The instance which holds the state.
|
||||
* @param pos [IN] The affected field.
|
||||
* @param state [IN] The new state of the field.
|
||||
*/
|
||||
static void set_state(model_t *instance, model_pos_t pos, model_state_t state)
|
||||
{
|
||||
assert_pos(pos);
|
||||
|
||||
// Instructions to the students:
|
||||
// set the field of the board to the new state
|
||||
// BEGIN-STUDENTS-TO-ADD-CODE
|
||||
|
||||
|
||||
|
||||
|
||||
// END-STUDENTS-TO-ADD-CODE
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Wenn die beiden obigen Teilaufgaben erfolgreich umgesetzt sind, laufen die Tests ohne Fehler durch und das Spiel kann gespielt werden.
|
||||
___
|
||||
|
||||
## 5. Bewertung
|
||||
|
||||
Der funktionierende Programmcode muss der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
| Aufgabe | Kriterium | Punkte |
|
||||
| :-- | :-- | :-- |
|
||||
| Sortieren von Strings | Sie können das funktionierende Programm demonstrieren und erklären. | 2 |
|
||||
| TicTacToe | Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären. | |
|
||||
| TicTacToe | Teilaufgabe test_model_init | 0.5 |
|
||||
| TicTacToe | Teilaufgabe test_model_get_state und test_model_get_winner | 0.5 |
|
||||
| TicTacToe | Teilaufgabe test_model_can_move | 0.5 |
|
||||
| TicTacToe | Teilaufgabe test_model_move und test_model_get_win_line | 0.5 |
|
||||
___
|
||||
Version: 14.02.2022
|
||||
@@ -0,0 +1,254 @@
|
||||
# 06 - Personen Verwaltung – Linked List
|
||||
___
|
||||
|
||||

|
||||
|
||||
___
|
||||
|
||||
## 1. Übersicht
|
||||
In diesem Praktikum schreiben Sie eine einfache Personenverwaltung. Dabei werden Sie etliche Elemente von C anwenden:
|
||||
* Header Files selber schreiben, inklusive Include Guard
|
||||
* Typen definieren
|
||||
* Funktionen mit `by value` und `by reference` Parametern deklarieren und definieren
|
||||
* einfache Variablen, Pointer Variablen, struct Variablen und Array Variablen benutzen
|
||||
* Strukturen im Speicher dynamisch allozieren und freigeben
|
||||
* I/O und String Funktionen aus der Standard Library anwenden
|
||||
* Anwender Eingaben verarbeiten
|
||||
* Fehlerbehandlung
|
||||
|
||||
___
|
||||
|
||||
## 2. Lernziele
|
||||
|
||||
In diesem Praktikum wenden Sie viele der bisher gelernten C Elemente an.
|
||||
* Sie können anhand dieser Beschreibung ein vollständiges C Programm schreiben.
|
||||
* Sie können Unit Tests schreiben welche die wesentlichen Funktionen des Programms individuell testen.
|
||||
*
|
||||
Die Bewertung dieses Praktikums ist am Ende angegeben.
|
||||
|
||||
Erweitern Sie die vorgegebenen Code Gerüste, welche im `git` Repository `snp-lab-code` verfügbar sind.
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 3. Personenverwaltung
|
||||
___
|
||||
|
||||
|
||||
### 3.1 Programmfunktion
|
||||
Das Programm soll in einer Schleife dem Benutzer jeweils folgende Auswahl bieten, wovon eine Aktion mit Eingabe des entsprechenden Buchstabens ausgelöst wird:
|
||||
|
||||
**I**(nsert), **R**(emove), **S**(how), **C**(lear), **E**(nd):
|
||||
* **Insert**: der Benutzer wird aufgefordert, eine Person einzugeben
|
||||
* **Remove**: der Benutzer wird aufgefordert, die Daten einer zu löschenden Person einzu-geben
|
||||
* **Show**: eine komplette Liste aller gespeicherten Personen wird in alphabetischer Rei-henfolge ausgegeben
|
||||
* **Clear**: alle Personen werden gelöscht
|
||||
* **End**: das Programm wird beendet
|
||||
|
||||
___
|
||||
|
||||
### 3.2 Designvorgaben
|
||||
|
||||
**Verkettete Liste**
|
||||
Da zur Kompilierzeit nicht bekannt ist, ob 10 oder 10'000 Personen eingegeben werden, wäre es keine gute Idee, im Programm einen statischen Array mit z.B. 10'000 Personen-Einträgen zu allozieren. Dies wäre ineffizient und umständlich beim sortierten Einfügen von Personen. In solchen Situationen arbeitet man deshalb mit dynamischen Datenstrukturen, die zur Laufzeit beliebig (solange Speicher vorhanden ist) wachsen und wieder schrumpfen können. Eine sehr populäre dynamische Datenstruktur ist die **verkettete Liste** und genau die werden wir in diesem Praktikum verwenden.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
Abbildung 1: Zyklisch verkettete Liste
|
||||
|
||||
|
||||
Eine verkettete Liste bedeutet, dass ein Knoten der verketten Liste einen Datensatz einer Person speichert und zusätzlich einen Pointer auf den nächsten Knoten in der Liste aufweist (siehe Abbildung 1). In dieser Pointer Variablen (`next` in der `node_t` Struktur unten) steht also einfach die Adresse des nächsten Knotens.
|
||||
|
||||
Die leere Liste besteht aus einem einzelnen Element, welches keine spezifische Person abspeichert und welches auf sich selbst zeigt (Abbildung 1 a). Dieses Element ist der Einstiegspunkt der Liste (auch Anker oder Wurzel genannt) und ist das einzige Element, das Sie im Programm direkt kennen und einer Variablen zuweisen. Dieses Element können Sie statisch allozieren (z.B. `node_t anchor`;, siehe Details weiter unten), denn es existiert während der gesamten Ausführungszeit. Alle anderen Elemente erreichen Sie ausgehend vom Anker, indem Sie einmal, den Pointern folgend, im Kreis herum gehen. Abbildung 1 b zeigt die Liste nach dem Einfügen der Person `Max Mueller, 40` Jahre. Nach dem Einfügen von zwei weiteren Personen sieht die Datenstruktur aus wie in Abbildung 1 c. Das Entfernen der Person `Arno Bosshard` führt zu Abbildung 1 d.
|
||||
|
||||
Eine Person kann **zugefügt** werden, indem dynamisch ein neuer Knoten erzeugt wird und dieser in die verkettete Liste eingefügt wird. Beim Einfügen müssen die Adressen der Knoten so den Pointern zugewiesen werden, dass die Kette intakt bleibt.
|
||||
|
||||
Ein Knoten wird **entfernt**, indem der entsprechende Knoten aus der Verkettung herausgelöst wird (`next` des Vorgängerknotens soll neu auf `next` des herauszulösenden Knotens zeigen) und dann der Speicher des entsprechenden Knotens freigegeben wird.
|
||||
|
||||
**Personen und Knoten Records**
|
||||
|
||||
Die für je eine Person zu speichernden Daten sollen in folgendem C `struct` zusammengefasst sein.
|
||||
|
||||
```C
|
||||
#define NAME_LEN 20
|
||||
|
||||
typedef struct {
|
||||
char name[NAME_LEN];
|
||||
char first_name[NAME_LEN];
|
||||
unsigned int age;
|
||||
} person_t;
|
||||
```
|
||||
|
||||
Jeder Knoten der verketteten Liste soll aus folgendem C `struct` bestehen.
|
||||
|
||||
```C
|
||||
typedef struct node {
|
||||
person_t content; // in diesem Knoten gespeicherte Person
|
||||
struct node *next; // Pointer auf den nächsten Knoten in der Liste
|
||||
} node_t;
|
||||
```
|
||||
|
||||
**Vorschlag: zyklisch verkettete Liste**
|
||||
|
||||
Erkennen des Endes der Liste: bei der zyklisch verketteten Liste zeigt das letzte Element wie-der auf den Anker, die Liste bildet also einen Kreis. Dies ist in Abbildung 1 so abgebildet.
|
||||
|
||||
Alternativ könnte man das Ende erkennbar machen, indem die Kette anstelle von zyklisch, mit einem NULL Pointer endet.
|
||||
|
||||
Die Wahl ist ihnen überlassen ob sie die eine oder andere Art der End-Erkennung implementieren. In der Beschreibung wird angenommen, dass es sich um eine zyklisch verkettete Liste handelt.
|
||||
|
||||
**Sortiertes Einfügen**
|
||||
|
||||
Die Personen Records sollen sortiert in die Liste eingefügt werden. Dies bedeutet, dass vom Anker her gesucht werden soll, bis der erste Knoten gefunden wurde dessen Nachfolgeknoten entweder „grösser“ ist als der einzufügende Knoten, oder wo das Ende der Liste erreicht ist. Die Ordnung (grösser, gleich, kleiner) soll so definiert sein:
|
||||
|
||||
```C
|
||||
// if (p1 > p2) { ... }
|
||||
if (person_compare(&p1, &p2) > 0) { ... }
|
||||
/**
|
||||
* @brief Compares two persons in this sequence: 1st=name, 2nd=first_name, 3rd=age
|
||||
* @param a [IN] const reference to 1st person in the comparison
|
||||
* @param b [IN] const reference to 2nd person in the comparison
|
||||
* @return =0 if all record fields are the same
|
||||
* >0 if all previous fields are the same, but for this field, a is greater
|
||||
* <0 if all previous fields are the same, but for this field, b is greater
|
||||
* @remark strncmp() is used for producing the result of string field comparisons
|
||||
* @remark a->age – b->age is used for producing the result of age comparison
|
||||
*/
|
||||
int person_compare(const person_t *a, const person_t *b);
|
||||
```
|
||||
|
||||
**Eingabe**
|
||||
|
||||
**Fehlerhafte Wahl der Operation** in der Hauptschleife soll gemeldet werden, ansonsten aber ignoriert werden.
|
||||
|
||||
**Fehlerhafte Eingabe der Personenangaben** sollen gemeldet werden und die gesamte Operation (z.B. Insert) verworfen werden.
|
||||
|
||||
Zu prüfende Fehler bei Personeneingaben:
|
||||
* für die Namen
|
||||
* zu lange Namen
|
||||
* für das Alter
|
||||
* keine Zahl
|
||||
* Duplikat
|
||||
* derselbe Record soll nicht doppelt in der Liste vorkommen
|
||||
|
||||
Weitergehende Prüfungen sind nicht erwartet.
|
||||
|
||||
**Zu beachten:** bei fehlerhafter Eingabe darf kein „Memory Leak“ entstehen, d.h. potentiell auf dem Heap allozierter Speicher muss im Fehlerfall freigegeben werden.
|
||||
|
||||
|
||||
___
|
||||
|
||||
### 3.3 Bestehender Programmrahmen
|
||||
|
||||
Der Programmrahmen besteht aus den unten aufgelisteten Files. Es sollen weitere Module in `src` hinzugefügt werden und die bestehenden Files ergänzt werden gemäss den Aufgaben.
|
||||
|
||||
| | |
|
||||
| :-- | :-- |
|
||||
| Makefile | -> **zu ergänzen** mit neuen Modulen |
|
||||
| tests/tests.c | -> **zu ergänzen** gemäss Aufgaben (implementieren von Unit Tests) |
|
||||
| src/main.c | -> **zu ergänzen** gemäss Aufgaben (Hauptprogramm) |
|
||||
|
||||
___
|
||||
|
||||
## 4. Aufgabe 1: Modularisierung – API und Implementation main.c
|
||||
Kreieren Sie folgende Files in `src` und implementieren Sie `main.c` basierend auf dem unten von Ihnen gegebenen API.
|
||||
|
||||
|
||||
**File person.h**
|
||||
|
||||
|
||||
Typ Definitionen:
|
||||
```C
|
||||
person_t... // siehe Beschreibung oben
|
||||
```
|
||||
|
||||
Funktionsdeklarationen:
|
||||
```C
|
||||
// siehe Beschreibung oben
|
||||
int person_compare(const person_t *a, const person_t *b);
|
||||
```
|
||||
|
||||
* gegebenenfalls weitere Funktionen für die Bearbeitung von Personen
|
||||
|
||||
|
||||
|
||||
|
||||
**File list.h**
|
||||
|
||||
Typ Definitionen:
|
||||
```C
|
||||
person_t... // siehe Beschreibung oben
|
||||
```
|
||||
|
||||
Funktionsdeklarationen:
|
||||
* Funktionen für `insert`, `remove`, `clear` Operationen auf der Liste
|
||||
|
||||
___
|
||||
|
||||
Das Hauptprogramm soll die Eingabeschleife implementieren und die obigen Funktionen (wo angebracht) aufrufen.
|
||||
|
||||
___
|
||||
|
||||
## 5. Aufgabe 2: Implementierung von person.c und list.c
|
||||
|
||||
Fügen Sie die beiden Implementationsfiles `person.c` und `list.c` zu `src`. Fügen Sie die beiden Module im `Makefile` zu der vorgegebenen Variablen `MODULES` hinzu, so dass sie beim `make` Aufruf auch berücksichtigt werden.
|
||||
|
||||
___
|
||||
|
||||
### 5.1 Teilaufgabe: Implementierung von person.c
|
||||
Implementieren Sie die Funktionen aus `person.h`.
|
||||
|
||||
Falls nötig, stellen Sie weitere statische Hilfsfunktionen in `person.c` zur Verfügung.
|
||||
|
||||
___
|
||||
|
||||
### 5.2 Teilaufgabe: Implementierung von list.c
|
||||
|
||||
Implementieren Sie die Funktionen aus `list.h`.
|
||||
|
||||
Falls nötig, stellen Sie weitere statische Hilfsfunktionen in `list.c` zur Verfügung.
|
||||
|
||||
___
|
||||
|
||||
## 6. Aufgabe 3: Unit Tests
|
||||
|
||||
Schreiben Sie Unit Tests für mindestens die folgenden Funktionen
|
||||
|
||||
* `person.h:`
|
||||
* `person_compare`
|
||||
* `list.h:`
|
||||
* `list_insert`
|
||||
* `list_remove`
|
||||
* `list_clear`
|
||||
|
||||
Es existieren in `tests/tests.c` schon vier Test Rahmen für diese Test Cases.
|
||||
|
||||
In diese Test Cases sollen die entsprechenden Funktionen unter verschiedenen Bedingungen isoliert aufgerufen werden und deren Verhalten überprüft werden.
|
||||
|
||||
Verwenden Sie für die Überprüfung die CUnit `CU_ASSERT_...` Makros.
|
||||
|
||||
Siehe dazu auch `man CUnit`.
|
||||
|
||||
Wenn die obigen Teilaufgaben erfolgreich umgesetzt sind, laufen die Tests ohne Fehler durch.
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 7. Bewertung
|
||||
|
||||
| Aufgabe | Kriterium | Punkte |
|
||||
| :-- | :-- | :-- |
|
||||
| | Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären. | |
|
||||
| 1 | API von list.h und person.h plus die Implementation von main.c | 2 |
|
||||
| 2 | Teilaufgabe: person.c | 2 |
|
||||
| 2 | Teilaufgabe: list.c | 2 |
|
||||
| 3 | Unit Tests | 2 |
|
||||
|
||||
___
|
||||
Version: 11.01.2022
|
||||
@@ -0,0 +1,441 @@
|
||||
# 07 - Prozesse und Threads
|
||||
___
|
||||
|
||||

|
||||
|
||||
|
||||
[Quelle: https://www.wikiwand.com/de/Ein-Mann-Orchester](https://www.wikiwand.com/de/Ein-Mann-Orchester)
|
||||
|
||||
___
|
||||
|
||||
## 1. Übersicht
|
||||
In diesem Praktikum werden wir uns mit Prozessen, Prozesshierarchien und Threads beschäftigen, um ein gutes Grundverständnis dieser Abstraktionen zu erhalten. Sie werden bestehenden Code analysieren und damit experimentieren. D.h. dies ist nicht ein «Codierungs»-Praktikum, sondern ein «Analyse»- und «Experimentier»-Praktikum.
|
||||
___
|
||||
|
||||
### 1.1 Nachweis
|
||||
Dieses Praktikum ist eine leicht abgewandelte Variante des ProcThreads Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.
|
||||
|
||||
Als Autoren des BSY Praktikums sind genannt: M. Thaler, J. Zeman.
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 2. Lernziele
|
||||
In diesem Praktikum werden Sie sich mit Prozessen, Prozesshierarchien und Threads beschäftigen. Sie erhalten einen vertieften Einblick und Verständnis zur Erzeugung, Steuerung und Terminierung von Prozessen unter Unix/Linux und Sie werden die unterschiedlichen Eigenschaften von Prozessen und Threads kennenlernen.
|
||||
* Sie können Prozesse erzeugen und die Prozesshierarchie erklären
|
||||
* Sie wissen was beim Erzeugen eines Prozesses vom Elternprozess vererbt wird
|
||||
* Sie wissen wie man auf die Terminierung von Kindprozessen wartet
|
||||
* Sie kennen die Unterschiede zwischen Prozessen und Threads
|
||||
___
|
||||
|
||||
## 3. Aufgaben
|
||||
Das Betriebssystem bietet Programme um die aktuellen Prozesse und Threads darzustellen.
|
||||
|
||||
Die Werkzeuge kommen mit einer Vielzahl von Optionen für die Auswahl und Darstellung der Daten, z.B. ob nur Prozesse oder auch Threads aufgelistet werden sollen, und ob alle Prozesse oder nur die «eigenen» Prozesse ausgewählt werden sollen, etc.
|
||||
|
||||
Siehe die entsprechenden `man` Pages für weitere Details.
|
||||
|
||||
Eine Auswahl, welche unter Umständen für die folgenden Aufgaben nützlich sind:
|
||||
|
||||
| | |
|
||||
| :-- | :-- |
|
||||
| `ps` | Auflisten der Prozess Zustände zum gegebenen Zeitpunkt. |
|
||||
| `pstree` | Darstellung der gesamten Prozesshierarchie. |
|
||||
| `top` | Wie `ps`, aber die Darstellung wird in Zeitintervallen aufdatiert. |
|
||||
| `htop` | Wie `top`, aber zusätzlich dazu die Auslastung der CPU in einem System mit mehreren CPUs. |
|
||||
| `lscpu` | Auflisten der CPUs. |
|
||||
| `cat`/`proc`/`cpuinfo` | Ähnlich zu `lscpu`, aber mit Zusatzinformationen wie enthaltene CPU Bugs (z.B. `bugs: cpu_meltdown spectre_v1 spect-re_v2 spec_store_bypass l1tf mds swapgs itlb_multihit`) |
|
||||
|
||||
___
|
||||
|
||||
### 3.1 Aufgabe 1: Prozess mit fork() erzeugen
|
||||
|
||||
**Ziele**
|
||||
|
||||
* Verstehen, wie mit `fork()` Prozesse erzeugt werden.
|
||||
* Einfache Prozesshierarchien kennenlernen.
|
||||
* Verstehen, wie ein Programm, das `fork()` aufruft, durchlaufen wird.
|
||||
|
||||
**Aufgaben**
|
||||
1. Studieren Sie zuerst das Programm `ProcA1.c` und beschrieben Sie was geschieht.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
2. Notieren Sie sich, was ausgegeben wird. Starten Sie das Programm und vergleichen Sie die Ausgabe mit ihren Notizen? Was ist gleich, was anders und wieso?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
___
|
||||
|
||||
### 3.2 Aufgabe 2: Prozess mit fork() und exec(): Programm Image ersetzen
|
||||
|
||||
**Ziele**
|
||||
* An einem Beispiel die Funktion `execl()` kennenlernen.
|
||||
* Verstehen, wie nach `fork()` ein neues Programm gestartet wird.
|
||||
**Aufgaben**
|
||||
1. Studieren Sie zuerst die Programme `ProcA2.c` und `ChildProcA2.c`.
|
||||
2. Starten Sie `ProcA2.e` und vergleichen Sie die Ausgabe mit der Ausgabe unter Aufgabe 1. Diskutieren und erklären Sie was gleich ist und was anders.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
3. Benennen Sie `ChildProcA2.e` auf `ChildProcA2.f` um (Shell Befehl `mv`) und überlegen Sie, was das Programm nun ausgibt. Starten Sie `ProcA2.e` und vergleichen Sie Ihre Überlegungen mit der Programmausgabe.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
4. Nennen Sie das Kindprogramm wieder `ChildProcA2.e` und geben Sie folgenden Befehl ein: `chmod -x ChildProcA2.e`. Starten Sie wiederum `ProcA2.e` und analysieren Sie die Ausgabe von `perror("...")`. Wieso verwenden wir `perror()`?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
___
|
||||
|
||||
### 3.3 Aufgabe 3: Prozesshierarchie analysieren
|
||||
|
||||
**Ziele**
|
||||
|
||||
* Verstehen, was `fork()` wirklich macht.
|
||||
* Verstehen, was Prozesshierarchien sind.
|
||||
|
||||
**Aufgaben**
|
||||
|
||||
1. Studieren Sie zuerst Programm `ProcA3.c` und zeichnen Sie die entstehende Prozesshierarchie (Baum) von Hand auf. Starten Sie das Programm und verifizieren Sie ob Ihre Prozesshierarchie stimmt.
|
||||
2. Mit dem Befehl `ps f` oder `pstree` können Sie die Prozesshierarchie auf dem Bildschirm ausgeben. Damit die Ausgabe von `pstree` übersichtlich ist, müssen Sie in dem Fenster, wo Sie das Programm `ProcA3.e` starten, zuerst die PID der Shell erfragen, z.B. über `echo $$`. Wenn Sie nun den Befehl `pstree -n -p pid-von-oben` eingeben, wird nur die Prozesshierarchie ausgehend von der Bash Shell angezeigt: `-n` sortiert die Prozesse numerisch, `-p` zeigt für jeden Prozess die PID an.
|
||||
|
||||
**Hinweis:** alle erzeugten Prozesse müssen arbeiten (d.h. nicht terminiert sein), damit die Darstellung gelingt. Wie wird das im gegebenen Programm erreicht?
|
||||
|
||||
|
||||
___
|
||||
|
||||
### 3.4 Aufgabe 4: Zeitlicher Ablauf von Prozessen
|
||||
|
||||
**Ziele**
|
||||
|
||||
* Verstehen, wie Kind- und Elternprozesse zeitlich ablaufen.
|
||||
|
||||
**Aufgaben**
|
||||
|
||||
1. Studieren Sie Programm `ProcA4.c.` Starten Sie nun mehrmals hintereinander das Programm `ProcA4.e` und vergleichen Sie die jeweiligen Outputs (leiten Sie dazu auch die Ausgabe auf verschiedene Dateien um). Was schliessen Sie aus dem Resultat?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
**Anmerkung:** Der Funktionsaufruf `selectCPU(0)` erzwingt die Ausführung des Eltern- und Kindprozesses auf CPU 0 (siehe Modul `setCPU.c`). Die Prozedur `justWork(HARD_WORK)` simuliert CPU-Load durch den Prozess (siehe Modul `workerUtils.c`).
|
||||
|
||||
___
|
||||
|
||||
### 3.5 Aufgabe 5: Waisenkinder (Orphan Processes)
|
||||
|
||||
**Ziele**
|
||||
* Verstehen, was mit verwaisten Kindern geschieht.
|
||||
|
||||
**Aufgaben**
|
||||
1. Analysieren Sie Programm `ProcA5.c`: was läuft ab und welche Ausgabe erwarten Sie?
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
2. Starten Sie `ProcA5.e`: der Elternprozess terminiert: was geschieht mit dem Kind?
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
3. Was geschieht, wenn der Kindprozess vor dem Elternprozess terminiert? Ändern Sie dazu im `sleep()` Befehl die Zeit von 2 Sekunden auf 12 Sekunden und verfolgen Sie mit top das Verhalten der beiden Prozesse, speziell auch die Spalte S.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
___
|
||||
|
||||
### 3.6 Aufgabe 6: Terminierte, halbtote Prozesse (Zombies)
|
||||
|
||||
**Ziele**
|
||||
|
||||
* Verstehen, was ein Zombie ist.
|
||||
* Eine Möglichkeit kennenlernen, um Zombies zu verhindern.
|
||||
|
||||
**Aufgaben**
|
||||
|
||||
1. Analysieren Sie das Programm `ProcA6.c`.
|
||||
2. Starten Sie das Script `mtop` bzw. `mtop aaaa.e`. Es stellt das Verhalten der Prozesse dynamisch dar.
|
||||
|
||||
**Hinweis:** `<defunct>` = Zombie.
|
||||
3. Starten Sie `aaaa.e` und verfolgen Sie im `mtop`-Fenster was geschieht. Was beachten Sie?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
4. In gewissen Fällen will man nicht auf die Terminierung eines Kindes mit `wait()`, bzw. `waitpid()` warten. Überlegen Sie sich, wie Sie in diesem Fall verhindern können, dass ein Kind zum Zombie wird.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
___
|
||||
|
||||
### 3.7 Aufgabe 7: Auf Terminieren von Kindprozessen warten
|
||||
|
||||
**Vorbemerkung:** Diese Aufgabe verwendet Funktionen welche erst in der Vorlesung über *Inter-Process-Communication (IPC)* im Detail behandelt werden.
|
||||
|
||||
Sie können diese Aufgabe bis dann aufsparen oder die verwendeten Funktionen selber via `man` Pages im benötigten Umfang kennenlernen: `man 2 kill` und `man 7 signal`.
|
||||
|
||||
**Ziele**
|
||||
* Verstehen, wie Informationen zu Kindprozessen abgefragt werden können.
|
||||
* Die Befehle `wait()` und `waitpid()` verwenden können.
|
||||
|
||||
**Aufgaben**
|
||||
1. Starten Sie das Programm `ProcA7.e` und analysieren Sie wie die Ausgabe im Hauptprogramm zustande kommt und was im Kindprozess `ChildProcA7.c` abläuft.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
2. Starten Sie `ProcA7.e` und danach nochmals mit `1` als erstem Argument. Dieser Argument Wert bewirkt, dass im Kindprozess ein ”Segmentation Error” erzeugt wird, also eine Speicherzugriffsverletzung. Welches Signal wird durch die Zugriffsverletzung an das Kind geschickt? Diese Information finden Sie im Manual mit `man 7 signal`. Schalten Sie nun core dump ein (siehe README) und starten Sie `ProcA7.e 1` erneut und analysieren Sie die Ausgabe.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
**Hinweis:** ein core Dump ist ein Abbild des Speichers z.B. zum Zeitpunkt, wenn das Programm abstürzt (wie oben mit der Speicher Zugriff Verletzung). Der Dump wird im File **core** abgelegt und kann mit dem **gdb** (GNU-Debugger) gelesen werden (siehe `README`). Tippen Sie nach dem Starten des Command Line UI des `gdb where` gefolgt von list ein, damit sie den Ort des Absturzes sehen. Mit `quit` verlassen Sie **gdb** wieder.
|
||||
|
||||
3. Wenn Sie `ProcA7.e 2` starten, sendet das Kind das Signal 30 an sich selbst. Was geschieht?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
4. Wenn Sie `ProcA7.e 3` starten, sendet ProcA7.e das Signal SIGABRT (abort) an das Kind: was geschieht in diesem Fall?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
5. Mit `ProcA7.e 4` wird das Kind gestartet und terminiert nach 5 Sekunden. Analysieren Sie wie in ProcA7.e der Lauf- bzw. Exit-Zustand des Kindes abgefragt wird (siehe dazu auch `man 3 exit`).
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
___
|
||||
|
||||
### 3.8 Aufgabe 8: Kindprozess als Kopie des Elternprozesses
|
||||
|
||||
**Ziele**
|
||||
* Verstehen, wie Prozessräume vererbt werden.
|
||||
* Unterschiede zwischen dem Prozessraum von Eltern und Kindern erfahren.
|
||||
|
||||
**Aufgaben**
|
||||
1. Analysieren Sie Programm `ProcA8_1.c`: was gibt das Programm aus?
|
||||
* Starten Sie `ProcA8_1.e `und überprüfen Sie Ihre Überlegungen.
|
||||
* Waren Ihre Überlegungen richtig? Falls nicht, was könnten Sie falsch überlegt haben?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
2. Analysieren Sie Programm `ProcA8_2.c`: was gibt das Programm aus?
|
||||
* Starten Sie `ProcA8_2.e` und überprüfen Sie Ihre Überlegungen.
|
||||
* Waren Ihre Überlegungen richtig? Falls nicht, was könnten Sie falsch gemacht haben?
|
||||
* Kind und Eltern werden in verschiedener Reihenfolge ausgeführt: ist ein Unterschied ausser der Reihenfolge festzustellen?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
3. Analysieren Sie Programm `ProcA8_3.c` und Überlegen Sie, was in die Datei `AnyOutPut.txt` geschrieben wird, wer schreibt alles in diese Datei (sie wird ja vor `fork()` geöffnet) und wieso ist das so?
|
||||
* Starten Sie `ProcA8_3.e` und überprüfen Sie Ihre Überlegungen.
|
||||
* Waren Ihre Überlegungen richtig? Falls nicht, wieso nicht?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
___
|
||||
|
||||
### 3.9 Aufgabe 9: Unterschied von Threads gegenüber Prozessen
|
||||
|
||||
**Ziele**
|
||||
* Den Unterschied zwischen Thread und Prozess kennenlernen.
|
||||
* Problemstellungen um Threads kennenlernen.
|
||||
* Die `pthread`-Implementation kennen lernen.
|
||||
|
||||
**Aufgaben**
|
||||
1. Studieren Sie Programm `ProcA9.c` und überlegen Sie, wie die Programmausgabe aussieht. Vergleichen Sie Ihre Überlegungen mit denjenigen aus Aufgabe 8.2 b) (`Pro-cA8_2.e`).
|
||||
* Starten Sie `ProcA9.e` und vergleichen das Resultat mit Ihren Überlegungen.
|
||||
* Was ist anders als bei `ProcA8_2.e`?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
2. Setzen Sie in der Thread-Routine vor dem Befehl `pthread_exit()` eine unendliche Schleife ein, z.B. `while(1) { }`; .
|
||||
* Starten Sie das Programm und beobachten Sie das Verhalten mit `top`. Was beobachten Sie und was schliessen Sie daraus?
|
||||
|
||||
**Hinweis:** wenn Sie in `top` den Buchstaben H eingeben, werden die Threads einzeln dargestellt.
|
||||
* Kommentieren Sie im Hauptprogram die beiden `pthread_join()` Aufrufe aus und starten Sie das Programm. Was geschieht? Erklären Sie das Verhalten.
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
___
|
||||
|
||||
### 3.10 Aufgabe 10 (optional):
|
||||
|
||||
#### 3.10.1 Übersicht
|
||||
Dieser Teil des Praktikums behandelt spezielle Prozesse: die Dämon Prozesse («daemon pro-cesses»). Es ist gedacht als Zusatz zum Basis Praktikum über Prozesse und Threads.
|
||||
|
||||
Auch dieser Teil ist ein «Analyse»- und «Experimentier»-Praktikum.
|
||||
___
|
||||
|
||||
##### 3.10.1.1 Nachweis
|
||||
Dieses Praktikum ist eine leicht abgewandelte Variante des ProcThreads Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.
|
||||
|
||||
Als Autoren des BSY Praktikums sind genannt: M. Thaler, J. Zeman.
|
||||
|
||||
|
||||
___
|
||||
|
||||
#### 3.10.2 Lernziele
|
||||
In diesem Praktikum werden Sie sich mit Dämon Prozessen beschäftigen.
|
||||
* Sie können die Problemstellung der Dämon Prozesse erklären
|
||||
* Sie können einen Dämon Prozess kreieren
|
||||
* Sie können aus dem Dämon Prozess mit der Umgebung kommunizieren
|
||||
*
|
||||
___
|
||||
|
||||
#### 3.10.3 Aufgabe: Dämon Prozesse
|
||||
|
||||
**Ziele**
|
||||
* Problemstellungen um Daemons kennenlernen:
|
||||
* wie wird ein Prozess zum Daemon?
|
||||
* wie erreicht man, dass nur ein Daemon vom gleichen Typ aktiv ist?
|
||||
* wie teilt sich ein Daemon seiner Umwelt mit?
|
||||
* wo "lebt" ein Daemon?
|
||||
|
||||
**Einleitung**
|
||||
|
||||
Für diese Aufgabe haben wir einen Daemon implementiert: **MrTimeDaemon** gibt auf Anfrage die Systemzeit Ihres Rechners bekannt. Abfragen können Sie diese Zeit mit dem Programm `WhatsTheTimeMr localhost`. Die Kommunikation zwischen den beiden Prozessen haben wir mit TCP/IP Sockets implementiert. Weitere Infos zum Daemon finden Sie nach den Aufgaben.
|
||||
|
||||
Im Abschnitt 4 finden Sie Zusatzinformationen über diese Implementation eines Dämon Prozesses plus weiterführende Informationen.
|
||||
|
||||
**Aufgaben**
|
||||
|
||||
1. Für die folgende Aufgabe benötigen Sie mindestens zwei Fenster (Kommandozeilen-Konsolen). Übersetzen Sie die Programme mit `make` und starten Sie das Programm **PlapperMaul** in einem der Fenster. Das Programm schreibt (ca.) alle 0.5 Sekunden *Hallo, ich bins.... Pidi* plus seine Prozess-ID auf den Bildschirm. Mit dem Shell Befehl `ps` können Sie Ihre aktiven Prozesse auflisten, auch **PlapperMaul**. Überlegen Sie sich zuerst, was mit **PlapperMaul** geschieht, wenn Sie das Fenster schliessen: läuft **PlapperMaul** weiter? Was geschieht mit **PlapperMaul** wenn Sie sich ausloggen und wieder einloggen? Testen Sie Ihre Überlegungen, in dem Sie die entsprechenden Aktionen durchführen. Stimmen Ihre Überlegungen?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
2. Starten Sie nun das Programm bzw. den Daemon **MrTimeDaemon**. Stellen Sie die gleichen Überlegungen an wie mit **PlapperMaul** und testen Sie wiederum, ob Ihre Überlegungen stimmen. Ob **MrTimeDaemon** noch läuft können Sie feststellen, indem Sie die Zeit abfragen oder den Befehl `ps ajx | grep MrTimeDaemon` eingeben: was fällt Ihnen am Output auf? Was schliessen Sie aus Ihren Beobachtungen?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
3. Starten Sie **MrTimeDaemon** erneut, was geschieht?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
4. Stoppen Sie nun **MrTimeDaemon** mit `killall MrTimeDaemon`.
|
||||
5. Starten Sie **MrTimeDaemon** und fragen Sie mit `WhatsTheTimeMr localhost` oder mit `WhatsTheTimeMr 127.0.0.1` die aktuelle Zeit auf Ihrem Rechner ab.
|
||||
|
||||
|
||||
**Optional:**
|
||||
Fragen Sie die Zeit bei einem Ihrer Kollegen ab. Dazu muss beim Server (dort wo **MrTimeDaemon** läuft) ev. die Firewall angepasst werden. Folgende Befehle müssen dazu mit **root-Privilegien** ausgeführt werden:
|
||||
|
||||
```bash
|
||||
iptables-save > myTables.txt # sichert die aktuelle Firewall
|
||||
iptables -I INPUT 1 -p tcp --dport 65534 -j ACCEPT
|
||||
iptables -I OUTPUT 2 -p tcp --sport 65534 -j ACCEPT
|
||||
```
|
||||
|
||||
Nun sollten Sie über die IP-Nummer oder über den Rechner-Namen auf den **TimeServer** mit `WhatsTheTimeMr` zugreifen können.
|
||||
Die Firewall können Sie mit folgendem Befehl wiederherstellen:
|
||||
```bash
|
||||
iptables-restore myTables.txt
|
||||
```
|
||||
|
||||
6. Studieren Sie `MrTimeDaemon.c`, `Daemonizer.c` und `TimeDaemon.c` und analysieren Sie, wie die Daemonisierung abläuft. Entfernen Sie die Kommentare im Macro `Out-PutPIDs` am Anfang des Moduls `Daemonizer.c`. Übersetzen Sie die Programme mit make und starten Sie `MrTimeDaemon` erneut. Analysieren Sie die Ausgabe, was fällt Ihnen auf? Notieren Sie alle für die vollständige Daemonisierung notwendigen Schritte.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
7. Setzen Sie beim Aufruf von `Daemonizer()` in `MrTimeDaemon.c` anstelle von `lock-FilePath` den Null-Zeiger `NULL` ein. Damit wird keine lock-Datei erzeugt. Übersetzen Sie die Programme und starten Sie erneut `MrTimedaemon`. Was geschieht bzw. wie können Sie feststellen, was geschehen ist?
|
||||
|
||||
**Hinweis:** lesen Sie das log-File: `/tmp/timeDaemon.log.`
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
Wenn Sie noch Zeit und Lust haben: messen Sie die Zeit, zwischen Start der Zeitanfrage und Eintreffen der Antwort. Dazu müssen Sie die Datei `WhatsTheTimeMr.c` entsprechend anpassen.
|
||||
|
||||
___
|
||||
|
||||
#### 3.10.4 Zusatzinformationen
|
||||
___
|
||||
|
||||
##### 3.10.4.1 Diese Implementation
|
||||
|
||||
Dieser Daemon besteht aus den 3 Komponenten.
|
||||
|
||||
**Hauptprogramm: MrTimeDaemon.c**
|
||||
|
||||
Hier werden die Pfade für die lock-Datei, die log-Datei und der ”Aufenthaltsort” des Daemons gesetzt. Die lock-Datei wird benötigt um sicherzustellen, dass der Daemon nur einmal gestartet werden kann. In die lock-Datei schreibt der Daemon z.B. seine PID und sperrt sie dann für Schreiben. Wird der Daemon ein zweites Mal gestartet und will seine PID in diese Datei schreiben, erhält er eine Fehlermeldung und terminiert (es soll ja nur ein Daemon arbeiten). Terminiert der Daemon, wird die Datei automatisch freigegeben. Weil Daemonen sämtliche Kontakte mit ihrer Umwelt im Normalfall abbrechen und auch kein Kontrollterminal besitzen, ist es sinnvoll, zumindest die Ausgabe des Daemons in eine log-Datei umzuleiten. Dazu stehen einige Systemfunktionen für Logging zur Verfügung. Der Einfachheit halber haben wir hier eine normale Datei im Verzeichnis `/tmp` gewählt.
|
||||
|
||||
> **Anmerkung:** die Wahl des Verzeichnisses `/tmp` für die lock- und log-Datei ist für den normalen Betrieb problematisch, weil der Inhalt dieses Verzeichnisses jederzeit gelöscht werden kann, bzw. darf. Wir haben dieses Verzeichnis gewählt, weil wir die beiden Dateien nur für die kurze Zeit des Praktikums benötigen.
|
||||
|
||||
Der Daemon erbt sein Arbeitsverzeichnis vom Elternprozesse, er sollte deshalb in ein festes Verzeichnis des Systems wechseln, um zu verhindern, dass er sich in einem montierten (gemounteten) Verzeichnis aufhält, das dann beim Herunterfahren nicht demontiert werden könnte (wir haben hier wiederum `/tmp` gewählt).
|
||||
|
||||
**Daemonizer: Daemonizer.c**
|
||||
|
||||
Der Daemonizer macht aus dem aktuellen Prozess einen Daemon. Z.B. sollte er Signale (eine Art Softwareinterrupts) ignorieren: wenn Sie die CTRL-C Taste während dem Ausführen eines Vordergrundprozess drücken, erhält dieser vom Betriebssystem das Signal SIGINT und bricht seine Ausführung ab. Weiter sollte er die Dateierzeugungsmaske auf 0 setzen (Dateizugriffsrechte), damit kann er beim Öffnen von Dateien beliebige Zugriffsrechte verlangen (die Dateierzeugungsmaske erbt er vom Elternprozess). Am Schluss startet der Daemonizer das eigentliche Daemonprogramm: TimeDaemon.e.
|
||||
|
||||
**Daemonprogramm: TimeDaemon.c**
|
||||
|
||||
Das Daemonprogramm wartet in einer unendlichen Schleife auf Anfragen zur Zeit und schickt die Antwort an den Absender zurück. Die Datenkommunikation ist, wie schon erwähnt, mit Sockets implementiert, auf die wir aber im Rahmen dieses Praktikums nicht weiter eingehen wollen (wir stellen lediglich Hilfsfunktionen zur Verfügung).
|
||||
___
|
||||
|
||||
##### 3.10.4.2 Zusatzinformation zu Dämon Prozessen
|
||||
|
||||
Dämonen oder englisch Daemons sind eine spezielle Art von Prozessen, die vollständig unabhängig arbeiten, d.h. ohne direkte Interaktion mit dem Anwender. Dämonen sind Hintergrundprozesse und terminieren i.A. nur, wenn das System heruntergefahren wird oder abstürzt. Dämonen erledigen meist Aufgaben, die periodisch ausgeführt werden müssen, z.B. Überwachung von Systemkomponenten, abfragen, ob neue Mails angekommen sind, etc.
|
||||
|
||||
Ein typisches Beispiel unter Unix ist der Printer Daemon `lpd`, der periodisch nachschaut, ob ein Anwender eine Datei zum Ausdrucken hinterlegt hat. Wenn ja, schickt er die Datei auf den Drucker.
|
||||
|
||||
Hier wird eine weitere Eigenschaft von Daemons ersichtlich: meist kann nur ein Dämon pro Aufgabe aktiv sein: stellen Sie sich vor, was passiert, wenn zwei Druckerdämonen gleichzeitig arbeiten. Andererseits muss aber auch dafür gesorgt werden, dass ein Dämon wieder gestartet wird, falls er stirbt.
|
||||
|
||||
___
|
||||
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 4. Bewertung
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
| Aufgabe | Kriterium | Punkte |
|
||||
| :-- | :-- | :-- |
|
||||
| | Sie können die gestellten Fragen erklären. | |
|
||||
| 1 | Prozess mit `fork()` erzeugen | 0.5 |
|
||||
| 2 | Prozess mit `fork()` und `exec()`: Programm Image ersetzen | 0.5 |
|
||||
| 3 | Prozesshierarchie analysieren | 0.5 |
|
||||
| 4 | Zeitlicher Ablauf von Prozessen | 0.5 |
|
||||
| 5 | Waisenkinder (Orphan Processes) | 0.5 |
|
||||
| 6 | Terminierte, halbtote Prozesse (Zombies) | 0.5 |
|
||||
| 7 | Auf Terminieren von Kindprozessen warten | 0.5 |
|
||||
| 8 | Kindprozess als Kopie des Elternprozesses | 0.5 |
|
||||
| 9 | Unterschied von Threads gegenüber Prozessen | 0.5 |
|
||||
| 10 | Dämon Prozesse | (4) |
|
||||
|
||||
|
||||
___
|
||||
Version: 11.01.2022
|
||||
@@ -0,0 +1,149 @@
|
||||
# 09/02 - Dämon Prozesse
|
||||
|
||||
___
|
||||
|
||||

|
||||
|
||||
___
|
||||
|
||||
## 1. Übersicht
|
||||
Dieser Teil des Praktikums behandelt spezielle Prozesse: die Dämon Prozesse («daemon pro-cesses»). Es ist gedacht als Zusatz zum Basis Praktikum über Prozesse und Threads.
|
||||
|
||||
Auch dieser Teil ist ein «Analyse»- und «Experimentier»-Praktikum.
|
||||
|
||||
|
||||
___
|
||||
|
||||
### 1.1 Nachweis
|
||||
Dieses Praktikum ist eine leicht abgewandelte Variante des ProcThreads Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.
|
||||
|
||||
Als Autoren des BSY Praktikums sind genannt: M. Thaler, J. Zeman.
|
||||
|
||||
___
|
||||
|
||||
## 2. Lernziele
|
||||
In diesem Praktikum werden Sie sich mit Dämon Prozessen beschäftigen.
|
||||
* Sie können die Problemstellung der Dämon Prozesse erklären
|
||||
* Sie können einen Dämon Prozess kreieren
|
||||
* Sie können aus dem Dämon Prozess mit der Umgebung kommunizieren
|
||||
*
|
||||
___
|
||||
|
||||
## 3. Aufgabe: Dämon Prozesse
|
||||
|
||||
**Ziele**
|
||||
* Problemstellungen um Daemons kennenlernen:
|
||||
* wie wird ein Prozess zum Daemon?
|
||||
* wie erreicht man, dass nur ein Daemon vom gleichen Typ aktiv ist?
|
||||
* wie teilt sich ein Daemon seiner Umwelt mit?
|
||||
* wo "lebt" ein Daemon?
|
||||
|
||||
**Einleitung**
|
||||
|
||||
Für diese Aufgabe haben wir einen Daemon implementiert: **MrTimeDaemon** gibt auf Anfrage die Systemzeit Ihres Rechners bekannt. Abfragen können Sie diese Zeit mit dem Programm `WhatsTheTimeMr localhost`. Die Kommunikation zwischen den beiden Prozessen haben wir mit TCP/IP Sockets implementiert. Weitere Infos zum Daemon finden Sie nach den Aufgaben.
|
||||
|
||||
Im Abschnitt 4 finden Sie Zusatzinformationen über diese Implementation eines Dämon Prozesses plus weiterführende Informationen.
|
||||
|
||||
**Aufgaben**
|
||||
|
||||
1. Für die folgende Aufgabe benötigen Sie mindestens zwei Fenster (Kommandozeilen-Konsolen). Übersetzen Sie die Programme mit `make` und starten Sie das Programm **PlapperMaul** in einem der Fenster. Das Programm schreibt (ca.) alle 0.5 Sekunden *Hallo, ich bins.... Pidi* plus seine Prozess-ID auf den Bildschirm. Mit dem Shell Befehl `ps` können Sie Ihre aktiven Prozesse auflisten, auch **PlapperMaul**. Überlegen Sie sich zuerst, was mit **PlapperMaul** geschieht, wenn Sie das Fenster schliessen: läuft **PlapperMaul** weiter? Was geschieht mit **PlapperMaul** wenn Sie sich ausloggen und wieder einloggen? Testen Sie Ihre Überlegungen, in dem Sie die entsprechenden Aktionen durchführen. Stimmen Ihre Überlegungen?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
2. Starten Sie nun das Programm bzw. den Daemon **MrTimeDaemon**. Stellen Sie die gleichen Überlegungen an wie mit **PlapperMaul** und testen Sie wiederum, ob Ihre Überlegungen stimmen. Ob **MrTimeDaemon** noch läuft können Sie feststellen, indem Sie die Zeit abfragen oder den Befehl `ps ajx | grep MrTimeDaemon` eingeben: was fällt Ihnen am Output auf? Was schliessen Sie aus Ihren Beobachtungen?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
3. Starten Sie **MrTimeDaemon** erneut, was geschieht?
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
4. Stoppen Sie nun **MrTimeDaemon** mit `killall MrTimeDaemon`.
|
||||
5. Starten Sie **MrTimeDaemon** und fragen Sie mit `WhatsTheTimeMr localhost` oder mit `WhatsTheTimeMr 127.0.0.1` die aktuelle Zeit auf Ihrem Rechner ab.
|
||||
|
||||
|
||||
**Optional:**
|
||||
Fragen Sie die Zeit bei einem Ihrer Kollegen ab. Dazu muss beim Server (dort wo **MrTimeDaemon** läuft) ev. die Firewall angepasst werden. Folgende Befehle müssen dazu mit **root-Privilegien** ausgeführt werden:
|
||||
|
||||
```bash
|
||||
iptables-save > myTables.txt # sichert die aktuelle Firewall
|
||||
iptables -I INPUT 1 -p tcp --dport 65534 -j ACCEPT
|
||||
iptables -I OUTPUT 2 -p tcp --sport 65534 -j ACCEPT
|
||||
```
|
||||
|
||||
Nun sollten Sie über die IP-Nummer oder über den Rechner-Namen auf den **TimeServer** mit `WhatsTheTimeMr` zugreifen können.
|
||||
Die Firewall können Sie mit folgendem Befehl wiederherstellen:
|
||||
```bash
|
||||
iptables-restore myTables.txt
|
||||
```
|
||||
|
||||
6. Studieren Sie `MrTimeDaemon.c`, `Daemonizer.c` und `TimeDaemon.c` und analysieren Sie, wie die Daemonisierung abläuft. Entfernen Sie die Kommentare im Macro `Out-PutPIDs` am Anfang des Moduls `Daemonizer.c`. Übersetzen Sie die Programme mit make und starten Sie `MrTimeDaemon` erneut. Analysieren Sie die Ausgabe, was fällt Ihnen auf? Notieren Sie alle für die vollständige Daemonisierung notwendigen Schritte.
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
7. Setzen Sie beim Aufruf von `Daemonizer()` in `MrTimeDaemon.c` anstelle von `lock-FilePath` den Null-Zeiger `NULL` ein. Damit wird keine lock-Datei erzeugt. Übersetzen Sie die Programme und starten Sie erneut `MrTimedaemon`. Was geschieht bzw. wie können Sie feststellen, was geschehen ist?
|
||||
|
||||
**Hinweis:** lesen Sie das log-File: `/tmp/timeDaemon.log.`
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
|
||||
Wenn Sie noch Zeit und Lust haben: messen Sie die Zeit, zwischen Start der Zeitanfrage und Eintreffen der Antwort. Dazu müssen Sie die Datei `WhatsTheTimeMr.c` entsprechend anpassen.
|
||||
|
||||
___
|
||||
|
||||
## 4. Zusatzinformationen
|
||||
___
|
||||
|
||||
### 4.1 Diese Implementation
|
||||
|
||||
Dieser Daemon besteht aus den 3 Komponenten.
|
||||
|
||||
**Hauptprogramm: MrTimeDaemon.c**
|
||||
|
||||
Hier werden die Pfade für die lock-Datei, die log-Datei und der ”Aufenthaltsort” des Daemons gesetzt. Die lock-Datei wird benötigt um sicherzustellen, dass der Daemon nur einmal gestartet werden kann. In die lock-Datei schreibt der Daemon z.B. seine PID und sperrt sie dann für Schreiben. Wird der Daemon ein zweites Mal gestartet und will seine PID in diese Datei schreiben, erhält er eine Fehlermeldung und terminiert (es soll ja nur ein Daemon arbeiten). Terminiert der Daemon, wird die Datei automatisch freigegeben. Weil Daemonen sämtliche Kontakte mit ihrer Umwelt im Normalfall abbrechen und auch kein Kontrollterminal besitzen, ist es sinnvoll, zumindest die Ausgabe des Daemons in eine log-Datei umzuleiten. Dazu stehen einige Systemfunktionen für Logging zur Verfügung. Der Einfachheit halber haben wir hier eine normale Datei im Verzeichnis `/tmp` gewählt.
|
||||
|
||||
> **Anmerkung:** die Wahl des Verzeichnisses `/tmp` für die lock- und log-Datei ist für den normalen Betrieb problematisch, weil der Inhalt dieses Verzeichnisses jederzeit gelöscht werden kann, bzw. darf. Wir haben dieses Verzeichnis gewählt, weil wir die beiden Dateien nur für die kurze Zeit des Praktikums benötigen.
|
||||
|
||||
Der Daemon erbt sein Arbeitsverzeichnis vom Elternprozesse, er sollte deshalb in ein festes Verzeichnis des Systems wechseln, um zu verhindern, dass er sich in einem montierten (gemounteten) Verzeichnis aufhält, das dann beim Herunterfahren nicht demontiert werden könnte (wir haben hier wiederum `/tmp` gewählt).
|
||||
|
||||
**Daemonizer: Daemonizer.c**
|
||||
|
||||
Der Daemonizer macht aus dem aktuellen Prozess einen Daemon. Z.B. sollte er Signale (eine Art Softwareinterrupts) ignorieren: wenn Sie die CTRL-C Taste während dem Ausführen eines Vordergrundprozess drücken, erhält dieser vom Betriebssystem das Signal SIGINT und bricht seine Ausführung ab. Weiter sollte er die Dateierzeugungsmaske auf 0 setzen (Dateizugriffsrechte), damit kann er beim Öffnen von Dateien beliebige Zugriffsrechte verlangen (die Dateierzeugungsmaske erbt er vom Elternprozess). Am Schluss startet der Daemonizer das eigentliche Daemonprogramm: TimeDaemon.e.
|
||||
|
||||
**Daemonprogramm: TimeDaemon.c**
|
||||
|
||||
Das Daemonprogramm wartet in einer unendlichen Schleife auf Anfragen zur Zeit und schickt die Antwort an den Absender zurück. Die Datenkommunikation ist, wie schon erwähnt, mit Sockets implementiert, auf die wir aber im Rahmen dieses Praktikums nicht weiter eingehen wollen (wir stellen lediglich Hilfsfunktionen zur Verfügung).
|
||||
___
|
||||
|
||||
### 4.2 Zusatzinformation zu Dämon Prozessen
|
||||
|
||||
Dämonen oder englisch Daemons sind eine spezielle Art von Prozessen, die vollständig unabhängig arbeiten, d.h. ohne direkte Interaktion mit dem Anwender. Dämonen sind Hintergrundprozesse und terminieren i.A. nur, wenn das System heruntergefahren wird oder abstürzt. Dämonen erledigen meist Aufgaben, die periodisch ausgeführt werden müssen, z.B. Überwachung von Systemkomponenten, abfragen, ob neue Mails angekommen sind, etc.
|
||||
|
||||
Ein typisches Beispiel unter Unix ist der Printer Daemon `lpd`, der periodisch nachschaut, ob ein Anwender eine Datei zum Ausdrucken hinterlegt hat. Wenn ja, schickt er die Datei auf den Drucker.
|
||||
|
||||
Hier wird eine weitere Eigenschaft von Daemons ersichtlich: meist kann nur ein Dämon pro Aufgabe aktiv sein: stellen Sie sich vor, was passiert, wenn zwei Druckerdämonen gleichzeitig arbeiten. Andererseits muss aber auch dafür gesorgt werden, dass ein Dämon wieder gestartet wird, falls er stirbt.
|
||||
|
||||
___
|
||||
|
||||
## 5. Bewertung
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
| Aufgabe | Kriterium | Punkte |
|
||||
| :-- | :-- | :-- |
|
||||
| | Sie können die gestellten Fragen erklären. | |
|
||||
| 1 | Dämon Prozesse | 4 |
|
||||
|
||||
|
||||
___
|
||||
Version: 11.01.2022
|
||||
@@ -0,0 +1,187 @@
|
||||
# 08 - Synchronisationsprobleme
|
||||
|
||||
___
|
||||
|
||||
## 1. Übersicht
|
||||
|
||||

|
||||
|
||||
[Quelle: https://commons.wikimedia.org/wiki/File:Velgast-suedbahn.jpg](https://commons.wikimedia.org/wiki/File:Velgast-suedbahn.jpg)
|
||||
|
||||
In diesem Praktikum lernen sie zuerst am Beispiel eines Kaffee-Automaten verschiedene grundlegende Synchronisationsprobleme kennen und mit Hilfe von Locks (Mutexes) und Semaphoren lösen:
|
||||
- gegenseitiger Ausschluss mit einem Lock
|
||||
- Erzwingen einer einfachen Reihenfolge
|
||||
- Erzwingen einer erweiterten Reihenfolge
|
||||
|
||||
Im zweiten Teil werden sie auf Basis dieser Grundlagen ein komplexeres Synchronisationsproblem bearbeiten, diesmal am Beispiel von Bank Transaktionen.
|
||||
___
|
||||
|
||||
### 1.1 Nachweis
|
||||
Dieses Praktikum ist eine leicht abgewandelte Variante des Sync Praktikum des Moduls BSY, angepasst an die Verhältnisse des SNP Moduls. Die Beispiele und Beschreibungen wurden, wo möglich, eins-zu-ein übernommen.
|
||||
|
||||
Als Autor des BSY Praktikums ist genannt: M. Thaler.
|
||||
|
||||
___
|
||||
|
||||
## 2. Lernziele
|
||||
In diesem Praktikum werden sie Synchronisationsprobleme lösen
|
||||
- Sie wissen wie man systematisch Synchronisationsprobleme analysiert
|
||||
- Sie wissen wann ein potentieller Deadlock entstehen kann
|
||||
- Sie können Mutex mit Threads anwenden
|
||||
- Sie können Semaphoren mit Prozessen anwenden
|
||||
|
||||
___
|
||||
|
||||
## 3. Einführung
|
||||
Das Lösen von Synchronisationsproblemen ist oft nicht einfach, weil Prozesse bzw. Threads gleichzeitig ablaufen, ihre Aktivitäten jedoch nach Vorgaben koordiniert werden müssen: man verliert schnell den Überblick. Systematisches Vorgehen mit Aufzeichnen der Abläufe und Synchronisationsbedingungen bewährt ich sich in diesem Fall.
|
||||
|
||||
___
|
||||
|
||||
### 3.1 Wie löst man Synchronisationsprobleme?
|
||||
Gehen sie beim Lösen von Synchronisationsproblemen in folgenden Schritten vor:
|
||||
|
||||
- **Schritt 1: Prozesse (Threads) der Problemstellung identifizieren.**
|
||||
Prozesse sind die Aktivitäten, die gleichzeitig ausgeführt werden. In diesem Sinne sind sie eigenständige Ausführungs-Einheiten, deren zeitliches Verhalten synchronisiert werden muss.
|
||||
- **Schritt 2: Ausführungsschritte der einzelnen Prozesse (Threads) ermitteln.**
|
||||
Erstellen sie eine Liste mit einer Spalte für jeden Prozess. Notieren sie für jeden Prozess stichwortartig die wesentlichen Aktionen in der gewünschten zeitlichen Reihenfolge. Tragen sie noch keine Synchronisationsoperationen ein, sondern Texte wie warten auf Geld, etc. Übertragen sie anschliessend die Liste in einen Ablaufgraphen (Siehe Beispiel in Abbildung 1).
|
||||
- **Schritt 3: Synchronisationsbedingungen ermitteln.**
|
||||
Eine Synchronisationsbedingung ist eine zeitliche Beziehung (Abhängigkeit) zwischen Aktionen verschiedener Prozesse, die für das korrekte Arbeiten erforderlich ist. Zeichnen sie diese Beziehungen mit Pfeilen in den Ablaufgraphen aus Schritt 2 ein (Siehe Abbildung 1).
|
||||
- **Schritt 4: Benötigte Semaphore definieren.**
|
||||
Für jede Synchronisationsbedingung wird ein eigener Semaphor benötigt. Notieren sie für jeden Semaphor einen Namen und den Wert, mit dem er initialisiert werden muss.
|
||||
- **Schritt 5: Prozesse mit Semaphore Operationen ergänzen.**
|
||||
Erweitern sie nun alle Prozesse aus Schritt 2 mit den notwendigen Semaphore Operati-onen (Siehe Pseudocode in Abbildung 1).
|
||||
- **Schritt 6: Implementation.**
|
||||
Implementieren und testen sie das vollständige Programm.
|
||||
|
||||

|
||||
|
||||
|
||||
```c
|
||||
coin = sem_open(...,0);
|
||||
coffee = sem_open(...,0);
|
||||
```
|
||||
|
||||
Ablaufgraph und Pseudocode für 2 Prozesse und zwei Semaphore
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
## 4. Der Kaffee-Automat
|
||||
Als Beispiel verwenden wir einen Automaten, der Kaffee verkauft. Der Kunde muss zum Kauf eines Kaffees zuerst eine bzw. mehrere Münzen einwerfen und anschliessend den gewünsch-ten Kaffee wählen. Der Automat gibt dann das entsprechende Getränk aus.
|
||||
|
||||
Im ersten Beispiel werden der Automat und die Kunden mit Threads modelliert und tauschen Daten über gemeinsame Speichervariablen aus. Im zweiten und dritten Beispiel werden der Automat und die Kunden mit Prozessen modelliert, dabei wird der Ablauf mit Hilfe von Sema-phoren gesteuert bzw. erzwungen.
|
||||
|
||||
**Hinweis:** die Programme zu den folgenden Aufgaben können alle mit **startApp.e** gestartet werden. Dieses Programm startet und stoppt Threads und Prozesse, alloziert und dealloziert die Ressourcen (Mutexes, Semaphore).
|
||||
|
||||
___
|
||||
|
||||
### 4.1 Aufgabe: Mutual Exclusion
|
||||
Greifen mehrere Threads (oder Prozesse) auf gemeinsame Daten zu, können sogenannte Race Conditions entstehen. Das Resultat ist in diesem Fall abhängig von der Reihenfolge, in der die Threads (Prozesse) ausgeführt werden.
|
||||
|
||||
Im vorliegenden Beispiel wirft der Kunde eine 1 Euro Münze ein und drückt anschliessend auf eine von zwei Kaffeewahltasten. Dabei wird die Anzahl Münzen (*coinCount*) und die gewählte Kaffeesorte (*selCount1*, *selCount2*) inkrementiert. Diese Variablen sind in der Datenstruktur *cData* abgelegt, auf die gemeinsam Kaffee-Automat und Kunden zugreifen können. Der Auto-mat überprüft, ob die Anzahl Münzen und die Anzahl der Kaffeewahlen gleich gross sind, falls nicht, wird eine Fehlermeldung ausgegeben und alle Zähler auf *Null* gesetzt.
|
||||
|
||||
#### Aufgaben
|
||||
|
||||
1. Übersetzen sie die Programme im Verzeichnis *mutex* mit *make* und starten sie den Kaffee-Automaten mit **startApp.e** mehrmals hintereinander.
|
||||
Analysieren sie die Datenwerte in den Fehlermeldungen, beschreiben sie was die Gründe dafür sind bzw. sein können.
|
||||
|
||||
2. Schützen sie nun den Zugriff auf die gemeinsamen Daten mit einem Mutex so, dass alle Threads eine konsistente Sicht der Daten haben.
|
||||
Wir haben für sie einen Mutex vorbereitet: die Datenstruktur *cData* enthält die Mutex-Variable *mutex*, die in **startApp.c** initialisiert wird. Die Funktionen für das Schliessen und das Öffnen des Mutex (Locks) aus der *pthread* Bibliothek sind:
|
||||
```c
|
||||
pthread mutex lock(&(cD->lock));
|
||||
```
|
||||
- und
|
||||
```c
|
||||
pthread mutex unlock(&(cD->lock));
|
||||
```
|
||||
Überprüfen sie, ob der Kaffee-Automat nun keine Fehlermeldungen mehr ausgibt. Erhö-hen sie dazu auch die Anzahl Kunden *CUSTOMERS* in **commonDefs.h**, z.B. auf 10.
|
||||
|
||||
3. Im Thread des Kaffee-Automaten wird an verschiedenen Orten mehrmals auf die gemeinsamen Daten in *cD* zugegriffen. Wenn sie die gemeinsamen Daten in lokale Variablen kopieren und dann nur noch auf diese lokalen Variablen zugreifen würden, könn-ten sie dann auf die Synchronisation mit dem Mutex verzichten?
|
||||
|
||||
4. Wie oft kann ein einzelner Kunde einen Kaffee beziehen, bis der nächste Kunde an die Reihe kommt? Hier reicht eine qualitative Aussage.
|
||||
|
||||
### 4.2 Aufgabe: Einfache Reihenfolge
|
||||
Wie sie im ersten Beispiel festgestellt haben, verhindert ein Mutex zwar, dass Race Conditions auftreten, die Verarbeitungsreihenfolge der Threads lässt sich jedoch nicht beeinflussen und ist zufällig.
|
||||
Im Folgenden soll eine erzwungene Verarbeitungsreihenfolge implementiert werden:
|
||||
- Ein Kunde benutzt den Automat für einen Kaffeekauf exklusiv, d.h. alle Schritte des Kunden werden innerhalb eines Mutexes ausgeführt. Ist ein Kunde an der Reihe, wartet er bis der Automat bereit ist, wirft eine Münze ein, wartet auf den Kaffee und gibt anschlies-send den Automaten für den nächsten Kunden frei.
|
||||
|
||||
- Der Automat meldet zuerst in einer Endlos-Schleife, dass er für die Geld-Eingabe bereit ist, wartet dann auf die Eingabe einer Münze, gibt den Kaffee aus und meldet anschliessend wieder, wenn er bereit ist, etc.
|
||||
|
||||
Für die Lösung dieses Problems benötigen wir Semaphore, die, im Gegensatz zu Mutexes, auch in verschiedenen Prozessen gesetzt bzw. zurückgesetzt werden dürfen. Den Kaffee-Automat und die Kunden implementieren wir mit Prozessen. sie finden die entsprechenden Prozesse im Verzeichnis **basicSequence**.
|
||||
|
||||
#### Aufgaben
|
||||
1. Beschreiben sie den Kaffee-Automaten mit Hilfe der 6 Schritte aus Abschnitt 3 auf Papier, dokumentieren sie dabei alle Schritte schriftlich.
|
||||
2. Implementieren sie nun den Kaffee-Automaten. Ergänzen sie dazu den *coffeeTeller* und den *customer* Prozess so mit vier Semaphoren, dass die vorgegebenen Ablaufbedingungen eingehalten werden. Mit welchen Werten müssen die Semaphore initialisiert werden?
|
||||
Wir haben für sie vier Semaphore vorbereitet: Achtung, sie sind aber noch auskommentiert (siehe commonDefs.h und startApp.c. Die benötigten Semaphor-Funktionen aus der POSIX Bibliothek sind:
|
||||
```c
|
||||
sem_wait(&semaphor);
|
||||
```
|
||||
und
|
||||
```c
|
||||
sem_post(&semaphor);
|
||||
```
|
||||
Analysieren sie die Ausgabe der Prozesse (mehrmals starten). Was fällt auf?
|
||||
|
||||
3. Gibt Ihr Programm den Output in der korrekten Reihenfolge aus? Falls nicht, wie könnte das gelöst werden?
|
||||
|
||||
### 4.3 Aufgabe: Erweiterte Reihenfolge
|
||||
Die Preise steigen dauernd ... auch der Kaffee wird immer teurer, er kostet nun 3 Euro. Da der Automat nur 1 Euro Stücke annehmen kann, muss der Kunde 3 Münzen einwerfen. Erweitern sie die Prozesse aus Aufgabe 4.2 so, dass eine vordefinierte Anzahl Münzen eingegeben werden muss (die Anzahl Münzen ist in *commonDefs.h* als *NUM_COINS* definiert). Verwenden sie keine zusätzlichen Semaphore, sondern nutzen sie, dass wir Counting Semaphore verwenden. Die vordefinierten Prozesse finden sie im Verzeichnis *advancedSequence*.
|
||||
#### Aufgabe
|
||||
- Passen sie den coffeeTeller und den customer Prozess so an, dass der Kunde mehrere Münzen einwerfen muss, bis der Automat einen Kaffee ausgeben kann.
|
||||
|
||||
**Hinweis:** POSIX Semaphore sind Counting Semaphore, können aber nicht auf vordefinierte Werte gesetzt werden (ausser bei der Initialisierung). Abhilfe schafft hier das mehrmalige Aufrufen von *sem_post()*, z.B. in einer for-Schleife.
|
||||
|
||||
### 4.4 Zusammenfassung
|
||||
Wir haben drei grundlegenden Typen von Synchronisationsproblemen kennen gelernt:
|
||||
- **Mutex** nur ein Prozess bzw. Thread kann gleichzeitig auf gemeinsame Daten zugreifen.
|
||||
- Beispiel: entweder liest der Kaffee-Automat die Daten oder ein Kunde verändert sie.
|
||||
- **Einfache Reihenfolge** ein Prozess wartet auf die Freigabe durch einen anderen Prozess.
|
||||
- Beispiel: der Kaffee-Automat wartet auf die Eingabe einer Münze.
|
||||
- **Erweiterte Reihenfolge** ein Prozess wartet auf mehrere Freigaben durch einen anderen Pro-zess.
|
||||
- Beispiel: der Kaffee-Automat wartet auf die Eingabe von drei Münzen.
|
||||
|
||||
___
|
||||
|
||||
## 5. International Banking
|
||||
Die International Bank of Transfer (IBT) besitzt in 128 Ländern Filialen und stellt für 2048 spezielle Handels-Kunden in jeder Filiale ein Konto zur Verfügung. Gelder dieser Kunden werden dauernd zwischen den Filialen hin und her transferiert, dazu beschäftigt die Bank sogenannte Pusher. Pusher heben Geldbeträge von Konten in einer Filiale ab und buchen sie auf den entsprechenden Konten in irgendeiner (auch in der eigenen) Filiale wieder ein. Die Beträge liegen zwischen 1000 und 100’000 Dollar und werden zufällig ausgewählt, die Wahl der beiden Filialen ist ebenfalls zufällig.
|
||||
|
||||
### 5.1 Implementation
|
||||
Im Folgenden arbeiten wir mit einer *pthread*-basierten Implementation der IBT, die Pusher werden dabei mit Threads implementiert. Die Filialen der Bank sind als Array von Strukturen implementiert, wobei pro Filiale ein Lock (*branchLock*) und ein Array von Konten (Accounts) definiert ist. Die Konten sind wiederum Strukturen mit dem Kontostand (*account*) und dem Lock (*acntLock*), siehe dazu auch den Source Code. Die Zugriffe auf die Gelder sind imple-mentiert (Funktionen *withdraw()*, *deposit()*, *transfer()*), aber nicht synchronisiert.
|
||||
**Hinweis:** es ist von Vorteil hier mit mehreren CPUs zu arbeiten. Falls sie eine VM verwenden, setzen sie die Anzahl CPUs auf das Maximum.
|
||||
|
||||
|
||||
### 5.2 Aufgabe: Konto Synchronisation
|
||||
1. Wechseln sie ins Verzeichnis **banking/a1**, übersetzen sie das Programm und starten sie es mit dem Skript `./startApp`. Analysieren und erklären sie die Resultate. Notie-ren sie sich zudem die Laufzeiten für 1, 2 und 4 Threads.
|
||||
2. Synchronisieren sie die Kontenzugriffe so, dass möglichst viele Zugriffe gleichzeitig ausgeführt werden können und die Zugriffe atomar sind. Sie dürfen nur eines der beiden Locks *branchLock* bzw. *acntLock* verwenden: welches wählen sie und wieso? Be-gründen sie ihre Antwort und testen sie ihre Lösung.
|
||||
|
||||
### 5.3 Aufgabe: Filialen Zugriff in Critical Section
|
||||
Ihr Chef meint, dass es wohl aus Sicherheitsgründen besser wäre, sowohl die Filialen und die jeweiligen Kontenzugriffen zu ”locken”.
|
||||
1. Wechseln sie ins Verzeichnis banking/a2 und kopieren sie banking.c aus Aufgabe 5.2. Implementieren sie diese zusätzlichen Anforderungen. Analysieren sie die Resultate. Was stellen sie fest im Vergleich mit den Resultaten aus der Aufgabe 5.2? Was raten sie ihrem Chef?
|
||||
2. Ein Kollege meint, es wäre effizienter beim Abheben des Betrags zuerst das Konto zu locken und dann die Filiale, hingegen beim Einbuchen zuerst die die Filiale und dann das Konto. Was für eine Antwort geben sie ihrem Kollegen?**Hinweis:** falls sie nicht sicher sind: probieren sie es aus.
|
||||
|
||||
### 5.4 Aufgabe: Refactoring der Synchronisation
|
||||
Das International Banking Committe (IBC) erlässt neue Richtlinien, die unter anderem fordern, dass die Gesamtbilanz einer Bank über sämtliche Filialen zu jeder Zeit konsistent sein muss.
|
||||
1. Erklären sie wieso die Implementationen aus Aufgabe 5.2 und 5.3 diese Anforderungen nicht erfüllen.
|
||||
2. Ihr Entwicklungsteam kommt zum Schluss, dass den Pushern neu nur noch eine Funktion *transfer()* für die Überweisung von Beträgen zwischen den Filialen und Konten zur Verfügung gestellt werden darf.
|
||||
Welche Locks bzw. welches Lock muss verwendet werden, damit die Forderung des IBC erfüllt werden kann? Wechseln sie ins Verzeichnis *banking/a3* und ergänzen sie die Funktion *transfer()* in banking.c um die entsprechenden Lock-Funktionen.
|
||||
Wichtiger
|
||||
**Hinweis:** es darf kein neues Lock eingeführt werden und die Gesamtbilanz über sämtliche Filialen muss jederzeit konsistent sein.
|
||||
3. Testen und analysieren sie das Programm und vergleichen sie die Resultate (Funktionalität, Laufzeit) mit den Lösungen aus Aufgabe 5.2 und 5.3. Notieren sie sich, was ihnen bei dieser Aufgabe wichtig erscheint.
|
||||
4.
|
||||
___
|
||||
|
||||
|
||||
## 6. Bewertung
|
||||
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
| Aufgabe | Kriterium | Gewicht |
|
||||
| :-- | :-- | :-- |
|
||||
| | Sie können die gestellten Fragen erklären. | |
|
||||
| 4 | 4.1 Aufgabe: Mutual Exclusion<br>4.2 Aufgabe: Einfache Reihenfolge<br>4.3 Aufgabe: Erweiterte Reihenfolge | 4 |
|
||||
| 5 | 5.2 Aufgabe: Konto Synchronisation<br>5.3 Aufgabe: Filialen Zugriff in Critical Section<br>5.4 Aufgabe: Refactoring der Synchronisation | 4 |
|
||||
|
||||
|
||||
___
|
||||
___
|
||||
Version: 18.08.2021
|
||||
@@ -0,0 +1,34 @@
|
||||
# 09 - File Operations
|
||||
|
||||
___
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 1. Übersicht
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 2. Lernziele
|
||||
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 3. Aufgabe 1:
|
||||
|
||||
___
|
||||
|
||||
## 4. Bewertung
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
| Aufgabe | Kriterium | Punkte |
|
||||
| :-- | :-- | :-- |
|
||||
| | Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären. | |
|
||||
| 1 | - | - |
|
||||
|
||||
|
||||
|
||||
___
|
||||
Version: 16.02.2022
|
||||
@@ -0,0 +1,31 @@
|
||||
# 10 - IPC
|
||||
|
||||
___
|
||||
|
||||
## 1. Übersicht
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 2. Lernziele
|
||||
|
||||
|
||||
|
||||
___
|
||||
|
||||
## 3. Aufgabe 1:
|
||||
|
||||
___
|
||||
|
||||
## 4. Bewertung
|
||||
Die gegebenenfalls gestellten Theorieaufgaben und der funktionierende Programmcode müssen der Praktikumsbetreuung gezeigt werden. Die Lösungen müssen mündlich erklärt werden.
|
||||
|
||||
| Aufgabe | Kriterium | Punkte |
|
||||
| :-- | :-- | :-- |
|
||||
| | Sie können das funktionierende Programm inklusive funktionierende Tests demonstrieren und erklären. | |
|
||||
| 1 | - | - |
|
||||
|
||||
|
||||
|
||||
___
|
||||
Version: 16.02.2022
|
||||
@@ -0,0 +1,26 @@
|
||||
.. demo documentation master file, created by
|
||||
sphinx-quickstart on Wed Feb 9 08:17:44 2022.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:caption: Contents:
|
||||
|
||||
|
||||
SNP Laboratories
|
||||
----------------------------------
|
||||
|
||||
.. toctree::
|
||||
P01_Erste_Schritte_mit_C/README.md
|
||||
P02_Funktionen_Datentyp_enum/README.md
|
||||
P03_Bit_Operation_struct_typedef/README.md
|
||||
P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.md
|
||||
P05_TicTacToe/README.md
|
||||
P06_Personen_Verwaltung_Linked_List/README.md
|
||||
P07_Prozesse_und_Threads/README.md
|
||||
P08_Sync/README.md
|
||||
P09_File_Operations/README.md
|
||||
P10_IPC/README.md
|
||||
|
||||
@@ -0,0 +1,701 @@
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: Georgia, serif;
|
||||
font-size: 17px;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
div.document {
|
||||
width: 940px;
|
||||
margin: 30px auto 0 auto;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 220px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
width: 220px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #fff;
|
||||
color: #3E4349;
|
||||
padding: 0 30px 0 30px;
|
||||
}
|
||||
|
||||
div.body > .section {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
width: 940px;
|
||||
margin: 20px auto 30px auto;
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
p.caption {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
|
||||
div.relations {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 18px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper p.logo {
|
||||
padding: 0;
|
||||
margin: -10px 0 0 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper h1.logo {
|
||||
margin-top: -10px;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper h1.logo-name {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper p.blurb {
|
||||
margin-top: 0;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: Georgia, serif;
|
||||
color: #444;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin: 0 0 5px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo a,
|
||||
div.sphinxsidebar h3 a,
|
||||
div.sphinxsidebar p.logo a:hover,
|
||||
div.sphinxsidebar h3 a:hover {
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #555;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul li.toctree-l1 > a {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul li.toctree-l2 > a {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #CCC;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar hr {
|
||||
border: none;
|
||||
height: 1px;
|
||||
color: #AAA;
|
||||
background: #AAA;
|
||||
|
||||
text-align: left;
|
||||
margin-left: 0;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar .badge {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar .badge:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* To address an issue with donation coming after search */
|
||||
div.sphinxsidebar h3.donation {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #004B6B;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #6D4100;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: Georgia, serif;
|
||||
font-weight: normal;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
|
||||
div.body h2 { font-size: 180%; }
|
||||
div.body h3 { font-size: 150%; }
|
||||
div.body h4 { font-size: 130%; }
|
||||
div.body h5 { font-size: 100%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #DDD;
|
||||
padding: 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
color: #444;
|
||||
background: #EAEAEA;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
div.admonition {
|
||||
margin: 20px 0px;
|
||||
padding: 10px 30px;
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
|
||||
background-color: #FBFBFB;
|
||||
border-bottom: 1px solid #fafafa;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title {
|
||||
font-family: Georgia, serif;
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
div.admonition p.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.highlight {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
dt:target, .highlight {
|
||||
background: #FAF3E8;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
}
|
||||
|
||||
div.danger {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
-moz-box-shadow: 2px 2px 4px #D52C2C;
|
||||
-webkit-box-shadow: 2px 2px 4px #D52C2C;
|
||||
box-shadow: 2px 2px 4px #D52C2C;
|
||||
}
|
||||
|
||||
div.error {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
-moz-box-shadow: 2px 2px 4px #D52C2C;
|
||||
-webkit-box-shadow: 2px 2px 4px #D52C2C;
|
||||
box-shadow: 2px 2px 4px #D52C2C;
|
||||
}
|
||||
|
||||
div.caution {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
}
|
||||
|
||||
div.attention {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
}
|
||||
|
||||
div.important {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.tip {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.hint {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre, tt, code {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.hll {
|
||||
background-color: #FFC;
|
||||
margin: 0 -12px;
|
||||
padding: 0 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname, code.descname, code.descclassname {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
tt.descname, code.descname {
|
||||
padding-right: 0.08em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
-moz-box-shadow: 2px 2px 4px #EEE;
|
||||
-webkit-box-shadow: 2px 2px 4px #EEE;
|
||||
box-shadow: 2px 2px 4px #EEE;
|
||||
}
|
||||
|
||||
table.docutils {
|
||||
border: 1px solid #888;
|
||||
-moz-box-shadow: 2px 2px 4px #EEE;
|
||||
-webkit-box-shadow: 2px 2px 4px #EEE;
|
||||
box-shadow: 2px 2px 4px #EEE;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
border: 1px solid #888;
|
||||
padding: 0.25em 0.7em;
|
||||
}
|
||||
|
||||
table.field-list, table.footnote {
|
||||
border: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table.footnote {
|
||||
margin: 15px 0;
|
||||
width: 100%;
|
||||
border: 1px solid #EEE;
|
||||
background: #FDFDFD;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
table.footnote + table.footnote {
|
||||
margin-top: -15px;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
table.field-list th {
|
||||
padding: 0 0.8em 0 0;
|
||||
}
|
||||
|
||||
table.field-list td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.field-list p {
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
|
||||
/* Cloned from
|
||||
* https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
|
||||
*/
|
||||
.field-name {
|
||||
-moz-hyphens: manual;
|
||||
-ms-hyphens: manual;
|
||||
-webkit-hyphens: manual;
|
||||
hyphens: manual;
|
||||
}
|
||||
|
||||
table.footnote td.label {
|
||||
width: .1px;
|
||||
padding: 0.3em 0 0.3em 0.5em;
|
||||
}
|
||||
|
||||
table.footnote td {
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 0 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
/* Matches the 30px from the narrow-screen "li > ul" selector below */
|
||||
margin: 10px 0 10px 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #EEE;
|
||||
padding: 7px 30px;
|
||||
margin: 15px 0px;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background: #ffd;
|
||||
}
|
||||
|
||||
dl pre, blockquote pre, li pre {
|
||||
margin-left: 0;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
tt, code {
|
||||
background-color: #ecf0f3;
|
||||
color: #222;
|
||||
/* padding: 1px 2px; */
|
||||
}
|
||||
|
||||
tt.xref, code.xref, a tt {
|
||||
background-color: #FBFBFB;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
a.reference {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #004B6B;
|
||||
}
|
||||
|
||||
/* Don't put an underline on images */
|
||||
a.image-reference, a.image-reference:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
a.reference:hover {
|
||||
border-bottom: 1px solid #6D4100;
|
||||
}
|
||||
|
||||
a.footnote-reference {
|
||||
text-decoration: none;
|
||||
font-size: 0.7em;
|
||||
vertical-align: top;
|
||||
border-bottom: 1px dotted #004B6B;
|
||||
}
|
||||
|
||||
a.footnote-reference:hover {
|
||||
border-bottom: 1px solid #6D4100;
|
||||
}
|
||||
|
||||
a:hover tt, a:hover code {
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 870px) {
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
li > ul {
|
||||
/* Matches the 30px from the "ul, ol" selector above */
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.document {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.github {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 875px) {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: block;
|
||||
float: none;
|
||||
width: 102.5%;
|
||||
margin: 50px -30px -20px -30px;
|
||||
padding: 10px 20px;
|
||||
background: #333;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #AAA;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.body {
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rtd_doc_footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.document {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.github {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* misc. */
|
||||
|
||||
.revsys-inline {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
/* Make nested-list/multi-paragraph items look better in Releases changelog
|
||||
* pages. Without this, docutils' magical list fuckery causes inconsistent
|
||||
* formatting between different release sub-lists.
|
||||
*/
|
||||
div#changelog > div.section > ul > li > p:only-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Hide fugly table cell borders in ..bibliography:: directive output */
|
||||
table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
|
||||
border: none;
|
||||
/* Below needed in some edge cases; if not applied, bottom shadows appear */
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/* relbar */
|
||||
|
||||
.related {
|
||||
line-height: 30px;
|
||||
width: 100%;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.related.top {
|
||||
border-bottom: 1px solid #EEE;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.related.bottom {
|
||||
border-top: 1px solid #EEE;
|
||||
}
|
||||
|
||||
.related ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav#rellinks {
|
||||
float: right;
|
||||
}
|
||||
|
||||
nav#rellinks li+li:before {
|
||||
content: "|";
|
||||
}
|
||||
|
||||
nav#breadcrumbs li+li:before {
|
||||
content: "\00BB";
|
||||
}
|
||||
|
||||
/* Hide certain items when printing */
|
||||
@media print {
|
||||
div.related {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,906 @@
|
||||
/*
|
||||
* basic.css
|
||||
* ~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.section::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap : break-word;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox form.search {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="text"] {
|
||||
float: left;
|
||||
width: 80%;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||
float: left;
|
||||
width: 20%;
|
||||
border-left: none;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li p.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
table.indextable > tbody > tr > td > ul {
|
||||
padding-left: 0em;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.modindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
/* -- domain module index --------------------------------------------------- */
|
||||
|
||||
table.modindextable td {
|
||||
padding: 2px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
div.body {
|
||||
min-width: 450px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
a.brackets:before,
|
||||
span.brackets > a:before{
|
||||
content: "[";
|
||||
}
|
||||
|
||||
a.brackets:after,
|
||||
span.brackets > a:after {
|
||||
content: "]";
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink,
|
||||
caption:hover > a.headerlink,
|
||||
p.caption:hover > a.headerlink,
|
||||
div.code-block-caption:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, figure.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, figure.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, figure.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
img.align-default, figure.align-default, .figure.align-default {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-default {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar,
|
||||
aside.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
clear: right;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.admonition, div.topic, blockquote {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||
|
||||
div.sidebar > :last-child,
|
||||
aside.sidebar > :last-child,
|
||||
div.topic > :last-child,
|
||||
div.admonition > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sidebar::after,
|
||||
aside.sidebar::after,
|
||||
div.topic::after,
|
||||
div.admonition::after,
|
||||
blockquote::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-default {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table caption span.caption-text {
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 5px;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.footnote td, table.footnote th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
table.citation td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
th > :first-child,
|
||||
td > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
th > :last-child,
|
||||
td > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* -- figures --------------------------------------------------------------- */
|
||||
|
||||
div.figure, figure {
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.figure p.caption, figcaption {
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-number,
|
||||
figcaption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-text,
|
||||
figcaption span.caption-text {
|
||||
}
|
||||
|
||||
/* -- field list styles ----------------------------------------------------- */
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.field-name {
|
||||
-moz-hyphens: manual;
|
||||
-ms-hyphens: manual;
|
||||
-webkit-hyphens: manual;
|
||||
hyphens: manual;
|
||||
}
|
||||
|
||||
/* -- hlist styles ---------------------------------------------------------- */
|
||||
|
||||
table.hlist {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
table.hlist td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -- object description styles --------------------------------------------- */
|
||||
|
||||
.sig {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
}
|
||||
|
||||
.sig-name, code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sig-name {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.sig-prename, code.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.sig-paren {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.sig-param.n {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* C++ specific styling */
|
||||
|
||||
.sig-inline.c-texpr,
|
||||
.sig-inline.cpp-texpr {
|
||||
font-family: unset;
|
||||
}
|
||||
|
||||
.sig.c .k, .sig.c .kt,
|
||||
.sig.cpp .k, .sig.cpp .kt {
|
||||
color: #0033B3;
|
||||
}
|
||||
|
||||
.sig.c .m,
|
||||
.sig.cpp .m {
|
||||
color: #1750EB;
|
||||
}
|
||||
|
||||
.sig.c .s, .sig.c .sc,
|
||||
.sig.cpp .s, .sig.cpp .sc {
|
||||
color: #067D17;
|
||||
}
|
||||
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:first-child > :first-child,
|
||||
:not(li) > ul > li:first-child > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:last-child > :last-child,
|
||||
:not(li) > ul > li:last-child > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
ol.simple ol p,
|
||||
ol.simple ul p,
|
||||
ul.simple ol p,
|
||||
ul.simple ul p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple > li:not(:first-child) > p,
|
||||
ul.simple > li:not(:first-child) > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple p,
|
||||
ul.simple p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dl.footnote > dt,
|
||||
dl.citation > dt {
|
||||
float: left;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
dl.footnote > dd,
|
||||
dl.citation > dd {
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl.footnote > dd:after,
|
||||
dl.citation > dd:after {
|
||||
content: "";
|
||||
clear: both;
|
||||
}
|
||||
|
||||
dl.field-list {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(30%) auto;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
dl.field-list > dt:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
dl.field-list > dd {
|
||||
padding-left: 0.5em;
|
||||
margin-top: 0em;
|
||||
margin-left: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dl > dd:last-child,
|
||||
dl > dd:last-child > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt:target, span.highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
rect.highlighted {
|
||||
fill: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.guilabel, .menuselection {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.accelerator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.classifier {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
.classifier:before {
|
||||
font-style: normal;
|
||||
margin: 0 0.5em;
|
||||
content: ":";
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
pre, div[class*="highlight-"] {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
span.pre {
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div[class*="highlight-"] {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tbody {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tr {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td.code {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.highlight .hll {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.highlight pre,
|
||||
table.highlighttable pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption + div {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
margin-top: 1em;
|
||||
padding: 2px 5px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div.code-block-caption code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos,
|
||||
span.linenos,
|
||||
div.highlight span.gp { /* gp: Generic.Prompt */
|
||||
user-select: none;
|
||||
-webkit-user-select: text; /* Safari fallback only */
|
||||
-webkit-user-select: none; /* Chrome/Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE10+ */
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-number {
|
||||
padding: 0.1em 0.3em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-text {
|
||||
}
|
||||
|
||||
div.literal-block-wrapper {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
code.xref, a code {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
span.eqno a.headerlink {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.math:hover a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/* This file intentionally left blank. */
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* doctools.js
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx JavaScript utilities for all documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* select a different prefix for underscore
|
||||
*/
|
||||
$u = _.noConflict();
|
||||
|
||||
/**
|
||||
* make the code below compatible with browsers without
|
||||
* an installed firebug like debugger
|
||||
if (!window.console || !console.firebug) {
|
||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||||
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
|
||||
"profile", "profileEnd"];
|
||||
window.console = {};
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
window.console[names[i]] = function() {};
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* small helper function to urldecode strings
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
|
||||
*/
|
||||
jQuery.urldecode = function(x) {
|
||||
if (!x) {
|
||||
return x
|
||||
}
|
||||
return decodeURIComponent(x.replace(/\+/g, ' '));
|
||||
};
|
||||
|
||||
/**
|
||||
* small helper function to urlencode strings
|
||||
*/
|
||||
jQuery.urlencode = encodeURIComponent;
|
||||
|
||||
/**
|
||||
* This function returns the parsed url parameters of the
|
||||
* current request. Multiple values per key are supported,
|
||||
* it will always return arrays of strings for the value parts.
|
||||
*/
|
||||
jQuery.getQueryParameters = function(s) {
|
||||
if (typeof s === 'undefined')
|
||||
s = document.location.search;
|
||||
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||
var result = {};
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var tmp = parts[i].split('=', 2);
|
||||
var key = jQuery.urldecode(tmp[0]);
|
||||
var value = jQuery.urldecode(tmp[1]);
|
||||
if (key in result)
|
||||
result[key].push(value);
|
||||
else
|
||||
result[key] = [value];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* highlight a given string on a jquery object by wrapping it in
|
||||
* span elements with the given class name.
|
||||
*/
|
||||
jQuery.fn.highlightText = function(text, className) {
|
||||
function highlight(node, addItems) {
|
||||
if (node.nodeType === 3) {
|
||||
var val = node.nodeValue;
|
||||
var pos = val.toLowerCase().indexOf(text);
|
||||
if (pos >= 0 &&
|
||||
!jQuery(node.parentNode).hasClass(className) &&
|
||||
!jQuery(node.parentNode).hasClass("nohighlight")) {
|
||||
var span;
|
||||
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
|
||||
if (isInSVG) {
|
||||
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
||||
} else {
|
||||
span = document.createElement("span");
|
||||
span.className = className;
|
||||
}
|
||||
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||
document.createTextNode(val.substr(pos + text.length)),
|
||||
node.nextSibling));
|
||||
node.nodeValue = val.substr(0, pos);
|
||||
if (isInSVG) {
|
||||
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
var bbox = node.parentElement.getBBox();
|
||||
rect.x.baseVal.value = bbox.x;
|
||||
rect.y.baseVal.value = bbox.y;
|
||||
rect.width.baseVal.value = bbox.width;
|
||||
rect.height.baseVal.value = bbox.height;
|
||||
rect.setAttribute('class', className);
|
||||
addItems.push({
|
||||
"parent": node.parentNode,
|
||||
"target": rect});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!jQuery(node).is("button, select, textarea")) {
|
||||
jQuery.each(node.childNodes, function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
}
|
||||
}
|
||||
var addItems = [];
|
||||
var result = this.each(function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
for (var i = 0; i < addItems.length; ++i) {
|
||||
jQuery(addItems[i].parent).before(addItems[i].target);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
* backward compatibility for jQuery.browser
|
||||
* This will be supported until firefox bug is fixed.
|
||||
*/
|
||||
if (!jQuery.browser) {
|
||||
jQuery.uaMatch = function(ua) {
|
||||
ua = ua.toLowerCase();
|
||||
|
||||
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(msie) ([\w.]+)/.exec(ua) ||
|
||||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
|
||||
[];
|
||||
|
||||
return {
|
||||
browser: match[ 1 ] || "",
|
||||
version: match[ 2 ] || "0"
|
||||
};
|
||||
};
|
||||
jQuery.browser = {};
|
||||
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Small JavaScript module for the documentation.
|
||||
*/
|
||||
var Documentation = {
|
||||
|
||||
init : function() {
|
||||
this.fixFirefoxAnchorBug();
|
||||
this.highlightSearchWords();
|
||||
this.initIndexTable();
|
||||
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
|
||||
this.initOnKeyListeners();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* i18n support
|
||||
*/
|
||||
TRANSLATIONS : {},
|
||||
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
|
||||
LOCALE : 'unknown',
|
||||
|
||||
// gettext and ngettext don't access this so that the functions
|
||||
// can safely bound to a different name (_ = Documentation.gettext)
|
||||
gettext : function(string) {
|
||||
var translated = Documentation.TRANSLATIONS[string];
|
||||
if (typeof translated === 'undefined')
|
||||
return string;
|
||||
return (typeof translated === 'string') ? translated : translated[0];
|
||||
},
|
||||
|
||||
ngettext : function(singular, plural, n) {
|
||||
var translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated === 'undefined')
|
||||
return (n == 1) ? singular : plural;
|
||||
return translated[Documentation.PLURALEXPR(n)];
|
||||
},
|
||||
|
||||
addTranslations : function(catalog) {
|
||||
for (var key in catalog.messages)
|
||||
this.TRANSLATIONS[key] = catalog.messages[key];
|
||||
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
||||
this.LOCALE = catalog.locale;
|
||||
},
|
||||
|
||||
/**
|
||||
* add context elements like header anchor links
|
||||
*/
|
||||
addContextElements : function() {
|
||||
$('div[id] > :header:first').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this headline')).
|
||||
appendTo(this);
|
||||
});
|
||||
$('dt[id]').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this definition')).
|
||||
appendTo(this);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* workaround a firefox stupidity
|
||||
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
|
||||
*/
|
||||
fixFirefoxAnchorBug : function() {
|
||||
if (document.location.hash && $.browser.mozilla)
|
||||
window.setTimeout(function() {
|
||||
document.location.href += '';
|
||||
}, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* highlight the search words provided in the url in the text
|
||||
*/
|
||||
highlightSearchWords : function() {
|
||||
var params = $.getQueryParameters();
|
||||
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||
if (terms.length) {
|
||||
var body = $('div.body');
|
||||
if (!body.length) {
|
||||
body = $('body');
|
||||
}
|
||||
window.setTimeout(function() {
|
||||
$.each(terms, function() {
|
||||
body.highlightText(this.toLowerCase(), 'highlighted');
|
||||
});
|
||||
}, 10);
|
||||
$('<p class="highlight-link"><a href="javascript:Documentation.' +
|
||||
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
|
||||
.appendTo($('#searchbox'));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* init the domain index toggle buttons
|
||||
*/
|
||||
initIndexTable : function() {
|
||||
var togglers = $('img.toggler').click(function() {
|
||||
var src = $(this).attr('src');
|
||||
var idnum = $(this).attr('id').substr(7);
|
||||
$('tr.cg-' + idnum).toggle();
|
||||
if (src.substr(-9) === 'minus.png')
|
||||
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
||||
else
|
||||
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
||||
}).css('display', '');
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
|
||||
togglers.click();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to hide the search marks again
|
||||
*/
|
||||
hideSearchWords : function() {
|
||||
$('#searchbox .highlight-link').fadeOut(300);
|
||||
$('span.highlighted').removeClass('highlighted');
|
||||
var url = new URL(window.location);
|
||||
url.searchParams.delete('highlight');
|
||||
window.history.replaceState({}, '', url);
|
||||
},
|
||||
|
||||
/**
|
||||
* make the url absolute
|
||||
*/
|
||||
makeURL : function(relativeURL) {
|
||||
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
||||
},
|
||||
|
||||
/**
|
||||
* get the current relative url
|
||||
*/
|
||||
getCurrentURL : function() {
|
||||
var path = document.location.pathname;
|
||||
var parts = path.split(/\//);
|
||||
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
||||
if (this === '..')
|
||||
parts.pop();
|
||||
});
|
||||
var url = parts.join('/');
|
||||
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
||||
},
|
||||
|
||||
initOnKeyListeners: function() {
|
||||
$(document).keydown(function(event) {
|
||||
var activeElementType = document.activeElement.tagName;
|
||||
// don't navigate when in search box, textarea, dropdown or button
|
||||
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
|
||||
&& activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey
|
||||
&& !event.shiftKey) {
|
||||
switch (event.keyCode) {
|
||||
case 37: // left
|
||||
var prevHref = $('link[rel="prev"]').prop('href');
|
||||
if (prevHref) {
|
||||
window.location.href = prevHref;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 39: // right
|
||||
var nextHref = $('link[rel="next"]').prop('href');
|
||||
if (nextHref) {
|
||||
window.location.href = nextHref;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// quick alias for translations
|
||||
_ = Documentation.gettext;
|
||||
|
||||
$(document).ready(function() {
|
||||
Documentation.init();
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
FILE_SUFFIX: '.html',
|
||||
LINK_SUFFIX: '.html',
|
||||
HAS_SOURCE: true,
|
||||
SOURCELINK_SUFFIX: '.txt',
|
||||
NAVIGATION_WITH_KEYS: false
|
||||
};
|
||||
|
After Width: | Height: | Size: 286 B |
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* language_data.js
|
||||
* ~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This script contains the language-specific data used by searchtools.js,
|
||||
* namely the list of stopwords, stemmer, scorer and splitter.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
||||
|
||||
|
||||
/* Non-minified version is copied as a separate JS file, is available */
|
||||
|
||||
/**
|
||||
* Porter Stemmer
|
||||
*/
|
||||
var Stemmer = function() {
|
||||
|
||||
var step2list = {
|
||||
ational: 'ate',
|
||||
tional: 'tion',
|
||||
enci: 'ence',
|
||||
anci: 'ance',
|
||||
izer: 'ize',
|
||||
bli: 'ble',
|
||||
alli: 'al',
|
||||
entli: 'ent',
|
||||
eli: 'e',
|
||||
ousli: 'ous',
|
||||
ization: 'ize',
|
||||
ation: 'ate',
|
||||
ator: 'ate',
|
||||
alism: 'al',
|
||||
iveness: 'ive',
|
||||
fulness: 'ful',
|
||||
ousness: 'ous',
|
||||
aliti: 'al',
|
||||
iviti: 'ive',
|
||||
biliti: 'ble',
|
||||
logi: 'log'
|
||||
};
|
||||
|
||||
var step3list = {
|
||||
icate: 'ic',
|
||||
ative: '',
|
||||
alize: 'al',
|
||||
iciti: 'ic',
|
||||
ical: 'ic',
|
||||
ful: '',
|
||||
ness: ''
|
||||
};
|
||||
|
||||
var c = "[^aeiou]"; // consonant
|
||||
var v = "[aeiouy]"; // vowel
|
||||
var C = c + "[^aeiouy]*"; // consonant sequence
|
||||
var V = v + "[aeiou]*"; // vowel sequence
|
||||
|
||||
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
||||
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
||||
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
||||
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
||||
|
||||
this.stemWord = function (w) {
|
||||
var stem;
|
||||
var suffix;
|
||||
var firstch;
|
||||
var origword = w;
|
||||
|
||||
if (w.length < 3)
|
||||
return w;
|
||||
|
||||
var re;
|
||||
var re2;
|
||||
var re3;
|
||||
var re4;
|
||||
|
||||
firstch = w.substr(0,1);
|
||||
if (firstch == "y")
|
||||
w = firstch.toUpperCase() + w.substr(1);
|
||||
|
||||
// Step 1a
|
||||
re = /^(.+?)(ss|i)es$/;
|
||||
re2 = /^(.+?)([^s])s$/;
|
||||
|
||||
if (re.test(w))
|
||||
w = w.replace(re,"$1$2");
|
||||
else if (re2.test(w))
|
||||
w = w.replace(re2,"$1$2");
|
||||
|
||||
// Step 1b
|
||||
re = /^(.+?)eed$/;
|
||||
re2 = /^(.+?)(ed|ing)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(fp[1])) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1];
|
||||
re2 = new RegExp(s_v);
|
||||
if (re2.test(stem)) {
|
||||
w = stem;
|
||||
re2 = /(at|bl|iz)$/;
|
||||
re3 = new RegExp("([^aeiouylsz])\\1$");
|
||||
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re2.test(w))
|
||||
w = w + "e";
|
||||
else if (re3.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
else if (re4.test(w))
|
||||
w = w + "e";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1c
|
||||
re = /^(.+?)y$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(s_v);
|
||||
if (re.test(stem))
|
||||
w = stem + "i";
|
||||
}
|
||||
|
||||
// Step 2
|
||||
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step2list[suffix];
|
||||
}
|
||||
|
||||
// Step 3
|
||||
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step3list[suffix];
|
||||
}
|
||||
|
||||
// Step 4
|
||||
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
||||
re2 = /^(.+?)(s|t)(ion)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
if (re.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1] + fp[2];
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re2.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
re = /^(.+?)e$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
re2 = new RegExp(meq1);
|
||||
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
||||
w = stem;
|
||||
}
|
||||
re = /ll$/;
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re.test(w) && re2.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
|
||||
// and turn initial Y back to y
|
||||
if (firstch == "y")
|
||||
w = firstch.toLowerCase() + w.substr(1);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var splitChars = (function() {
|
||||
var result = {};
|
||||
var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
|
||||
1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
|
||||
2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
|
||||
2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
|
||||
3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
|
||||
3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
|
||||
4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
|
||||
8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
|
||||
11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
|
||||
43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
|
||||
var i, j, start, end;
|
||||
for (i = 0; i < singles.length; i++) {
|
||||
result[singles[i]] = true;
|
||||
}
|
||||
var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
|
||||
[722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
|
||||
[1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
|
||||
[1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
|
||||
[1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
|
||||
[2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
|
||||
[2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
|
||||
[2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
|
||||
[2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
|
||||
[2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
|
||||
[2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
|
||||
[2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
|
||||
[3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
|
||||
[3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
|
||||
[3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
|
||||
[3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
|
||||
[3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
|
||||
[3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
|
||||
[4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
|
||||
[4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
|
||||
[4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
|
||||
[4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
|
||||
[5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
|
||||
[6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
|
||||
[6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
|
||||
[6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
|
||||
[6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
|
||||
[7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
|
||||
[7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
|
||||
[8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
|
||||
[8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
|
||||
[8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
|
||||
[10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
|
||||
[11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
|
||||
[12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
|
||||
[12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
|
||||
[12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
|
||||
[19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
|
||||
[42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
|
||||
[42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
|
||||
[43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
|
||||
[43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
|
||||
[43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
|
||||
[43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
|
||||
[44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
|
||||
[57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
|
||||
[64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
|
||||
[65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
|
||||
[65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
|
||||
for (i = 0; i < ranges.length; i++) {
|
||||
start = ranges[i][0];
|
||||
end = ranges[i][1];
|
||||
for (j = start; j <= end; j++) {
|
||||
result[j] = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
|
||||
function splitQuery(query) {
|
||||
var result = [];
|
||||
var start = -1;
|
||||
for (var i = 0; i < query.length; i++) {
|
||||
if (splitChars[query.charCodeAt(i)]) {
|
||||
if (start !== -1) {
|
||||
result.push(query.slice(start, i));
|
||||
start = -1;
|
||||
}
|
||||
} else if (start === -1) {
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
if (start !== -1) {
|
||||
result.push(query.slice(start));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 90 B |
|
After Width: | Height: | Size: 90 B |
@@ -0,0 +1,74 @@
|
||||
pre { line-height: 125%; }
|
||||
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #eeffcc; }
|
||||
.highlight .c { color: #408090; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #333333 } /* Generic.Output */
|
||||
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||
.highlight .m { color: #208050 } /* Literal.Number */
|
||||
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||
.highlight .nf { color: #06287e } /* Name.Function */
|
||||
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mb { color: #208050 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #208050 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
||||
@@ -0,0 +1,529 @@
|
||||
/*
|
||||
* searchtools.js
|
||||
* ~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx JavaScript utilities for the full-text search.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
if (!Scorer) {
|
||||
/**
|
||||
* Simple result scoring code.
|
||||
*/
|
||||
var Scorer = {
|
||||
// Implement the following function to further tweak the score for each result
|
||||
// The function takes a result array [filename, title, anchor, descr, score]
|
||||
// and returns the new score.
|
||||
/*
|
||||
score: function(result) {
|
||||
return result[4];
|
||||
},
|
||||
*/
|
||||
|
||||
// query matches the full name of an object
|
||||
objNameMatch: 11,
|
||||
// or matches in the last dotted part of the object name
|
||||
objPartialMatch: 6,
|
||||
// Additive scores depending on the priority of the object
|
||||
objPrio: {0: 15, // used to be importantResults
|
||||
1: 5, // used to be objectResults
|
||||
2: -5}, // used to be unimportantResults
|
||||
// Used when the priority is not in the mapping.
|
||||
objPrioDefault: 0,
|
||||
|
||||
// query found in title
|
||||
title: 15,
|
||||
partialTitle: 7,
|
||||
// query found in terms
|
||||
term: 5,
|
||||
partialTerm: 2
|
||||
};
|
||||
}
|
||||
|
||||
if (!splitQuery) {
|
||||
function splitQuery(query) {
|
||||
return query.split(/\s+/);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search Module
|
||||
*/
|
||||
var Search = {
|
||||
|
||||
_index : null,
|
||||
_queued_query : null,
|
||||
_pulse_status : -1,
|
||||
|
||||
htmlToText : function(htmlString) {
|
||||
var virtualDocument = document.implementation.createHTMLDocument('virtual');
|
||||
var htmlElement = $(htmlString, virtualDocument);
|
||||
htmlElement.find('.headerlink').remove();
|
||||
docContent = htmlElement.find('[role=main]')[0];
|
||||
if(docContent === undefined) {
|
||||
console.warn("Content block not found. Sphinx search tries to obtain it " +
|
||||
"via '[role=main]'. Could you check your theme or template.");
|
||||
return "";
|
||||
}
|
||||
return docContent.textContent || docContent.innerText;
|
||||
},
|
||||
|
||||
init : function() {
|
||||
var params = $.getQueryParameters();
|
||||
if (params.q) {
|
||||
var query = params.q[0];
|
||||
$('input[name="q"]')[0].value = query;
|
||||
this.performSearch(query);
|
||||
}
|
||||
},
|
||||
|
||||
loadIndex : function(url) {
|
||||
$.ajax({type: "GET", url: url, data: null,
|
||||
dataType: "script", cache: true,
|
||||
complete: function(jqxhr, textstatus) {
|
||||
if (textstatus != "success") {
|
||||
document.getElementById("searchindexloader").src = url;
|
||||
}
|
||||
}});
|
||||
},
|
||||
|
||||
setIndex : function(index) {
|
||||
var q;
|
||||
this._index = index;
|
||||
if ((q = this._queued_query) !== null) {
|
||||
this._queued_query = null;
|
||||
Search.query(q);
|
||||
}
|
||||
},
|
||||
|
||||
hasIndex : function() {
|
||||
return this._index !== null;
|
||||
},
|
||||
|
||||
deferQuery : function(query) {
|
||||
this._queued_query = query;
|
||||
},
|
||||
|
||||
stopPulse : function() {
|
||||
this._pulse_status = 0;
|
||||
},
|
||||
|
||||
startPulse : function() {
|
||||
if (this._pulse_status >= 0)
|
||||
return;
|
||||
function pulse() {
|
||||
var i;
|
||||
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||
var dotString = '';
|
||||
for (i = 0; i < Search._pulse_status; i++)
|
||||
dotString += '.';
|
||||
Search.dots.text(dotString);
|
||||
if (Search._pulse_status > -1)
|
||||
window.setTimeout(pulse, 500);
|
||||
}
|
||||
pulse();
|
||||
},
|
||||
|
||||
/**
|
||||
* perform a search for something (or wait until index is loaded)
|
||||
*/
|
||||
performSearch : function(query) {
|
||||
// create the required interface elements
|
||||
this.out = $('#search-results');
|
||||
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
||||
this.dots = $('<span></span>').appendTo(this.title);
|
||||
this.status = $('<p class="search-summary"> </p>').appendTo(this.out);
|
||||
this.output = $('<ul class="search"/>').appendTo(this.out);
|
||||
|
||||
$('#search-progress').text(_('Preparing search...'));
|
||||
this.startPulse();
|
||||
|
||||
// index already loaded, the browser was quick!
|
||||
if (this.hasIndex())
|
||||
this.query(query);
|
||||
else
|
||||
this.deferQuery(query);
|
||||
},
|
||||
|
||||
/**
|
||||
* execute search (requires search index to be loaded)
|
||||
*/
|
||||
query : function(query) {
|
||||
var i;
|
||||
|
||||
// stem the searchterms and add them to the correct list
|
||||
var stemmer = new Stemmer();
|
||||
var searchterms = [];
|
||||
var excluded = [];
|
||||
var hlterms = [];
|
||||
var tmp = splitQuery(query);
|
||||
var objectterms = [];
|
||||
for (i = 0; i < tmp.length; i++) {
|
||||
if (tmp[i] !== "") {
|
||||
objectterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
|
||||
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i] === "") {
|
||||
// skip this "word"
|
||||
continue;
|
||||
}
|
||||
// stem the word
|
||||
var word = stemmer.stemWord(tmp[i].toLowerCase());
|
||||
// prevent stemmer from cutting word smaller than two chars
|
||||
if(word.length < 3 && tmp[i].length >= 3) {
|
||||
word = tmp[i];
|
||||
}
|
||||
var toAppend;
|
||||
// select the correct list
|
||||
if (word[0] == '-') {
|
||||
toAppend = excluded;
|
||||
word = word.substr(1);
|
||||
}
|
||||
else {
|
||||
toAppend = searchterms;
|
||||
hlterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
// only add if not already in the list
|
||||
if (!$u.contains(toAppend, word))
|
||||
toAppend.push(word);
|
||||
}
|
||||
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||
|
||||
// console.debug('SEARCH: searching for:');
|
||||
// console.info('required: ', searchterms);
|
||||
// console.info('excluded: ', excluded);
|
||||
|
||||
// prepare search
|
||||
var terms = this._index.terms;
|
||||
var titleterms = this._index.titleterms;
|
||||
|
||||
// array of [filename, title, anchor, descr, score]
|
||||
var results = [];
|
||||
$('#search-progress').empty();
|
||||
|
||||
// lookup as object
|
||||
for (i = 0; i < objectterms.length; i++) {
|
||||
var others = [].concat(objectterms.slice(0, i),
|
||||
objectterms.slice(i+1, objectterms.length));
|
||||
results = results.concat(this.performObjectSearch(objectterms[i], others));
|
||||
}
|
||||
|
||||
// lookup as search terms in fulltext
|
||||
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
|
||||
|
||||
// let the scorer override scores with a custom scoring function
|
||||
if (Scorer.score) {
|
||||
for (i = 0; i < results.length; i++)
|
||||
results[i][4] = Scorer.score(results[i]);
|
||||
}
|
||||
|
||||
// now sort the results by score (in opposite order of appearance, since the
|
||||
// display function below uses pop() to retrieve items) and then
|
||||
// alphabetically
|
||||
results.sort(function(a, b) {
|
||||
var left = a[4];
|
||||
var right = b[4];
|
||||
if (left > right) {
|
||||
return 1;
|
||||
} else if (left < right) {
|
||||
return -1;
|
||||
} else {
|
||||
// same score: sort alphabetically
|
||||
left = a[1].toLowerCase();
|
||||
right = b[1].toLowerCase();
|
||||
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||
}
|
||||
});
|
||||
|
||||
// for debugging
|
||||
//Search.lastresults = results.slice(); // a copy
|
||||
//console.info('search results:', Search.lastresults);
|
||||
|
||||
// print the results
|
||||
var resultCount = results.length;
|
||||
function displayNextItem() {
|
||||
// results left, load the summary and display it
|
||||
if (results.length) {
|
||||
var item = results.pop();
|
||||
var listItem = $('<li></li>');
|
||||
var requestUrl = "";
|
||||
var linkUrl = "";
|
||||
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
|
||||
// dirhtml builder
|
||||
var dirname = item[0] + '/';
|
||||
if (dirname.match(/\/index\/$/)) {
|
||||
dirname = dirname.substring(0, dirname.length-6);
|
||||
} else if (dirname == 'index/') {
|
||||
dirname = '';
|
||||
}
|
||||
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
|
||||
linkUrl = requestUrl;
|
||||
|
||||
} else {
|
||||
// normal html builders
|
||||
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
|
||||
linkUrl = item[0] + DOCUMENTATION_OPTIONS.LINK_SUFFIX;
|
||||
}
|
||||
listItem.append($('<a/>').attr('href',
|
||||
linkUrl +
|
||||
highlightstring + item[2]).html(item[1]));
|
||||
if (item[3]) {
|
||||
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||
Search.output.append(listItem);
|
||||
setTimeout(function() {
|
||||
displayNextItem();
|
||||
}, 5);
|
||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||
$.ajax({url: requestUrl,
|
||||
dataType: "text",
|
||||
complete: function(jqxhr, textstatus) {
|
||||
var data = jqxhr.responseText;
|
||||
if (data !== '' && data !== undefined) {
|
||||
var summary = Search.makeSearchSummary(data, searchterms, hlterms);
|
||||
if (summary) {
|
||||
listItem.append(summary);
|
||||
}
|
||||
}
|
||||
Search.output.append(listItem);
|
||||
setTimeout(function() {
|
||||
displayNextItem();
|
||||
}, 5);
|
||||
}});
|
||||
} else {
|
||||
// no source available, just display title
|
||||
Search.output.append(listItem);
|
||||
setTimeout(function() {
|
||||
displayNextItem();
|
||||
}, 5);
|
||||
}
|
||||
}
|
||||
// search finished, update title and status message
|
||||
else {
|
||||
Search.stopPulse();
|
||||
Search.title.text(_('Search Results'));
|
||||
if (!resultCount)
|
||||
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
||||
else
|
||||
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
||||
Search.status.fadeIn(500);
|
||||
}
|
||||
}
|
||||
displayNextItem();
|
||||
},
|
||||
|
||||
/**
|
||||
* search for object names
|
||||
*/
|
||||
performObjectSearch : function(object, otherterms) {
|
||||
var filenames = this._index.filenames;
|
||||
var docnames = this._index.docnames;
|
||||
var objects = this._index.objects;
|
||||
var objnames = this._index.objnames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
var i;
|
||||
var results = [];
|
||||
|
||||
for (var prefix in objects) {
|
||||
for (var iMatch = 0; iMatch != objects[prefix].length; ++iMatch) {
|
||||
var match = objects[prefix][iMatch];
|
||||
var name = match[4];
|
||||
var fullname = (prefix ? prefix + '.' : '') + name;
|
||||
var fullnameLower = fullname.toLowerCase()
|
||||
if (fullnameLower.indexOf(object) > -1) {
|
||||
var score = 0;
|
||||
var parts = fullnameLower.split('.');
|
||||
// check for different match types: exact matches of full name or
|
||||
// "last name" (i.e. last dotted part)
|
||||
if (fullnameLower == object || parts[parts.length - 1] == object) {
|
||||
score += Scorer.objNameMatch;
|
||||
// matches in last name
|
||||
} else if (parts[parts.length - 1].indexOf(object) > -1) {
|
||||
score += Scorer.objPartialMatch;
|
||||
}
|
||||
var objname = objnames[match[1]][2];
|
||||
var title = titles[match[0]];
|
||||
// If more than one term searched for, we require other words to be
|
||||
// found in the name/title/description
|
||||
if (otherterms.length > 0) {
|
||||
var haystack = (prefix + ' ' + name + ' ' +
|
||||
objname + ' ' + title).toLowerCase();
|
||||
var allfound = true;
|
||||
for (i = 0; i < otherterms.length; i++) {
|
||||
if (haystack.indexOf(otherterms[i]) == -1) {
|
||||
allfound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!allfound) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var descr = objname + _(', in ') + title;
|
||||
|
||||
var anchor = match[3];
|
||||
if (anchor === '')
|
||||
anchor = fullname;
|
||||
else if (anchor == '-')
|
||||
anchor = objnames[match[1]][1] + '-' + fullname;
|
||||
// add custom score for some objects according to scorer
|
||||
if (Scorer.objPrio.hasOwnProperty(match[2])) {
|
||||
score += Scorer.objPrio[match[2]];
|
||||
} else {
|
||||
score += Scorer.objPrioDefault;
|
||||
}
|
||||
results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
/**
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
||||
*/
|
||||
escapeRegExp : function(string) {
|
||||
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
},
|
||||
|
||||
/**
|
||||
* search for full-text terms in the index
|
||||
*/
|
||||
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
|
||||
var docnames = this._index.docnames;
|
||||
var filenames = this._index.filenames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
var i, j, file;
|
||||
var fileMap = {};
|
||||
var scoreMap = {};
|
||||
var results = [];
|
||||
|
||||
// perform the search on the required terms
|
||||
for (i = 0; i < searchterms.length; i++) {
|
||||
var word = searchterms[i];
|
||||
var files = [];
|
||||
var _o = [
|
||||
{files: terms[word], score: Scorer.term},
|
||||
{files: titleterms[word], score: Scorer.title}
|
||||
];
|
||||
// add support for partial matches
|
||||
if (word.length > 2) {
|
||||
var word_regex = this.escapeRegExp(word);
|
||||
for (var w in terms) {
|
||||
if (w.match(word_regex) && !terms[word]) {
|
||||
_o.push({files: terms[w], score: Scorer.partialTerm})
|
||||
}
|
||||
}
|
||||
for (var w in titleterms) {
|
||||
if (w.match(word_regex) && !titleterms[word]) {
|
||||
_o.push({files: titleterms[w], score: Scorer.partialTitle})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no match but word was a required one
|
||||
if ($u.every(_o, function(o){return o.files === undefined;})) {
|
||||
break;
|
||||
}
|
||||
// found search word in contents
|
||||
$u.each(_o, function(o) {
|
||||
var _files = o.files;
|
||||
if (_files === undefined)
|
||||
return
|
||||
|
||||
if (_files.length === undefined)
|
||||
_files = [_files];
|
||||
files = files.concat(_files);
|
||||
|
||||
// set score for the word in each file to Scorer.term
|
||||
for (j = 0; j < _files.length; j++) {
|
||||
file = _files[j];
|
||||
if (!(file in scoreMap))
|
||||
scoreMap[file] = {};
|
||||
scoreMap[file][word] = o.score;
|
||||
}
|
||||
});
|
||||
|
||||
// create the mapping
|
||||
for (j = 0; j < files.length; j++) {
|
||||
file = files[j];
|
||||
if (file in fileMap && fileMap[file].indexOf(word) === -1)
|
||||
fileMap[file].push(word);
|
||||
else
|
||||
fileMap[file] = [word];
|
||||
}
|
||||
}
|
||||
|
||||
// now check if the files don't contain excluded terms
|
||||
for (file in fileMap) {
|
||||
var valid = true;
|
||||
|
||||
// check if all requirements are matched
|
||||
var filteredTermCount = // as search terms with length < 3 are discarded: ignore
|
||||
searchterms.filter(function(term){return term.length > 2}).length
|
||||
if (
|
||||
fileMap[file].length != searchterms.length &&
|
||||
fileMap[file].length != filteredTermCount
|
||||
) continue;
|
||||
|
||||
// ensure that none of the excluded terms is in the search result
|
||||
for (i = 0; i < excluded.length; i++) {
|
||||
if (terms[excluded[i]] == file ||
|
||||
titleterms[excluded[i]] == file ||
|
||||
$u.contains(terms[excluded[i]] || [], file) ||
|
||||
$u.contains(titleterms[excluded[i]] || [], file)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have still a valid result we can add it to the result list
|
||||
if (valid) {
|
||||
// select one (max) score for the file.
|
||||
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
|
||||
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
|
||||
results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to return a node containing the
|
||||
* search summary for a given text. keywords is a list
|
||||
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||
* words. the first one is used to find the occurrence, the
|
||||
* latter for highlighting it.
|
||||
*/
|
||||
makeSearchSummary : function(htmlText, keywords, hlwords) {
|
||||
var text = Search.htmlToText(htmlText);
|
||||
if (text == "") {
|
||||
return null;
|
||||
}
|
||||
var textLower = text.toLowerCase();
|
||||
var start = 0;
|
||||
$.each(keywords, function() {
|
||||
var i = textLower.indexOf(this.toLowerCase());
|
||||
if (i > -1)
|
||||
start = i;
|
||||
});
|
||||
start = Math.max(start - 120, 0);
|
||||
var excerpt = ((start > 0) ? '...' : '') +
|
||||
$.trim(text.substr(start, 240)) +
|
||||
((start + 240 - text.length) ? '...' : '');
|
||||
var rv = $('<p class="context"></p>').text(excerpt);
|
||||
$.each(hlwords, function() {
|
||||
rv = rv.highlightText(this, 'highlighted');
|
||||
});
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
Search.init();
|
||||
});
|
||||
@@ -0,0 +1,119 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Index — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
<script src="_static/jquery.js"></script>
|
||||
<script src="_static/underscore.js"></script>
|
||||
<script src="_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="#" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
|
||||
<h1 id="index">Index</h1>
|
||||
|
||||
<div class="genindex-jumpbox">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="index.html">
|
||||
<img class="logo" src="_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,319 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>SNP Laboratories — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
<script src="_static/jquery.js"></script>
|
||||
<script src="_static/underscore.js"></script>
|
||||
<script src="_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="genindex.html" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
<link rel="next" title="01 - Erste Schritte mit C" href="P01_Erste_Schritte_mit_C/README.html" />
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="toctree-wrapper compound">
|
||||
</div>
|
||||
<section id="snp-laboratories">
|
||||
<h1>SNP Laboratories<a class="headerlink" href="#snp-laboratories" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="toctree-wrapper compound">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html#aufgabe-1-virtuelle-maschine">3. Aufgabe 1: virtuelle Maschine</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html#aufgabe-2-hello-world">4. Aufgabe 2: Hello World</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html#aufgabe-3-tabellenausgabe">5. Aufgabe 3: Tabellenausgabe</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html#aufgabe-4-zeichen-und-worter-zahlen">6. Aufgabe 4: Zeichen und Wörter zählen</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html#bewertung">7. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#aufgaben">3. Aufgaben</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#aufgabe-1-tage-pro-monat">3.1 Aufgabe 1 Tage pro Monat</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#aufgabe-2-bestimmen-des-wochentags">3.2 Aufgabe 2 Bestimmen des Wochentags</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#teilaufgabe-argumente-parsen-und-auf-korrektheit-prufen">3.2.1 Teilaufgabe Argumente Parsen und auf Korrektheit prüfen</a><ul>
|
||||
<li class="toctree-l5"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#argument-format">3.2.1.1 Argument Format</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#korrektes-datum">3.2.1.2 Korrektes Datum</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#vorgaben-an-die-umsetzung">3.2.1.3 Vorgaben an die Umsetzung</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#hinweise">3.2.1.4 Hinweise</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#teilaufgabe-wochentag-berechnung">3.2.2 Teilaufgabe Wochentag Berechnung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#bewertung">4. Bewertung</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#anhang">5. Anhang</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#sprach-element">5.1 Sprach Element</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html#beschreibung">5.2 Beschreibung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#bit-operationen">1. Bit Operationen</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#ubungen">1.1 Übungen</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#basis-operationen">1. Basis Operationen</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#variablen-tauschen-ohne-dritt-variable">2. Variablen tauschen (ohne Dritt-Variable)</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#lower-uppercase">3. Lower- / Uppercase</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#prufen-auf-2-er-potenz">4. Prüfen auf 2-er Potenz</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#struct-typedef">2. Struct & typedef</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#id1">2.1 Übungen</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#bit-operationen-rechner">1. Bit Operationen Rechner</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#aufgabe-1-modularisieren">3. Aufgabe 1: Modularisieren</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#teilaufgabe-modules-einbinden-header-files-schreiben">3.1 Teilaufgabe Modules einbinden, Header Files schreiben</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#aufgabe-2-makefile-regeln">4. Aufgabe 2: Makefile Regeln</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#neue-regeln-hinzufugen">4.1 Neue Regeln hinzufügen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#aufgabe-3">5. Aufgabe 3</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#bewertung">6. Bewertung</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html#erweiterung-doxyfile-fur-abhangigkeitsanalyse">7. Erweiterung Doxyfile für Abhängigkeitsanalyse</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P05_TicTacToe/README.html#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P05_TicTacToe/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P05_TicTacToe/README.html#aufgabe-1-sortieren-von-strings">3. Aufgabe 1: Sortieren von Strings</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P05_TicTacToe/README.html#aufgabe-2-tictactoe">4. Aufgabe 2: TicTacToe</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P05_TicTacToe/README.html#teilaufgabe-test-model-init">4.1 Teilaufgabe test_model_init</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P05_TicTacToe/README.html#teilaufgabe-test-model-get-state-und-test-model-get-winner">4.2 Teilaufgabe test_model_get_state und test_model_get_winner</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P05_TicTacToe/README.html#teilaufgabe-test-model-can-move">4.3 Teilaufgabe test_model_can_move</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P05_TicTacToe/README.html#teilaufgabe-test-model-move-und-test-model-get-win-line">4.4 Teilaufgabe test_model_move und test_model_get_win_line</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P05_TicTacToe/README.html#bewertung">5. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#personenverwaltung">3. Personenverwaltung</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#programmfunktion">3.1 Programmfunktion</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#designvorgaben">3.2 Designvorgaben</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#bestehender-programmrahmen">3.3 Bestehender Programmrahmen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#aufgabe-1-modularisierung-api-und-implementation-main-c">4. Aufgabe 1: Modularisierung – API und Implementation main.c</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#aufgabe-2-implementierung-von-person-c-und-list-c">5. Aufgabe 2: Implementierung von person.c und list.c</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#teilaufgabe-implementierung-von-person-c">5.1 Teilaufgabe: Implementierung von person.c</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#teilaufgabe-implementierung-von-list-c">5.2 Teilaufgabe: Implementierung von list.c</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#aufgabe-3-unit-tests">6. Aufgabe 3: Unit Tests</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html#bewertung">7. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#ubersicht">1. Übersicht</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#nachweis">1.1 Nachweis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgaben">3. Aufgaben</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-1-prozess-mit-fork-erzeugen">3.1 Aufgabe 1: Prozess mit fork() erzeugen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-2-prozess-mit-fork-und-exec-programm-image-ersetzen">3.2 Aufgabe 2: Prozess mit fork() und exec(): Programm Image ersetzen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-3-prozesshierarchie-analysieren">3.3 Aufgabe 3: Prozesshierarchie analysieren</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-4-zeitlicher-ablauf-von-prozessen">3.4 Aufgabe 4: Zeitlicher Ablauf von Prozessen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-5-waisenkinder-orphan-processes">3.5 Aufgabe 5: Waisenkinder (Orphan Processes)</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-6-terminierte-halbtote-prozesse-zombies">3.6 Aufgabe 6: Terminierte, halbtote Prozesse (Zombies)</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-7-auf-terminieren-von-kindprozessen-warten">3.7 Aufgabe 7: Auf Terminieren von Kindprozessen warten</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-8-kindprozess-als-kopie-des-elternprozesses">3.8 Aufgabe 8: Kindprozess als Kopie des Elternprozesses</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-9-unterschied-von-threads-gegenuber-prozessen">3.9 Aufgabe 9: Unterschied von Threads gegenüber Prozessen</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-10-optional">3.10 Aufgabe 10 (optional):</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#id1">3.10.1 Übersicht</a><ul>
|
||||
<li class="toctree-l5"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#id2">3.10.1.1 Nachweis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#id3">3.10.2 Lernziele</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#aufgabe-damon-prozesse">3.10.3 Aufgabe: Dämon Prozesse</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#zusatzinformationen">3.10.4 Zusatzinformationen</a><ul>
|
||||
<li class="toctree-l5"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#diese-implementation">3.10.4.1 Diese Implementation</a></li>
|
||||
<li class="toctree-l5"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#zusatzinformation-zu-damon-prozessen">3.10.4.2 Zusatzinformation zu Dämon Prozessen</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P08_Sync/README.html">08 - Synchronisationsprobleme</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P08_Sync/README.html#ubersicht">1. Übersicht</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#nachweis">1.1 Nachweis</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P08_Sync/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P08_Sync/README.html#einfuhrung">3. Einführung</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#wie-lost-man-synchronisationsprobleme">3.1 Wie löst man Synchronisationsprobleme?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P08_Sync/README.html#der-kaffee-automat">4. Der Kaffee-Automat</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#aufgabe-mutual-exclusion">4.1 Aufgabe: Mutual Exclusion</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P08_Sync/README.html#aufgaben">Aufgaben</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#aufgabe-einfache-reihenfolge">4.2 Aufgabe: Einfache Reihenfolge</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P08_Sync/README.html#id1">Aufgaben</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#aufgabe-erweiterte-reihenfolge">4.3 Aufgabe: Erweiterte Reihenfolge</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="P08_Sync/README.html#aufgabe">Aufgabe</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#zusammenfassung">4.4 Zusammenfassung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P08_Sync/README.html#international-banking">5. International Banking</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#implementation">5.1 Implementation</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#aufgabe-konto-synchronisation">5.2 Aufgabe: Konto Synchronisation</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#aufgabe-filialen-zugriff-in-critical-section">5.3 Aufgabe: Filialen Zugriff in Critical Section</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="P08_Sync/README.html#aufgabe-refactoring-der-synchronisation">5.4 Aufgabe: Refactoring der Synchronisation</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P08_Sync/README.html#bewertung">6. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P09_File_Operations/README.html">09 - File Operations</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P09_File_Operations/README.html#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P09_File_Operations/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P09_File_Operations/README.html#aufgabe-1">3. Aufgabe 1:</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P09_File_Operations/README.html#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P10_IPC/README.html">10 - IPC</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P10_IPC/README.html#ubersicht">1. Übersicht</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P10_IPC/README.html#lernziele">2. Lernziele</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P10_IPC/README.html#aufgabe-1">3. Aufgabe 1:</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="P10_IPC/README.html#bewertung">4. Bewertung</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="#">
|
||||
<img class="logo" src="_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="#">Documentation overview</a><ul>
|
||||
<li>Next: <a href="P01_Erste_Schritte_mit_C/README.html" title="next chapter">01 - Erste Schritte mit C</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="_sources/index.rst.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,138 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Search — SNP Labs documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
<script src="_static/jquery.js"></script>
|
||||
<script src="_static/underscore.js"></script>
|
||||
<script src="_static/doctools.js"></script>
|
||||
<script src="_static/searchtools.js"></script>
|
||||
<script src="_static/language_data.js"></script>
|
||||
<link rel="index" title="Index" href="genindex.html" />
|
||||
<link rel="search" title="Search" href="#" />
|
||||
<script src="searchindex.js" defer></script>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1 id="search-documentation">Search</h1>
|
||||
|
||||
<noscript>
|
||||
<div class="admonition warning">
|
||||
<p>
|
||||
Please activate JavaScript to enable the search
|
||||
functionality.
|
||||
</p>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
|
||||
<p>
|
||||
Searching for multiple words only shows matches that contain
|
||||
all words.
|
||||
</p>
|
||||
|
||||
|
||||
<form action="" method="get">
|
||||
<input type="text" name="q" aria-labelledby="search-documentation" value="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="search" />
|
||||
<span id="search-progress" style="padding-left: 10px"></span>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<div id="search-results">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<p class="logo">
|
||||
<a href="index.html">
|
||||
<img class="logo" src="_static/logo.png" alt="Logo"/>
|
||||
|
||||
<h1 class="logo logo-name">SNP Labs</h1>
|
||||
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P01_Erste_Schritte_mit_C/README.html">01 - Erste Schritte mit C</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P02_Funktionen_Datentyp_enum/README.html">02: Funktionen, Datentyp “enum”</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P03_Bit_Operation_struct_typedef/README.html">03 - Bit Operationen, Struct, Typedef</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P04_Modularisieren_von_C_Code/new_P04/P04_Modularisieren_von_C_Code.html">04 - Modularisieren von C Code</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P05_TicTacToe/README.html">05 - Arrays/Strings/TicTacToe</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P06_Personen_Verwaltung_Linked_List/README.html">06 - Personen Verwaltung – Linked List</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P07_Prozesse_und_Threads/README.html">07 - Prozesse und Threads</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P08_Sync/README.html">08 - Synchronisationsprobleme</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P09_File_Operations/README.html">09 - File Operations</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="P10_IPC/README.html">10 - IPC</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2022, stsh.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||