Beispiel zu einem kleinen Projekt

Das folgende Beispiel demonstriert ein kleines Projekt, in dem der Quellcode auf zwei Dateien mit einer gemeinsamen Header-Datei verteilt wird. Es werden zwei Funktionen zur sicheren Benutzerabfrage von Zahlen erstellt. Im Folgenden werden die drei Dateien aufgelistet gefolgt von einigen Erläuterungen. Hinter allen unterstrichenen Passagen verbirgt sich weiter unten eine kurze Erläuterung; einfach anklicken.


Die Headerdatei get.h

/****************************************************************/
/* Two functions that read double- and int-values from user.    */
/* This is to demonstrate a mini project.                       */
/* author: Robert Hess                                          */
/* date: December 22nd 2007                                     */
/* version 1.00                                                 */
/* filename: get.h                                              */
/****************************************************************/

#ifndef FUNCTIONS_GET_FROM_USER_BY_ROBERT_HESS_INCLUDED
#define FUNCTIONS_GET_FROM_USER_BY_ROBERT_HESS_INCLUDED

double getDouble(char *text, double min, double max,
                 double oldValue);
int getInt(char *text, int min, int max, int oldValue);

#endif /*#ifndef FUNCTIONS_GET_FROM_USER_BY_ROBERT_HESS_INCLUDED*/

Die Quellcodedatei get.c

/****************************************************************/
/* Two functions that read double- and int-values from user.    */
/* This is to demonstrate a mini project.                       */
/* author: Robert Hess                                          */
/* date: December 22nd 2007                                     */
/* version 1.00                                                 */
/* filename: get.c                                              */
/****************************************************************/

#include "get.h"
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

/* All messages are collected here: */
#define OLD_VALUE "alter Wert"
#define TYPE_A_NUMBER "Das war keine Zahl"
#define OUT_OF_RANGE "Die Zahl liegt au\341erhalb des "\
                     "g\201ltigen Bereiches!"

/* Reads a double value from the user. */
double getDouble(char *text, double min, double max,
                 double oldValue)
{
    char line[51];      /* user input line */
    double newValue=0;  /* new user input value */
    int finished=0;     /* flag for correct input */

    do {
        /* print user request */
        printf("%s (%g - %g, %s: %g): ", text, min, max,
            OLD_VALUE, oldValue);

        /* get user input */
        fgets(line, 50, stdin);

        /* if user pressed ENTER only use old value */
        if(*line=='\n') {
            newValue = oldValue;
            finished = 1;

        /* check if user typed a number */
        } else if(sscanf(line, "%lf", &newValue)!=1)
            printf("%s!\n", TYPE_A_NUMBER);

        /* check range */
        else if(newValue<min || newValue>max)
            printf("%s!\n", OUT_OF_RANGE);

        /* number is correct */
        else finished = 1;

    /* repeat until finished */
    } while(!finished);

    /* return new value */
    return newValue;
}

/* Reads a int value from the user. */
int getInt(char *text, int min, int max, int oldValue)
{
    char line[51];      /* user input line */
    int newValue=0;     /* new user input value */
    int finished=0;     /* flag for correct input */

    do {
        /* print user request */
        printf("%s (%d - %d, %s: %d): ", text, min, max,
            OLD_VALUE, oldValue);

        /* get user input */
        fgets(line, 50, stdin);

        /* if user pressed ENTER only use old value */
        if(*line=='\n') {
            newValue = oldValue;
            finished = 1;

        /* check if user typed a number */
        } else if(sscanf(line, "%d", &newValue)!=1)
            printf("%s!\n", TYPE_A_NUMBER);

        /* check range */
        else if(newValue<min || newValue>max)
            printf("%s!\n", OUT_OF_RANGE);

        /* number is correct */
        else finished = 1;

    /* repeat until finished */
    } while(!finished);

    /* return new value */
    return newValue;
}

Die Quellcodedatei main.c

/****************************************************************/
/* Two functions that read double- and int-values from user.    */
/* This is to demonstrate a mini project.                       */
/* author: Robert Hess                                          */
/* date: December 22nd 2007                                     */
/* version 1.00                                                 */
/* filename: main.c                                             */
/****************************************************************/

#include "get.h"
#include <stdio.h>

int main()
{
    double d=3.141; /* a double-value */
    int i=8;        /* an integer-value */

    /* get a double-value from user */
    d = getDouble("Bitte geben Sie eine Zahl ein", 1.2, 4.5, d);
    printf("Sie haben folgenden Wert eingegeben: %g\n\n", d);

    /* get a int-value from user */
    i = getInt("Bitte geben Sie eine Zahl ein", 5, 10, i);
    printf("Sie haben folgenden Wert eingegeben: %d\n\n", i);

    return 0;
}

Verwendung unter Microsoft Visual Studio 2015

