Artikel aus dem Jahr 2018

Felder in R: der Datentyp array

Felder sind in R die Verallgemeinerung von Matrizen. In einer Matrix werden die Komponenten zweidimensional angeordnet (Zeilen und Spalten), in einem Feld sind beliebige Dimensionen zugelassen. Erzeugt werden Felder meist, indem ein Vektor mit Hilfe des Dimensionsvektors mehrdimensional angeordnet wird, oder mit der Funktion outer(). Weitere Gemeinsamkeiten und Unterschiede zu Matrizen werden diskutiert.

Matrizen in R: Anwendungen

Vorgestellt wird, wie Matrizen miteinander verknüpft werden, welche Funktionen Eigenschaften von Matrizen anzeigen, sowie zahlreiche Funktionen aus der Linearen Algebra (Berechnung von Determinanten, Lösung von linearen Gleichungssystemen, Berechnung von transponierten und inversen Matrizen, Berechnung von Eigenwerten und Eigenvektoren).

Matrizen in R: der Datentyp matrix

Die Komponenten eines Vektors können in R zweidimensional angeordnet werden wie in einer Matrix. Es werden verschiedene Möglichkeiten gezeigt, wie man Matrizen erzeugen kann, wie man spezielle Matrizen erzeugt und wie man auf die Komponenten einer Matrix zugreift. Weiter werden der Dimensionsvektor (Attribut dim) und das optionale Attribut dimnames vorgestellt. Wie Matrizen verknüpft werden und weitere Anwendungen folgen im nächsten Kapitel (Matrizen in R: Anwendungen).

Vektoren in R: Anwendungen

Grundlegend für das Verständnis von Operationen, die mit Vektoren ausgeführt werden können, sind die punktweise Ausführung (eine Operation wird an die Komponenten weitergereicht) und der recycling-Mechanismus, der festlegt, wie Vektoren mit unterschiedlichen Längen verknüpft werden. Ausgehend hiervon werden zahlreiche Operationen vorgestellt, die mit Vektoren ausgeführt werden können (wie zum Beispiel statistische Funktionen, Sortier-Algorithmen, Mengen-Operationen).

Vektoren in R: der Datentyp vector

Da es in R eigentlich keine fundamentalen Datentypen gibt (wie ganze Zahlen, Gleitkommazahlen, Zeichen, logische Werte), sondern diese Spezialfall eines Vektors der Länge 1 sind, ist dieses Kapitel entscheidend für das Verständnis von R. Vektoren bestehen aus Komponenten mit identischem Speichermodus und die Komponenten sind numeriert (oder wie man auch sagt: indiziert). Vorgestellt werden hier Funktionen zum Erzeugen von Vektoren, der Zugriff auf die Komponenten eines Vektors, Diagnose-Funktionen für Vektoren und das Attribut names. Wie man Vektoren verknüpft und welche weiteren Funktionen zur Weiterverarbeitung von Vektoren existieren, wird im nächsten Kapitel gezeigt (Vektoren in R: Anwendungen).

Einführung in R: Zeichen

In R sind Zeichen kein fundamentaler Datentyp; sie werden nicht von Zeichenketten unterschieden. Um aber mit den Besonderheiten der Verarbeitung von Zeichen vertraut zu werden, werden vorerst nur Zeichen behandelt. Diese Besonderheiten betreffen insbesondere die Maskierung von bestimmten Zeichen und die Typumwandlungen. Einige harmlose Beispiele für Zeichenketten (die ohne Wissen über Vektoren verständlich sind) werden hier schon angeführt.

Einführung in Betriebssysteme

Die Aufgaben des Betriebssystems haben sich im Lauf der Zeit gewandelt: Anfangs war ein menschlicher Operator dafür zuständig, Programme zu starten und zu beenden, später wurde diese und weitere Aufgaben von Dienst-Programmen übernommen. Um die Aufgaben und die Arbeitsweise des Betriebssystem besser zu verstehen, wird ein Computer in Schichten zerlegt: Anwendersoftware, Systemsoftware und Hardware.

