Wie entsteht ein Programm 1/9
1. Schritt: Programmentwurf Der wichtigste Teil beim Erstellen eines Programms ist der Programmentwurf. Dabei wird das vorgegebene Problem analysiert, es wird ermittelt, welche Eingangsinformationen zur Problemlösung notwendig sind. Als nächstes versucht man, das Problem in einzelne Teilprobleme zu zerlegen, die dann in separaten Funktionen oder bei größeren Projekten in eigenen Programmmodulen realisiert werden können. Für diese Teilprobleme muß dann ein geeigneter Algorithmus gefunden werden. Meist gibt es dafür mehrere Wege, oft erweist sich ein gewählter Weg später als ungünstig und muß abgeändert werden. Der Programmentwurf ist der schwierigste Teil der Programmierung. Fehler, die in dieser Phase gemacht werden kann man später nur mit großem Aufwand korrigieren und führen meist zu einem kompletten Redesign des Programms. Dieser Schritt der Programmerstellung geschieht am Schreibtisch, nicht am Rechner!! 2/9
2.Schritt: Codierung Ist die Programmstruktur klar und stehen die Algorithmen fest, so wird mit Hilfe eines Editors der Programmcode erstellt und in der sogenannten Quelldatei oder Source-Datei als ASCII-Text abgelegt. Editor: Der Editor ist ein Textverarbeitungsprogramm, das die speziellen Bedürfnisse beim Programmieren berücksichtigt. Prinzipiell ist jedes Textverarbeitungssystem als Programmeditor verwendbar, allerdings sollte ein vernünftiger Editor folgende Eigenschaften besitzen: Textteile sollten kopiert, verschoben oder gelöscht werden können Eine Suchen + Ersetzen -Funktion sollte vorhanden sein, wobei verschiedene Suchvarianten z.b. mit Wildcards sehr nützlich sind. Eine Anzeige der aktuellen Zeile und Spalte ist notwendig, um die Fehlermeldungen des Compilers leicht zuordnen zu können Der Editor sollte mehrere Texte gleichzeitig in verschiedenen Fenstern bearbeiten können. Manche Editoren zeigen z.b. die Fehlermeldungen des Compilers in einem eigenen Fenster an und springen bei der Auswahl einer Fehlermeldung sofort an die entsprechende Position im Sourcecode. Der Editor sollte ohne große Einarbeitungsphase für die Basisfunktionen leicht bedienbar sein. Bei Bedarf kann man sich dann die erweiterten Funktionen aneignen. Idealerweise ist ein Editor language sensitive ; d.h. er ist auf eine Programmiersprache zugeschnitten. Solche Editoren erkennen z.b. Kommentare, Sprachelemente, Konstanten oder Variablen und unterlegen sie mit unterschiedlichen Farben. Oft erkennen solche Editoren auch zusammengehörige Klammernpaare oder führen selbständig Einrückungen im Programm durch. 3/9
3.Schritt: Compilieren Die Übersetzung des Quellprogramms geschieht mit Hilfe eines Compilers. Der Compiler ist ein Programm, das die Quelldatei einliest, das Einhalten der Syntaxregeln einer Programmiersprache überprüft und daraus eine Datei erzeugt, die die Maschinenbefehle für den entsprechenden Prozessor enthält. Diese Datei heißt Object-Datei und hat üblicherweise dei Endung.o. Neben diesem eigentlichen Ausgangsprodukt des Compilers werden wahlweise zusätzliche Dateien erzeugt, z.b. eine List-Datei, die neben dem mit Zeilennummern versehenen Quelltext die Übersetzungsfehler enthält, oder eine Assembler-Datei, die einen aus dem Quelltext generierten Assemblercode enthält. Der Compiler kann beim Aufruf über eine Reihe von Optionen gesteuert werden. Beim dem GNU-Compiler gcc, der in dem Praktikum verwendet wird, bedeuten z.b.: gcc c hello.c -o hello.o hello.c wird übersetzt, die Option -o benennt die Ausgangsdatei in hello.o gcc hello.c -S es wird ein Assemblerlisting erzeugt gcc c hello.c -Wall -g die Option -Wall schaltet alle Warnungshinweise ein, d.h. auf verdächtige Programmkonstruktionen, die nicht direkt ein Fehler sind, wird hingewiesen (z.b. Verwenden einer nicht initialisierten Variablen). -g erzeugt Zusatzinformationen für den Debugger 4/9
4.Schritt: Linken (Verbinden) Ist das Programm fehlerfrei übersetzt, so wird aus allen Objekt-Dateien, die zu einem Programm gehören, ein lauffähiges Programm generiert. Diese Aufgabe übernimmt ein weiteres Programm, der sogenannte Linker. Die Objekt-Dateien bestehen aus dem vorher übersetzten, selbst erstellten C-Programm sowie den verwendeten Programmbibliotheken, deren Quellcode meist gar nicht vorliegt. Bei größeren Programmen werden meist mehrere einzelne Teilprogramme erstellt und separat übersetzt und getestet. Diese Teilprogramme werden ebenfalls beim Linken zum lauffähigern Programm zusammengebunden. Der Aufruf des Linkers erfolgt am einfachsten über den Compileraufruf. So bindet der Aufruf gcc hello.o -o hello.exe die Objekt-Datei hello.o und die Standardbibliothek zum lauffähigen Programm hello.exe. 5/9
5.Schritt: Testen Ein Programm ist in den seltesten Fällen auf Anhieb fehlerfrei ( oft sind auch ausgetestete Programme nicht fehlerfrei). Beim Programmieren gibt es zwei Arten von Fehlern: Syntaxfehler Diese Fehler entstehen durch das Verletzen der Regeln einer Programmiersprache. Syntaxfehler erkennt der Compiler und meldet sie unter Angabe der Fehlerursache und des Fehlerortes. Solche Fehler sind sehr leicht zu beheben. semantische Fehler, Laufzeitfehler Solche Fehler treten auf, wenn vom Programmierer Sonderfälle nicht bedacht wurden, wenn falsche Eingaben nicht abgefangen werden, wenn allgemein gesagt das Programm nicht das tut, was sich der Programmierer bei der Programmerstellung gedacht hat. Solche Fehler treten erst zur Laufzeit eines Programms auf. Ein Werkzeug, um solche Fehler zu analysieren und den Ablauf eines Programms nachzuvollziehen ist ein Debugger. 6/9
Debugger Der Name kommt von Bug (Käfer, Wanze) mit dem im englischen Sprachgebrauch Fehler in Programmen bezeichnet werden. Mit Hilfe eines Debuggers wird ein lauffähiges Programm getestet. Typische Funktionen eines Debuggers sind: Setzen von Breakpoints. Das Programm wird an bestimmten Stellen angehalten, um die Werte von Variablen zu untersuchen oder um Festzustellen, unter welchen Bedingungen das Programm einen Breakpoint erreicht hat Beobachten von Variablen Single-Step Betrieb. Damit kann ein Programm sozusagen in Zeitlupe ablaufen. Nach Ausführung jedes Befehls wird das Programm angehalten. So kann die Auswirkung jedes Befehls analysiert werden. Anzeigen des Aufrufstacks von ineinander aufgerufenen Unterprogrammen Mit Hilfe eines Debuggers wird der Ablauf eines Programms sichtbar. Die Verwendung eines Debuggers ist daher nicht nur für die Fehlersuche sehr wichtig. Der Einsatz eines Debuggers bietet einem Programmieranfänger eine gute Hilfe zum Verständnis und zum Nachvollziehen eines Algorithmus. Der Debugger sollte dazu aber ein sogennanter Source-Level Debugger sein, d.h. er verwendet die vom Programmierer verwendeten Variablennamen und verwendet beim Setzen und Anzeigen von Breakpoints den vom Programmierer erstellten Programmcode und nicht auf den daraus übersetzten Assembler oder Maschinencode. Ein Beispiel eines solchen Debuggers ist der Gnu-Debugger gdb. 7/9
Die Werkzeuge bei der Programmentwicklung Idee Editor Source-Datei "hello.c" Compiler Include-Dateien z.b. stdio.h Object-Datei "hello.o" Linker Bilbliothek z.b. stdlib.a Debugger ausführbares Programm "hello.e" 8/9
Entwicklungsumgebung Idee Editor Source-Datei "hello.c" Compiler Include-Dateien z.b. stdio.h Object-Datei "hello.o" Linker Bilbliothek z.b. stdlib.a Debugger ausführbares Programm "hello.e" 9/9