Regionales Rechenzentrum für Niedersachsen
Programmierung mit C
Modularisierung von Programmen. Präprozessor-Anweisungen nutzen.
Programmieren mit C | 19.03.07 | Folie 2Regionales Rechenzentrum für Niedersachsen
Modularisierung
Zerlegung eines Programms in überschaubare Einheiten Die einzelnen Einheiten werden als Modul bezeichnet. Bei der Kompilierung des Programms werden die verschiedenen Module
in einem Programm zusammengeführt. Die verschiedenen Module können über Schnittstellen Daten
austauschen. Schnittstellen zwischen den Modulen sollten vor Beginn der
Programmierung definiert werden. Schnittstellen sollten klar und eindeutig für alle definiert sein.
... ist ein Merkmal der strukturierten Programmierung.
Programmieren mit C | 19.03.07 | Folie 3Regionales Rechenzentrum für Niedersachsen
Header-Dateien und Code-Dateien
Zusammengehörige Header- und Code-Dateien sollten den gleichen Namen besitzen.
Beide Dateien besitzen unterschiedliche Dateiendungen: Eine Header-Datei hat die Endung ".h". Die Code-Datei besitzt die Endung ".c".
Eine Header-Datei ist eine Art Inhaltsverzeichnis für die Code-Datei. Sie definiert alle Elemente, die in einer Code-Datei benötigt werden. Konstanten und Variablen werden wie gewohnt deklariert. Statische Variablen sind nicht erlaubt. Funktionen werden als Prototypen deklariert.
Programmieren mit C | 19.03.07 | Folie 4Regionales Rechenzentrum für Niedersachsen
Modularisierung
#include "modul.h"
int main(void){ ausgabe(); return 0;}
void ausgabe(void);modul.h
modul.c#include <stdio.h>void ausgabe(void){ printf("Hello\n");}
Start
Programmieren mit C | 19.03.07 | Folie 5Regionales Rechenzentrum für Niedersachsen
Vorteile
Quelltexte werden überschaubarer. Die Fehlersuche ist in kleinen, überschaubaren Einheiten einfacher. Die
Suche nach Fehlern kann auf einzelne Module beschränkt werden. Die Fehlerbehebung in einem Modul zieht keine weiteren Abstürze im
weiteren Programm hinter sich her. Falls Schnittstellen definiert sind, kann jedes Modul von einen anderen
Team erstellt werden. Jedes Modul für sich kann kompiliert werden und erst nach dem alle
Fehler beseitigt sind, wird das gesamte Programm kompiliert. Die Wartung der verschiedenen Module ist einfacher. Einzelne Module können in anderen Projekten wiederverwendet werden.
Programmieren mit C | 19.03.07 | Folie 6Regionales Rechenzentrum für Niedersachsen
Projekte erstellen
Entwicklungsumgebung: Erstellen eines Projekts. Dem Projekt werden alle benötigen Code-Dateien hinzugefügt. Die Code-Dateien können kompiliert werden. Falls die Code-Dateien fehlerfrei sind, wird das gesamte Projekt kompiliert
und anschließend gestartet. ... mit Hilfe des Compilers gcc:
Die Quelldateien werden geschrieben. Jede Quelldatei löst ein Teilbereich des Algorithmus.
Mit Hilfe von gcc - Name_des_Programms.c werden die einzelnen Quelldateien kompiliert. Die einzelnen Dateien werden übersetzt. Anschließend befinden sich Objektdateien [Name_des_Programm.obj] im Verzeichnis, in dem kompiliert wurde.
Mit Hilfe der Anweisung gcc -o Name_der_Datei.exe Objektdatei01 Objektdatei02 Objektdatei03 werden die einzelnen Objektdateien zu einer ausführbaren Datei gelinkt.
Programmieren mit C | 19.03.07 | Folie 7Regionales Rechenzentrum für Niedersachsen
Objektdatei erstellen
source1.c
source2.c
source3.c
makefile
Präprozessor
Übersetzer(Compiler)
Assembler
Compiler
Objektdatei.obj
Header.h
Programmieren mit C | 19.03.07 | Folie 8Regionales Rechenzentrum für Niedersachsen
Ausführbare Datei erstellen
objekt1.obj
objekt.obj Linker programm.exe
Bibliotheken(library.dll,library.lib)
Programmieren mit C | 19.03.07 | Folie 9Regionales Rechenzentrum für Niedersachsen
Hauptprogramm
#include <stdio.h>#include "kreisBerechnen.h"int main(){
float radius;float umfang;float flaeche;printf("Bitte geben Sie einen Radius ein: ");scanf("%f", &radius);
flaeche = KreisFlaeche(radius);umfang = KreisUmfang(radius);printf("\n\nRadius: %f \n Umfang: %f \n Flaeche: %f \n",
radius, umfang, flaeche);
return 0;}
In dieser Zeile wird die, vom Programmierer erstellte Header-Datei eingebunden. Durch die Anführungsstriche wird dem Compiler signalisiert, dass die Header-Datei im Verzeichnis des Programms zu finden ist.
Programmieren mit C | 19.03.07 | Folie 10Regionales Rechenzentrum für Niedersachsen
Header-Datei
#include<stdio.h>#define PI 3.141592;float KreisFlaeche(float);float KreisUmfang(float);
Mit Hilfe von #define wird eine Konstante definiert.Der Präprozessor ersetzt die Bezeichnung durch den angegebenen Wert.
Prototypen der zu definierenden Funktionen.
Programmieren mit C | 19.03.07 | Folie 11Regionales Rechenzentrum für Niedersachsen
Code-Datei
#include "kreisBerechnen.h"float KreisFlaeche(float radius){
float flaeche;flaeche = (radius * radius) * PI;return flaeche;
}float KreisUmfang(float radius){
float umfang;umfang = 2 * radius * PI;return umfang;
}
Die Funktionen werden in einer eigenen Quelldatei gespeichert und nicht mehr im Start.Die, in der Header-Datei, deklarierten Funktionen werden hier definiert.Die Prototypen werden mit Hilfe der Header-Datei eingebunden.Das Modul kann auch eigenständig kompiliert werden.
Programmieren mit C | 19.03.07 | Folie 12Regionales Rechenzentrum für Niedersachsen
Gültigkeit von Variablennamen
Welche Variablen sind wo im Programm bekannt? Möglichkeiten:
Global im gesamten Projekt / Programm. Global in einem Modul. Lokal in einer Funktion. Lokal innerhalb eines Blocks, deren Anfang und Ende durch die geschweiften
Klammern gekennzeichnet ist. Eine lokale Variable in einer Funktion überdeckt eine globale Variable
gleichen Namens. Eine lokale Variable in einem Block überdeckt eine globale Variable
gleichen Namens sowie lokale Namen in umgebenden Blöcken.
Programmieren mit C | 19.03.07 | Folie 13Regionales Rechenzentrum für Niedersachsen
Globale Variablen
... werden außerhalb von Funktionen definiert. Auf globale, definierte Variablen kann von überall her zugegriffen werden. Globale Variablen, die in anderen Modulen definiert sind, müssen vor dem
ersten Zugriff bekannt gemacht werden. extern int summe; extern float umfang;
... sollten nicht eingesetzt werden, weil ... der Zusammenhang zwischen Variablen und dem Programmcode, in dem
sie definiert sind, verloren geht. ... Variablen von Funktionen verändert werden können, ohne das der Aufruf
dies erwartet. Diese Effekte werden als Seiteneffekte bezeichnet. ... Änderungen der Variablen alle Programmteile betrifft, in denen sie genutzt
werden.
Programmieren mit C | 19.03.07 | Folie 14Regionales Rechenzentrum für Niedersachsen
Externe Variablen oder Funktionen
Zugriff von einer beliebigen Position im Programm auf eine Funktion oder Variable, die in einem anderen Modul definiert ist.
Externe Variablen können nicht initialisiert werden, weil sie nur auf eine Variable verweisen, die anderswo definiert wird.
Die Lebensdauer erstreckt sich auf die gesamte Laufzeit des Programms.
Programmieren mit C | 19.03.07 | Folie 15Regionales Rechenzentrum für Niedersachsen
Externe Funktionen
#include <stdio.h>
extern void modul01(void);extern void modul02(void);
int main(void) {
modul01( );modul02( );return 0;
}
#include <stdio.h>
void modul01(void) {printf("Modul01\n");
}
#include <stdio.h>
void modul02(void) {printf("Modul02\n");
}
Programmieren mit C | 19.03.07 | Folie 16Regionales Rechenzentrum für Niedersachsen
Präprozessor nutzen
Der Präprozessor ist Bestandteil des Compilers. Bevor das Programm kompiliert wird, werden mit Hilfe des
Präprozessors bestimmte Bereiche eines C-Programms übersetzt Ein Präprozessor kann
... Header- und Quelldateien in den Quelltext kopieren, ... symbolische Konstanten einbinden, ... eine bedingte Kompilierung durchführen, .. String-Literale zusammenfassen, ... Zeilenumbrüche, die mit einem Backslash beginnen, entfernen, ... Kommentare durch Leerzeichen ersetzen und ... viele Dinge mehr.
Programmieren mit C | 19.03.07 | Folie 17Regionales Rechenzentrum für Niedersachsen
Präprozessor-Anweisungen
... stehen meist am Anfang einer Quelldatei oder Header-Datei. ... beginnen immer mit einem Hash (#). ... enden nicht mit einem Semikolon. ... stehen nicht mit anderen Anweisungen in einer Zeile. Pro Zeile ist nur eine Präprozessor-Anweisung zulässig.
#include <stdio.h>#define DKR 7.45239
int main(void) {double zahl;zahl = 2.0 * DKR;printf("2 Euro = %f DKR", zahl);return 0;
}
Programmieren mit C | 19.03.07 | Folie 18Regionales Rechenzentrum für Niedersachsen
Module mit #include einbinden
#include ist durch das Hash-Zeichen als Präprozessor-Anweisung gekennzeichnet.
Die #include-Anweisungen wird durch den Code im angegebenen Modul ersetzt.
Alle deklarierten Elemente aus der einzubindenden Datei sind in der Quelldatei bekannt.
Programmieren mit C | 19.03.07 | Folie 19Regionales Rechenzentrum für Niedersachsen
Eigene Module und Standard-Module einbinden
#include <[Header]> ... bindet Header-Dateien der Standard-Bibliothek ein. Es werden nur Header-Dateien aus dem Verzeichnis include des
Compilers oder der Entwicklungsumgebung eingebunden. ... bindet Header-Dateien ein, die vom Compiler oder der
Entwicklungsumgebung geliefert werden. #include "[Header]"
... bindet vom Programmierer erstellte Header-Dateien ein. Häufig liegt die angegebene Header-Datei im aktuellen
Arbeitsverzeichnis. Andernfalls muss der Pfad angegeben werden.
Programmieren mit C | 19.03.07 | Folie 20Regionales Rechenzentrum für Niedersachsen
Beispiel
#include <stdio.h>#include "kreisBerechnen.h"int main(){
float radius;float umfang;float flaeche;printf("Bitte geben Sie einen Radius ein: ");scanf("%f", &radius);
flaeche = KreisFlaeche(radius);umfang = KreisUmfang(radius);printf("\n\nRadius: %f \n Umfang: %f \n Flaeche: %f \n",
radius, umfang, flaeche);
return 0;}
Programmieren mit C | 19.03.07 | Folie 21Regionales Rechenzentrum für Niedersachsen
Standard-Header-Dateien
Header-Dateiassert.hctype.herrno.hfloat.hlimits.hlocale.h
Programmieren mit C | 19.03.07 | Folie 22Regionales Rechenzentrum für Niedersachsen
Module einmalig einbinden
#include <stdio.h>#ifndef MODUL_H
#define MODUL_Hextern int kreisumfang;int UmfangBerechne(int);
#endif
#define SYMBOL definiert eine symbolische Konstante. #ifnddef
... ist vergleichbar mit if not. ... bedeutet "Wenn die symbolische Konstante nicht definiert ist".
Falls die symbolische Konstante nicht definiert ist, wird einmalig eine externe Variable und ein Funktionsprototypen für das gesamte Programm definiert.
Programmieren mit C | 19.03.07 | Folie 23Regionales Rechenzentrum für Niedersachsen
Symbolische Konstanten
#define Bezeichner Zeichenfolge Die symbolische Konstante wird im Quellcode durch den Präprozessor
mit der angegebenen Zeichenfolge ersetzt. Die assoziierte Zeichenfolge kann auch mit früher definierten
symbolischen Konstanten gebildet werden. Wenn eine Zeile mit einem Backslash abgeschlossen wird, kann der
Ersatztext in der nächsten Zeile fortgesetzt werden. Für symbolische Konstanten werden häufig Großbuchstaben genutzt.
Alle #define-Anweisungen werden am Anfang eines Programms oder in einer separaten Header-Datei aufgeführt.
Programmieren mit C | 19.03.07 | Folie 24Regionales Rechenzentrum für Niedersachsen
Beispiel: Symbolische Konstanten nutzen
#include <stdio.h>#define ROT -1#define GREEN 1#define FEHLER "Standard-Fehler"
#define GELB ROT + GREEN
#define FEHLERAUSGABE "Bei der \ Ausgabe ist ein Fehler aufgetreten"
void func(void){ int ampel; printf(FEHLER); ampel = ROT;}
Symbolischen Konstanten wird ein Wert zugewiesen. Im Programm wird zum Beispiel GREEN durch 1 ersetzt.
Der Wert wird mit Hilfe von symbolischen Konstanten berechnet.
Der lange Text wird mit Hilfe des Backslash umgebrochen.
Programmieren mit C | 19.03.07 | Folie 25Regionales Rechenzentrum für Niedersachsen
Beispiel: Symbolische Konstanten nutzen
#include <stdio.h>#define ROT -1#define GREEN 1#define GELB ROT + GREEN#define FEHLER "Standard-Fehler"#define FEHLERAUSGABE "Bei der \
Ausgabe ist ein Fehler aufgetreten"void func(void){ int ampel;
printf(FEHLER); ampel = ROT;}
Programmieren mit C | 19.03.07 | Folie 26Regionales Rechenzentrum für Niedersachsen
Beispiel: Bedingungen nutzen
#include <stdio.h>#define ENGLISCH#if defined(DEUTSCH) #define whichLanguage() printf("Willkommen ...")#elif defined(ENGLISCH) #define whichLanguage() printf("Welcome ...")#else #define whichLanguage() printf("Unbekannten Sprache...")#endifint main(){ /*Universale Routine zur Ausgabe einer Sprache*/ whichLanguage(); return 0;}
Programmieren mit C | 19.03.07 | Folie 27Regionales Rechenzentrum für Niedersachsen
Beispiel: Bedingungen nutzen
#include <stdio.h>#define ENGLISCH#if defined(DEUTSCH) #define whichLanguage() printf("Willkommen ...")#elif defined(ENGLISCH) #define whichLanguage() printf("Welcome ...")#else #define whichLanguage() printf("Unbekannten Sprache...")#endifint main(){ /*Universale Routine zur Ausgabe einer Sprache*/ whichLanguage(); return 0;}
In Abhängigkeit der gesetzten symbolischen Konstante wird ein Willkommenstext ausgegeben.Hier wird keine Zeichenfolge zur Ersetzung der symbolischen Konstanten angegeben.
Programmieren mit C | 19.03.07 | Folie 28Regionales Rechenzentrum für Niedersachsen
Beispiel: Bedingungen nutzen
#include <stdio.h>#define ENGLISCH#if defined(DEUTSCH) #define whichLanguage() printf("Willkommen ...")#elif defined(ENGLISCH) #define whichLanguage() printf("Welcome ...")#else #define whichLanguage() printf("Unbekannten Sprache...")#endifint main(){ /*Universale Routine zur Ausgabe einer Sprache*/ whichLanguage(); return 0;}
Mit Hilfe von defined wird abgefragt, ob eine symbolische Konstante gesetzt ist oder nicht.Falls die Konstante gesetzt ist, wird ein Makro für die Ausgabe definiert.
Programmieren mit C | 19.03.07 | Folie 29Regionales Rechenzentrum für Niedersachsen
Beispiel: Bedingungen nutzen
#include <stdio.h>#define ENGLISCH#if defined(DEUTSCH) #define whichLanguage() printf("Willkommen ...")#elif defined(ENGLISCH) #define whichLanguage() printf("Welcome ...")#else #define whichLanguage() printf("Unbekannten Sprache...")#endifint main(){ /*Universale Routine zur Ausgabe einer Sprache*/ whichLanguage(); return 0;}
Ein Makro wird aufgerufen.
Programmieren mit C | 19.03.07 | Folie 30Regionales Rechenzentrum für Niedersachsen
Funktionen-Makros
#define Makroname(Variable) (Anweisungen). Dem Makronamen werden beliebig viele Argumente übergeben. Diese
Argumente werden durch die wirklichen Argumente im Programm ersetzt.
Mit Hilfe der Argumente wird ähnlich wie in Funktionen ein Wert berechnet.
Die Argumente können beliebig oft auf der rechten Seite verwendet werden.
Auf der rechten Seite stehen die Argumente immer in Klammern. Bei Berechnungen innerhalb von Makros gilt die Punkt-vor-Strich-
Regelung.
Programmieren mit C | 19.03.07 | Folie 31Regionales Rechenzentrum für Niedersachsen
Beispiel
#include <stdio.h>#define MAX(a, b) (a) <= (b) ? (b) : (a)#define KLEINER_10(zahl) ((zahl < 10))void func(int zahl, int wert) { int ergebnis; ergebnis = MAX(zahl, wert)}void func(int zahl) { if (KLEINER_10(zahl)) {
printf("Kleiner");}
}
Programmieren mit C | 19.03.07 | Folie 32Regionales Rechenzentrum für Niedersachsen
Makros oder Funktionen?
Makros: Die Definition eines Makros muss für den Compiler sichtbar sein. Mit jedem Aufruf wird der entsprechende Ersatztext eingefügt und neu
übersetzt. Die ausführbare Datei wird dadurch länger. Die Programmausführung wird schneller, da keine Verzweigung wie in
Funktionen vorhanden sind. Bei Makros sind Seiteneffekte möglich. Der Aufruf QUADRAT(++zahl) wird
durch ((++zahl) * (++zahl) ) ersetzt. zahl wird zweimal inkrementiert und damit entspricht das Produkt nicht dem Quadrat der inkrementierten Zahl.
Funktionen ... können eigenständig übersetzt werden. Der Linker bindet die Funktionen in das Programm ein. Mit jedem Aufruf wird zu der Funktion verzweigt, wodurch sich die
Programmausführung verlangsamt. Die ausführbare Datei ist jedoch kürzer, da der Code der Funktion nur einmal
vorhanden ist. Seiteneffekte sind nicht möglich.
Programmieren mit C | 19.03.07 | Folie 33Regionales Rechenzentrum für Niedersachsen
Makros aufheben
#undef [Makroname] Ein Makroname ist nur so lange gültig, bis dieser mit der #undef-
Anweisung aufgehoben wird. Makros sind nur innerhalb bestimmter Bereiche gültig.
#define MAX 100
#ifdef MAX#undef MAX
#endif
#define MAX 50