Auszeichnungssprachen (markup language)

Programmiersprachen werden eingesetzt, um Algorithmen zu schreiben. Auszeichnungssprachen sind dazu da, um die Elemente eines Textes (wie Überschriften, Fließtext, Listen und dergleichen) logisch auszuzeichnen und meist Formatierungsregeln für diese Elemente festzulegen. Als Beispiele für Auszeichnungssprachen werden LaTeX, HTML, XML und SVG vorgestellt. Der Vorteil einer Auszeichnungssprache ist, dass sie sowohl menschen-lesbar als auch maschinen-lesbar ist, wodurch sie insbesondere in der automaischen Textverarbeitung eingesetzt wird.

Die Komponenten des von Neumann Rechners: Der Prozessor

Die Maschinensprache-Befehle sind noch nicht die elementaren Anweisungen für die Komponenten des Prozessors: einen Maschinensprache-Befehl zu dekodieren heißt, ein Mikro-Programm zu laden, das den Befehl implementiert. Je nach Prozessor-Architektur gibt es eine unterschiedlich große semantische Lücke zwischen den Maschinensprache-Befehlen und den Mikro-Befehlen. Mit der Kenntnis der Mikro-Programme wird leichter verständlich, wie die Komponenten des Prozessors zusammenarbeiten und sie mit Hilfe des Pipelining optimal ausgelastet werden können.

Elementare Syntax von C++: Fundamentale Datentypen

Für das Erlernen der Sprache C++ ist dieser Abschnitt zentral: es werden die wichtigsten fundamentalen Datentypen ausführlich vorgestellt, also Zeichen, Boolesche Variable, ganze Zahlen und Gleitkommazahlen. Die Datentypen sind immer verknüpft mit den Operationen, die mit ihnen ausgeführt werden können. Weiter werden die Typumwandlungen (und die damit verbundenen Fehlerquellen) zwischen den fundamentalen Datentypen besprochen.

Lösungshinweise zu den Aufgaben aus Elementare Syntax von C++: Fundamentale Datentypen

Aufgrund der Plattformabhängigkeit der fundamentalen Datentypen in C++ ist es für den Programmierer unerlässlich zu wissen, welcher Datentyp wieviel Speicherplatz belegt und insbesondere in welchen Zahlenbereichen die am häufigsten verwendeten Datentypen (wie short, int, float, double) fehlerfrei eingesetzt werden können. Da man sich die Grenzen der Zahlenbereiche vermutlich nicht merken kann, sollte man zumindest wissen, wie man sie leicht feststellen kann. Dazu werden die in Elementare Syntax von C++: Fundamentale Datentypen gestellten Aufgaben gelöst beziehungsweise Lösungshinweise gegeben.

C++ Programmieraufgabe: Auswertung einer Fahrradtour

Die Programmieraufgabe behandelt ein typisches Problem der Datenverarbeitung: Messdaten werden laufend aufgenommen und sollen geeignet ausgewertet werden. Sie können: Erstens direkt angezeigt werden, zweitens sofort in andere relevante Daten umgerechnet und angezeigt werden oder drittens abgespeichert und erst in ihrer Gesamtheit ausgewertet werden. Diese Aufgaben sollen anhand der zu simulierenden Daten, die während einer Fahrradtour anfallen können, eingeübt werden.

C++ Programmieraufgabe: Simulation einer Heizung und eines Heizungsreglers

Vorgestellt wird ein Problem der Regelungstechnik: Es soll die Umgebung eines Hauses und dessen Heizung simuliert werden. Dabei sollen in konstanten Zeitabständen die Außentemperatur und die Raumtemperatur gemessen werden und ein Algorithmus entwickelt werden, der dafür sorgt, dass die Raumtemperatur der vorgegebenen Soll-Temperatur möglichst nahe kommt.

