Modularisierung



  • Hallo,

    ich habe das Programm nachvollzogen und es auf meine Bedürfnisse erweitert. Dabei bin ich auf ein Problem/Fehler gestoßen, wenn ich versuche die allocate-Funktion in ein anderes Modula auszulagern.

    Hier mein Beispiel:
    ------------------------------------------------------------------------------
    ftypes.h

    typedef struct {
      char string[1000];
      int number;
    } Blade;
    
    typedef struct {
      int elements;
      Blade *pBlade;
    } Domain;
    

    ------------------------------------------------------------------------------
    allocate.h
    ------------------------------------------------------------------------------

    #include "ftypes.h"
    
    Domain* allocate(int n);
    

    ------------------------------------------------------------------------------
    allocate.c
    ------------------------------------------------------------------------------

    #include <stdlib.h>
    #include "alloc.h"
    #include "ftypes.h"
    
    Domain* allocate(int n) {
      Domain *newDomain = malloc(sizeof(Domain));
      if (newDomain != NULL) {
        newDomain->pBlade = malloc(sizeof(Blade)*n); 
        if (newDomain->pBlade != NULL) {
          newDomain->elements = n;
        } else {
          printf("Fehler 2!\n");
        }
      } else {
        printf("Fehler 1\n");
      }
      return newDomain;
    }
    

    bsp.c
    ------------------------------------------------------------------------------

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "ftypes.h"
    #include "alloc.h"
    
    int main(void) {
      int ret;
      int retval;
      int i, n = 10;
      Domain *pDomain;
    
      pDomain = allocate(n);
      for (i=0;i<pDomain->elements;i++) {
        pDomain->pBlade[i].number = i*10;
        strcpy(pDomain->pBlade[i].string,"Beispieltext");
      }
    
      for (i=0;i<pDomain->elements;i++) {
        printf("Element [%d]: '%d'\n", i+1, pDomain->pBlade[i].number);
      }
    
      free(pDomain);
      return 0;
    }
    

    Wenn ich versuche das Programm zu übersetzen, erhalte ich folgende Fehler:

    gcc alloc.c bsp5.c -o bsp5.exe
    In file included from alloc.c:3:
    ftypes.h:4: Fehler: In Konflikt stehende Typen für »Blade«
    ftypes.h:4: Fehler: Vorherige Deklaration von »Blade« war hier
    ftypes.h:9: Fehler: In Konflikt stehende Typen für »Domain«
    ftypes.h:9: Fehler: Vorherige Deklaration von »Domain« war hier
    alloc.c:5: Fehler: In Konflikt stehende Typen für »allocate«
    alloc.h:3: Fehler: Vorherige Deklaration von »allocate« war hier
    alloc.c: In Funktion »allocate«:
    alloc.c:12: Warnung: Unverträgliche implizite Deklaration der eingebauten Funktion »printf«
    alloc.c:15: Warnung: Unverträgliche implizite Deklaration der eingebauten Funktion »printf«
    In file included from alloc.h:1,
                     from bsp5.c:6:
    ftypes.h:4: Fehler: In Konflikt stehende Typen für »Blade«
    ftypes.h:4: Fehler: Vorherige Deklaration von »Blade« war hier
    ftypes.h:9: Fehler: In Konflikt stehende Typen für »Domain«
    ftypes.h:9: Fehler: Vorherige Deklaration von »Domain« war hier
    

    Woran liegt's ?



  • Sieht mir nach fehlenden Includeguards aus.



  • Was beudetet das?





  • Die Includeguards verhindern mehrmaliges Einbinden.
    Schreib mal deine ftypes.h so:

    // ftypes.h
    
    #ifndef FTYPES_H
    #define FTYPES_H
    
    typedef struct {
      char string[1000];
      int number;
    } Blade;
    
    typedef struct {
      int elements;
      Blade *pBlade;
    } Domain;
    
    #endif
    


  • supertux schrieb:

    Include guards

    😃



  • Entschuldigung, blöde Frage, aber ich kriege das immer noch nicht zum laufen.
    Also ich versuche genau das hier zu übersetzen...

    // allocmem.h
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "inc/allocmem.h"
    #include "inc/blade.h"
    #include "inc/sendmsg.h"
    
    /* *************************************************************************** */
    
    Domain* allocateDomain(int elements) {
      Domain *newDomain = malloc(sizeof(structDomain));
      if (newDomain != NULL) {
        newDomain->Blade = malloc(sizeof(structBlade)*elements); 
        if (newDomain->Blade != NULL) {
          newDomain->Rows = elements;
        } else {
          senderrmsg("ALLOCMEM", "Unable to allocate memory for [Domain.Blade].");
        }
      } else {
        senderrmsg("ALLOCMEM", "Unable to allocate memory for [Domain].");
      }
      return newDomain;
    }
    
    // blade.h
    // ************************************************************************** //
    // STRINGS FOR GLOBALE FILENAMES
    // ************************************************************************** //
    
    #include "globConstants.h"
    
    #ifndef BLADE_H
    #define BLADE_H
    
    typedef struct {
      int i;
      double x,y,z;
      double r, rTheta;
      double betaAngle;
    } BladeSubDomain;
    
    /* *************************************************************************** */
    
    typedef struct {
      char filename[const_strlen1]; // filename
      char idirname[const_strlen2]; // input-directory
      char odirname[const_strlen2]; // output-directory
    
      double stagger_angle;         // stagger-angle
      int blades;                   // number of blades per row
    
      BladeSubDomain LE;
      BladeSubDomain TE;
    } structBlade;
    
    /* *************************************************************************** */
    
    typedef struct {
      int Rows;                    // number of blades in Domain
      structBlade *Blade;
    } structDomain;
    
    #endif
    

    Das sollte doch genau das gleiche sein.



  • Der Fehler lautet:

    gcc -c allocmem.c
    In file included from allocmem.c:4:
    inc/allocmem.h:3: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »*« token
    allocmem.c:10: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »*« token
    


  • Deine allocmem.h musst du noch überdenken:

    1. Includeguards vergessen.
    2. Funktionsdefinitionen gehören in eine *.c Datei. In Headerdateien deklariert man üblicherweise die Prototypen der Funktionen.


  • habs gerade selbst gefunden! schön blöder Fehler!!!

    structDomain* allocateDomain(int elements) {
    


  • Noch eine letzte Frage:

    Ich würde gerne eine Funktion definieren, die diverse Fehlermeldungen meines Programms auf den Bildschirm ausgibt.

    Beispiel

    > ERROR@[MODULE]: Der Wert 2 ist größer als 1.
                      Bitte ändern Sie den Wert XYZ in der Steuerdatei ein,
    

    Ich würde die Ausgabe gerne auf zwei Funktionen (1 und 2 Zeile) aufteilen.
    1. Die erste Zeile erhält die Info, in welchem Modul der Fehler auftrat sowie den Text. Und hier stellt sich mir die Frage, wie ich der Funktion einen Text, in dem auch Zahlen "2" und "1" auftauchen, als String übergebe?

    2. Für die zweite Zeile muss der Funktion mitgeteilt werden, wieviele Tabs bzw. Leerzeichen vor dem Text stehen sollen. Wie macht man das geschickt?

    Für bessere / professionellere Vorschläge bin ich gerne offen....



  • Ich mache das z.Zt. ungefähr so:

    // msg.h
    //...
    // Include Guards nicht vergessen :D
    char* msg_mk (char*, ...);
    //...
    
    // msg.c
    #define MSGLEN_MAX 1024
    static char msgbuf[MSGLEN_MAX+1] = {0};
    
    #ifdef WIN32 
    	#define vsnprintf _vsnprintf
    #endif
    
    char* msg_mk (char* a, ...)
    {
    	const int n = MSGLEN_MAX;
    	va_list v;
    	va_start(v,a);
    	vsnprintf(msgbuf, n, a, v);
    	va_end(v); 
    	return msgbuf;
    }
    
    // main.c
    #include "msg.h"
    int main (void)
    {
    	char* e = "You have moved your mouse. Restart Windows for the "
    		"change to take effect.";
    
    	while (type = check_input())
    	{
    		switch(type)
    		{
    
    			case MOUSEMOVE:
    				puts ( msg_mk ("Error nr: %d in file %s line %d occured! "
    			"The message is: %s.\n", 88, __FILE__, __LINE__, e ));
    			exit(1);
    			break;
    
    //...
    


  • Könntest Du bitte einmal kurz erklären, was genau Du mit den Funktionen

    va_list v;
    va_start(v,a);
    vsnprintf(msgbuf, n, a, v);
    va_end(v);
    

    bewirkst. Und was ist "vsnprintf _vsnprintf" für eine Funktion?

    Ist es in C möglich optionale Parameter für eine Funktion zu definieren?



  • Phil270307 schrieb:

    Ist es in C möglich optionale Parameter für eine Funktion zu definieren?

    klar. (...) heisst, dass der aufrufer die anzahl der argumente bestimmen kann.
    http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D
    🙂



  • Die Macros va_list, va_end werden z.B. hier mit Beispielen erklärt:
    http://pronix.linuxdelta.de/C/standard_C/c_programmierung_21.shtml
    Die Funktion vsnprintf arbeitet mit va_list zusammen, ist ähnlich wie snprintf.

    Das define vsnprintf -> _vsnprintf brauchst du vielleicht gar nicht, wenn du einen neueren Compiler hast.



  • Hallo,

    ich habe noch ein Problem, was ich nicht in den Griff bekomme/verstehe.

    Ich versuche vergeblich in ein Element meiner Struktur einen Sinus/Cosinus/Tangens-Ausdruck zu schreiben.

    #include <math.h>
    
    #define CNTLBLDLE Domain->Blade[bldID].LE
    
    CNTLBLDLE.r = sin(3.14152);
    

    Sobald ich eine trigonometrische Funktion auf ein double-Element in der Strutkur anwende, erhalte ich den Fehler "undefined reference to 'sin'".
    Woran liegt das? Und wie kann man den Fehler beheben?

    Noch eins - kann mir jemand sagen, wo ich eine gute Anleitung finde, um mein C-Projekt in Eclipse zu importieren und ein Makefile automatisch zu generieren?


Anmelden zum Antworten