Mit den folgenden Schritten können Sie das Mini-Projekt unter Microsoft Visual Studio 2015 zum Laufen bringen. Es wird von einer deutschen Installation ausgegangen; bei andersprachigen Installationen müssen die Befehle sinngemäß übersetzt werden.

  1. Starten Sie Visual Studio, estellen Sie mit Datei->Neu->Projekt... eine Win32-Konsolenanwendung, geben Sie ihr einen sinnvollen Namen, wählen Sie den Speicherort aus und klicken Sie Ok.
  2. Im folgenden Dialog klicken Sie auf Weiter >.
  3. Im folgenden Dialog aktivieren Sie die Option Leeres Projekt und klicken dann auf Fertig stellen.
  4. Wählen Sie im Menü Projekt->Neues Element hinzufügen..., wählen Sie dann Headerdatei (.h), vergeben Sie den Dateinamen get.h und klicken Sie auf Hinzufügen.
  5. Kopieren Sie in die gerade erstellte Datei den weiter oben auf dieser Seite gezeigten Inhalt für get.h.
  6. Wählen Sie im Menü Projekt->Neues Element hinzufügen..., wählen Sie dann C++-Datei (.cpp), vergeben Sie den Dateinamen get.c und klicken Sie auf Hinzufügen. (Hinweis: Durch die Dateiendung .c wird dem Compiler mitgeteilt, dass es sich um eine C-Datei und nicht um eine C++-Datei handelt.)
  7. Kopieren Sie in die gerade erstellte Datei den weiter oben auf dieser Seite gezeigten Inhalt für get.c.
  8. Wählen Sie im Menü Projekt->Neues Element hinzufügen..., wählen Sie dann C++-Datei (.cpp), vergeben Sie den Dateinamen main.c und klicken Sie auf Hinzufügen.
  9. Kopieren Sie in die gerade erstellte Datei den weiter oben auf dieser Seite gezeigten Inhalt für main.c.
  10. Jetzt kann das Projekt übersetzt und gestartet werden.

Zwei Quellcode-Dateien

In dem hier gezeigten Beispiel ist der Quellcode auf zwei Dateien verteilt. Die Datei get.c beinhaltet die beiden Funktionen getDouble() und getInt(). In der Datei main.c ist nur das Hauptprogramm main() implementiert, welche die beiden anderen Funktionen verwendet.

Die Header-Datei

Die Header-Datei get.h stellt das Bindeglied zwischen den beiden Quellcode-Dateien dar. In ihr stehen die Deklarationen (Ankündigungen) der Funktionen getDouble() und getInt(). Die Header-Datei wird in alle Quellcode-Dateien eingebunden, welche getDouble() und getInt() verwenden.

Einbinden der Header-Datei

Die Header-Datei wird mit dem Präprozessorbefehl #include eingebunden. Der Präprozessor entfernt die Zeile selbst, und fügt dafür den gesammten Inhalt der Header-Datei ein.

Neu ist, dass statt der spitzen Klammern <...> hier die Anführungszeichen "..." verwendet werden. Das hat folgenden Grund: Bei Dateinamen in spitzen Klammern sucht der Compiler nur in seinen Standardverzeichnissen nach dieser Datei. Steht der Dateiname in Anführungszeichen (Gänsefüßchen), so sucht der Compiler zuerst im aktuellen Verzeichnis nach der angegebenen Datei, bevor er dann in seinen Standardverzeichnissen weitersucht. Zusätzlich wird durch die Anführungszeichen dem Leser des Programms deutlich gemacht, welche Header-Dateien speziell für das Projekt erstellt wurden.

Header-Datei nur einmal übersetzen

In Projekten zunehmender Größe kann es vorkommen, dass eine Header-Datei innerhalb einer Quelcode-Datei mehrfach eingebunden wird. Entweder wurde die Header-Datei tatsächlich durch zwei identische #include-Befehle eingebunden, oder es wurden zwei unterschiedliche Header-Dateien eingebunden, von denen die eine die andere wiederum mit #include einbindet. Wird eine Header-Datei mehrfach eingebunden, so kommt es zu Mehrfachdeklarationen und -definitionen und der Compiler wird Fehler melden.

Der Ausweg ist eine bedingte Übersetzung mit #ifndef. Mit der ersten Zeile wird geprüft, ob ein recht langer Name (hier: GET_FROM_USER_ROBERT_HESS_INCLUDED) noch nicht definiert worden ist (if not defined). Nur wenn der Name noch nicht definiert wurde, wird der block zwischen #ifndef und #endif übersetzt. Damit dieser Block aber nur einmal übersetzt wird, sorgt der #define-Befehl dafür, das der lange Name jetzt definiert wird. Dabei muss dem Namen kein Inhalt zugewiesen werden (wie z.B. #define ANZAHL 10), es reicht, dass der Name existiert.

Wird die Header-Datei erneut eingebunden, so existiert der lange Name bereits, und der Block zwischen #ifndef und #endif wird nicht wieder übersetzt.

























Seite 18