C++ Programmieraufgabe: Matching

Matching-Probleme treten dann auf, wenn zwischen zwei Gruppen eine Zuordnung hergestellt werden soll (jedem Bewerber soll eine Stelle vermittelt werden; jedem Gast soll ein Geschenk überreicht werden). Dabei können unterschiedliche Nebenbedingungen hinzutreten (ein Bewerber ist nur für bestimmte Stellen qualifiziert; nicht jedes Geschenk ist für jeden Gast geeignet). Bei kleinen Gruppengrößen können diese Zuordnungen meist direkt gefunden werden; im Allgemeinen versucht man Algorithmen zu formulieren, die die Zuordnungen finden. Matching-Probleme werden in der Graphentheorie behandelt. Die hier vorgestellten Programmieraufgaben sollen einige typische Fragestellungen aufzeigen.

C++ Programmieraufgabe: Das Rucksackproblem

Das Rucksackproblem gehört zur Klasse der Optimierungsprobleme. Dabei sollen aus einer Menge von Gegenständen diejenigen in den Rucksack gepackt werden, die den Wert seines Inhaltes maximieren. Für kleine Anzahlen von Gegenständen kann man die optimale Lösung leicht erraten. Für sehr große Anzahlen kann ein Algorithmus, der alle möglichen Bepackungen durchprobiert, unzumutbare Rechenzeit beanspruchen.

Objekt-orientiertes Design in C++: Komposition und Vererbung

Vorgestellt werden die Design-Prinzipien Komposition und Vererbung, die immer dann eingesetzt werden, wenn Klassen als Datenelemente nicht nur fundamentale Datentypen sondern ihrerseits Klassen enthalten. Dabei werden weitere anspruchsvolle Konzepte von C++ erläutert: Der Polymorphismus (= Vielgestaltigkeit), Zeiger, das Überschreiben von Funktionen (function overriding) und Operatoren, Implementierung einer Baumstruktur.

Übersicht über Programmiersprachen

Anfangs wurde die Entwicklung von Programmiersprachen als Abfolge von Generationen aufgefasst (binäre Maschinensprache, Assembler, prozedurale Programmiersprache). Irgendwann wurde dies zu unübersichtlich, so dass man besser von Programmier-Paradigmen spricht, was die unterschiedliche Herangehensweise an ein zu lösendes Problem ausdrücken soll. Die wichtigsten Paradigmen sind: imperative Programmierung, deklarative Programmierung, funktionale Programmierung, objekt-orientierte Programmierung. Näher erläutert werden hier die strukturierte Programmierung (als Weiterentwicklung der imperativen Programmierung) und die objekt-orientierte Programmierung.

Einführung in die Programmierung: Fundamentale Datentypen

In der Erstellung von Algorithmen konzentriert man sich zunächst auf die Abfolge der Befehle, die in ihrer Gesamtheit das gegebene Problem (meist die Berechnung von Ausgabewerten aus Eingabewerten) lösen. Dabei gerät man schnell zur Frage, wie dabei auftretende veränderliche Größen modelliert werden. Jede Programmiersprache bietet dazu fundamentale Datentypen an, auf denen gewisse Operationen ausgeführt werden können (wie etwa die ganzen Zahlen zusammen mit den Grundrechenarten). Vorgestellt werden hier fundamentale Datentypen wie ganze Zahlen, Gleitkommazahlen, logische Werte und Zeichen. Zu ihrem besseren Verständnis ist es nötig, in Grundzügen die Speicherorganisation kennenzulernen.

Pseudocode und formale Sprachen

