|
#define DEBUG 1
#if DEBUG
#define ANFANG(Funktion) \
printf("Start %s [%s:%d]\n", Funktion, __FILE__, __LINE__);
#define ENDE(Funktion) \
printf("Ende %s [%s:%d]\n", Funktion, __FILE__, __LINE__);
#else
#define ANFANG(Funktion)
#define ENDE(Funktion)
#endif
float Endkapital (float Einz, float Zins, float Zeit);
main ()
{
printf ("Endkapital ... : %.2f DM", Endkapital (1000, 10, 2));
return (0);
}
/* Rekursive Berechnung des Endkapitals */
float Endkapital (float Einz, float Zins, float Zeit)
{
float ergebnis;
ANFANG ("Endkapital")
if (Zeit == 1)
ergebnis = Einz * (1 + Zins/100);
else
ergebnis = (1 + Zins/100) * Endkapital(Einz, Zins, Zeit - 1);
ENDE ("Endkapital")
return(ergebnis);
}
Der Programmlauf ergibt:
Start Endkapital [modrek2.C:31]
Ende Endkapital [modrek2.C:36]
Start Endkapital [modrek2.C:31]
Ende Endkapital [modrek2.C:36]
Endkapital ... : 1210.00 DM
In der Bildschirmausgabe ist zu erkennen, wann das Modul Endkapital() betreten und
wann es verlassen wurde. Weiterhin wird jeweils die aktuelle Zeilennummer ausgegeben.
Analyse
Anfang und Ende der Funktion Endkapital() sind mit ANFANG ("Endkapital")
und ENDE ("Endkapital") versehen worden. Bitte beachten: es folgt kein
Strichpunkt, da dieser bereits im Makro vorhanden ist. Makros werden ja vom Präprozessor
rein textuell ersetzt. Diese Makros haben aber nur dann eine Bedeutung, wenn DEBUG
wahr ist (#define DEBUG 1). In diesem Fall haben die Makros Anfang und Ende
die im #if-Zweig angegebene Bedeutung:
#define ANFANG(Funktion) \
printf("Start %s [%s:%d]\n", Funktion, __FILE__, __LINE__);
#define ENDE(Funktion) \
printf("Ende %s [%s:%d]\n", Funktion, __FILE__, __LINE__);
Anderenfalls haben sie keine Bedeutung, da im #else-Zweig ein leeres Makro
definiert wird. Das Makro muß nur vorhanden sein, damit der Compiler
keinen Fehler meldet:
#define ANFANG(Funktion)
#define ENDE(Funktion)
Diese Technik eignet sich gut zum Debuggen von Quelltext. Solange das Programm noch
nicht einwandfrei läuft, werden so Debuggingzeilen untergebracht. Sobald das Programm
für den Produktions-Betrieb compiliert werden soll, werden diese Zeilen für den
Compilationsvorgang deaktiviert (#define DEBUG 0). Sie werden nicht aus dem
Quelltext herausgenommen, da dies nicht nur Arbeit verursacht, sondern sie bei
Programmänderungen und -erweiterungen auch wieder von Nutzen sein können.
Da die Makroersetztung auf Quellniveau erfolgt, wird auch kein "toter Code" im
Binärprogramm erzeugt. Das Schema läßt sich beliebig erweitern, indem man
beispielsweise auch Variablenwerte "tracen" kann. Durch die Definition eines
weiteren Makros kann man auch den Resultatwert nachverfolgen:
/* Zinseszinsrechnung */
/* Rekursion mit Debugging-Informationen */
/* kaprek.c */
#include
#define DEBUG 1
#if DEBUG
#define ANFANG(Funktion) \
printf("Start %s [%s:%d]\n", Funktion, __FILE__, __LINE__);
#define ENDE(Funktion) \
printf("Ende %s [%s:%d]\n", Funktion, __FILE__, __LINE__);
#define TRACE(Floatvar, Floatwert) \
printf("Variable %s: %f [%s:%d]\n",
Floatvar, Floatwert, __FILE__, __LINE__);
#else
#define ANFANG(Funktion)
#define ENDE(Funktion)
#define TRACE(Floatvar, Floatwert)
#endif
float Endkapital (float Einz, float Zins, float Zeit);
main ()
{
printf ("Endkapital ... : %.2f DM", Endkapital (1000, 10, 2));
return (0);
}
/* Rekursive Berechnung des Endkapitals */
float Endkapital (float Einz, float Zins, float Zeit)
{
float ergebnis;
ANFANG ("Endkapital")
if (Zeit == 1)
ergebnis = Einz * (1 + Zins/100);
else
ergebnis = (1 + Zins/100) * Endkapital(Einz, Zins, Zeit - 1);
TRACE("ergebnis", ergebnis)
ENDE ("Endkapital")
return(ergebnis);
}
|
|
|