Die umgangssprachliche Formulierung eines Algorithmus sollte man nur verwenden, um sich zu übereugen, ob man die Problemstellung verstanden hat. Um die Strukturelemente eines Algorithmus hervorzuheben und damit die Programmierung vorzubereiten, ist eine Formulierung im Pseudocode vorzuziehen. Damit ist man schon näher an einer formalen Sprache, in der eine strenge Syntax eingehalten werden muss und Mehrdeutigkeiten wie in einer natürlichen Sprache nicht vorkommen.

Pseudocode und formale Sprachen

Eigenschaften von R und Vorbereitungen

Um R-Programme schreiben und ausführen zu können, sind einige Vorbereitungen nötig: Installation von R, Installation einer Entwicklungsumgebung, Anlegen und Strukturierung eines Arbeitsverzeichnisses. Diese Vorbereitungen und kleine erste Programme werden für den Programmier-Einsteiger erläutert. Weiter werden viele Hinweise gegeben, wie man sich das Arbeiten mit R erleichtern kann.

Übersicht über Datentypen in R

Die Programmiersprache R besitzt ihr eigenes Konzept, wie die eingebauten Datentypen aufgebaut sind; es unterscheidet sich von vielen anderen Programmiersprachen darin, dass es nicht elementaren Datentypen gibt (wie Zahlen, Zeichen und logische Werte) und zusammengesetzte Datentypen (also zum Beispiel Vektoren von Zahlen). Sondern es gibt nur Vektoren; eine Zahl ist dann ein Spezialfall eines Vektors der Länge 1. Neben den Vektoren gibt es sehr viele weitere vorbereitete Datentypen, so dass man als Programmierer erst für sehr spezielle Anwendungen eigene Datentypen definieren muss. Es wird eine Übersicht über die Datentypen in R gegeben sowie die Vorgehensweise beschrieben, wie man mit ihnen vertraut werden kann.

Einführung in R: Zahlen und Variablen

In R gibt es eigentlich keine elementaren Datentypen (wie Zahlen, logische Werte oder Zeichen), sondern nur Vektoren. Um die Rechenoperationen (Grundrechenarten, insbesondere Division mit Rest, wissenschaftliche Funktionen) für Zahlen besser kennenzulernen, werden hier Zahlen wie elementare Datentypen behandelt. Zur Unterscheidung von ganzen Zahlen und Gleitkommazahlen benötigt man die Konzepte Modus und Speicher-Modus. Es werden erste Beispiele gezeigt, wie man in R mit Variablen umgeht.

Objekt-orientiertes Design in C++: Datenkapselung und UML-Diagramme

Mit den drei Zugriffs-Spezifikationen (access modifier) public, protected und private wird festgelegt, welche Klasse auf welche Datenelemente und Methoden zugreifen kann. Mit ihrer Hilfe lässt sich die Datenkapselung realisieren. Die Zugriffs-Spezifikation ist ein Bestandteil der Deklaration von Datenelementen und Methoden; es wird gezeigt, wie man die Deklarationen einer Klasse übersichtlich in einem UML-Diagramm darstellen kann. UML-Diagramme sind somit eines der wichtigsten Hilfsmittel beim Entwurf komplexer Programme.

Wiki-Syntax Teil 3: Spezielle Textauszeichnungen

Mit der in JBerries verwendeten Wiki-Syntax können Links auf Inhalte von JBerries und auf spezielle Kapitel-Überschriften gesetzt werden. Externe Links werden dagegen nur im Klartext dargestellt. Beim Einbinden von Graphiken muss zwischen üblichen Graphik-Formaten (wie jpg oder png) und Vektorgraphiken (svg) unterschieden werden.

C++: Konstruktoren und Destruktoren

Ein Konstruktor legt fest, welche Aktionen beim Erzeugen eines Objektes ausgeführt werden und sind daher ein zentraler Bestandteil einer Klasse. Wie Methoden können sie überladen werden. Die Eigenschaften von Konstruktoren (und des Destruktors, der beim Löschen eines Objektes aufgerufen wird), einige spezielle Konstruktoren (Default-Konstruktor, Kopier-Konstruktor) sowie das Delegations-Prinzip werden hier vorgestellt.

C++: Grundlagen der objektorientierten Programmierung (OOP)

Die zentralen Begriffe zum Verständnis der objekt-orientierten Programmierung sind Klassse und Objekt: Die Klasse ist der allgemeine Bauplan für die konkreten Objekte. Gezeigt wird die Syntax in C++, mit der Klassen angelegt werden, ihre Datenelemente und Methoden definiert werden, wie konkrete Objekte erzeugt werden und wie diese in anderen Programmen genutzt werden.

Spezielle Konzepte der strukturierten Programmierung in C++: call by reference, Rekursion, Function Templates

Funktionsaufrufe können in C++ entweder mit call by value oder call by reference realisiert werden; beide werden vorgestellt und diskutiert. Rekursionen ermöglichen oft schlanke Quelltexte, die aber schwerer verständlich sind als die entsprechende Implementierung mit Schleifen; einige Beispiele sollen an die Verwendung von Rekursionen heranführen. Die sogenannten Function Templates werden in der C++-Standard-Bibliothek oft eingesetzt; sie sind in einem gewissen Sinn eine Verallgemeinerung des Überladens von Funktionen.

C++: Strukturierte Programmierung mit Funktionen

Strukturierte Programmierung heißt vor allem, dass man wiederkehrende Quelltexte zu Unterprogrammen (Funktionen) zusammenfasst. Dieser Abschnitt zeigt, wie Funktionen in C++ realisiert werden (genauer: wie sie definiert und aufgerufen werden). Die Quelltexte lassen sich besser strukturieren, wenn man die Definition einer Funktion in Deklaration und Implementierung aufteilt. Weiter wird das Überladen von Funktionen besprochen.

Weitere Konzepte der strukturierten Programmierung in C++: Einsatz von Vektoren, Gültigkeitsbereiche

Um Beispiele zur strukturierten Programmierung zu zeigen, werden einige Funktionen vorgestellt, die mit den Klassen vector und array aus der Standard-Bibliothek arbeiten. Weiter wird anhand der Beispiele das Konzept des Gültigkeitsbereiches näher erläutert, insbesondere werden Eigenschaften und Einsatz-Möglichkeiten von lokalen Variablen, globalen Variablen und lokalen static-Variablen diskutiert.

Elementare Syntax von C++: Schleifen

Wie im entsprechenden Kapitel zur Einführung in die Programmierung werden hier die kopfgesteuerte Schleife, die fußgesteuerte Schleife und die Schleife mit Zählvariable besprochen und einige Spitzfindigkeiten erklärt, die die C++-Syntax dazu bereithält. Weiter wird anhand der Schleifen das sehr viel weiter reichende Konzept des Gültigkeitsbereiches (scope) einer Variable vorgestellt.

Kennenlernen der Entwicklungsumgebung Code::Blocks

Die Entwicklungsumgebung Code::Blocks bietet mehrere Möglichkeiten, eine neue Datei oder ein neues Projekt anzulegen; die für den Anfänger relevanten Möglichkeiten werden vorgestellt. Zudem kann man sehr viel produktiver arbeiten, wenn man die in der Entwicklungsumgebung enthaltenen Helfer kennt (Syntaxhervorhebung, Syntax-Vervollständigung, Code-Refactoring, Code-Schnipsel).

Elementare Syntax von C++: Ein- und Ausgaben über die Konsole

Für die ersten Programme bietet es sich an, Ausgaben und Einagben über die Konsole zu machen. Die zugehörigen Befehle in C++ werden hier erläutert. Zugleich werden die Programmbeispiele verwendet, um zahlreiche weiterreichende Konzepte zu erklären: Präprozessor-Direktive, Kommentare, Namensräume, die besondere Bedeutung der main()-Methode, der Rückgabewert einer Funktion, Quelltextformatierung.