Modularisierung



  • Wenn man sich den Code von NEDUG mal ansieht, ist das vielleicht keine so gute Idee. Ich würde das weiter aufstrukturieren, damit man's auch versteht.

    Hmm ich weiß was du meinst. Und das war nur der Lexer 😞 Der Parser wäre noch mal ein Zacken schärfer. Zu meiner Verteidigung muß ich sagen, daß mein Code noch geht. Ich hab mich einige Zeit mit Compilerbau beschäftigt und muß sagen, daß Parser halt wirklich nicht einfach sind. Im Endeffekt sind sie alle sehr verwickelt. Die meisten benutzen aber eh einfach nur Lex/Yacc und fertig. Dabei sind selbstgebaute Sachen bei weitem schneller als das Duo. Ich bin mir auch noch nicht so ganz sicher, ob der Ersteller des Threads überhaupt eine solche Möglichkeit braucht. Er schreibt ja nicht weiter, was er eigentlich machen möchte. Er sagt "(...) Kommando-Datei parst und anschließend Textdaten (ASCII) einließt (...)" Was die geparste Kommando Datei im Endeffekt tun soll, wird nicht klar. Desewegen erstmal Statement abwarten und dann noch ma schaun. Für meinen unverständlichen, wenig kommentierten Code entschuldige ich mich auf jeden Fall. Hatte nicht mehr Zeit.



  • Hallo,

    ich möchte noch eine Frage im Kontext Modularisierung stellen.
    In dem Programm, welches ich schreiben möchte, greife ich auf mehrere Dateien zu.
    Um den einzelnen Routinen nicht immer gesamte Dateinamen und Pfade zu übergeben bzw. zusammenbauen zu müssen, wollte ich eine Funktion definieren, in welcher die erforderlichen Dateinamen inkl. Pfad in erzeugt werden.
    Diese Strings sollen dann in Zeichenketten gespeichert werden.

    Frage:
    # Ist dieses Vorgehen möglich/sinnvoll?
    # Kann ich die Strings in den Headerdateien wie folgt definieren:

    globStrings.h

    char cmdFilename[1024] = "";
    

    # Ist es möglich/sinnvoll einen char-Pointer auf das erste Zeichen von cmdFilename zeigen zu lassen und auf diese Weise in andere Routinen zu übergeben?

    char *fPtr;
    fPtr = &cmdFilename;
    

    Besten Dank.



  • Phil270307 schrieb:

    # Kann ich die Strings in den Headerdateien wie folgt definieren:

    das lass sein, sonst versucht der compiler für jedes C-file, das compiliert wird, diese variable anzulegen. erzeuge globale variablen nur in einem C-file und in die .h schreibst du ein 'extern' davor.

    // global.c
    int my_global;
    ...
    
    // global.h
    extern int my_global;
    ...
    

    Phil270307 schrieb:

    # Ist es möglich/sinnvoll einen char-Pointer auf das erste Zeichen von cmdFilename zeigen zu lassen und auf diese Weise in andere Routinen zu übergeben?

    klar, das wird sogar meistens so gemacht.
    🙂



  • # Ist dieses Vorgehen möglich/sinnvoll?

    Möglich jedenfalls, klingt auch sinnvoll.
    Ist dann sinnvoll, wenn's nicht auch einfacher geht.
    (zB mit relativen Pfaden, die man nicht zusammenbauen muss, oder so -- kann ich nicht wissen)

    # Kann ich die Strings in den Headerdateien wie folgt definieren: (...)

    Ja.

    # Ist es möglich/sinnvoll einen char-Pointer auf das erste Zeichen von cmdFilename zeigen zu lassen und auf diese Weise in andere Routinen zu übergeben?

    Ja, aber:

    char string[] = "12345";
    char *pt;
    // dann entweder:
    pt = string;
    // oder:
    pt = &string[0];
    // aber eher nicht:
    pt = &string;
    

    EDIT:
    fricky hat recht, lass mal lieber die Strings in den Headern (hatte ich überlesen).



  • bgdnoy schrieb:

    // aber eher nicht:
    pt = &string;

    sieht irgendwie blöd aus, geht aber trotzdem.
    🙂



  • Ja, geht trotzdem, aber nur für string als Array und nicht für string als Zeiger auf char. Und das hat mich in grauer Vorzeit einmal sehr verwirrt...



  • bgdnoy schrieb:

    Ja, geht trotzdem, aber nur für string als Array und nicht für string als Zeiger auf char.

    ersteres ergibt einen char(*)[], letzteres einen char**. deshalb geht's mit arrays, obwohl der compiler meckert.
    🙂



  • char cmdFilename[1024] = "";
    

    Kann mir mal jemand expliziet beschreiben, was hier genau passiert ...



  • knivil schrieb:

    char cmdFilename[1024] = "";
    

    Kann mir mal jemand expliziet beschreiben, was hier genau passiert ...

    das ist ein char-array mit 1024 elementen und das erste wird auf 0 gesetzt.
    🙂



  • Hallo,

    die Länge der String-Variable möchte ich über eine Konstante definieren, die in einer anderen Header-Datei liegt.
    Wie wird denn diese Header-Datei in die Header-Datei inkludiert, in welcher der String definiert wird?

    In einem nächsten Schritt möchte ich gerne den aktuellen Pfad auslesen und dafür einen entsprechenden String zur Verfügung stellen. Wäre es möglich mir ein kurzes Beispiel zu geben, wie man
    1. die erforderliche Länge des Strings für das Working-Directory bestimmt
    2. diesen String dynamisch auspannt

    Besten Dank



  • Phil270307 schrieb:

    die Länge der String-Variable möchte ich über eine Konstante definieren, die in einer anderen Header-Datei liegt.
    Wie wird denn diese Header-Datei in die Header-Datei inkludiert, in welcher der String definiert wird?

    in die eine .h datei machste erstmal die konstante als #define rein. dann inkludierst du diese datei in jedem .c-file bevor du die datei mit der string-definition inkludierst. du könntest du auch die konstanten-h von der string-h selber inkludieren lassen. ach ja, und verwende 'inlcude guards', also sowas ähnliches:

    #ifndef MY_CONSTANTS
    #define MY_CONSTANTS
    ...
    #define ... ... // hier alle konstanten rein
    ...
    #endif
    

    ^^das brauchste, damit mehrfaches includen nicht den compile-vorgang abbricht.

    Phil270307 schrieb:

    1. die erforderliche Länge des Strings für das Working-Directory bestimmt

    unter windoofs gibt's die konstante MAX_PATH, aber ich weiss nicht, ob die brauchbar ist.

    Phil270307 schrieb:

    2. diesen String dynamisch auspannt

    ausspannt oder aufspannt? wie auch immer, was meinst du damit?
    🙂



  • ok, die Definition der Konstanten mit #define ist mir klar.

    Die Strings, die ich für meine Dateipfade verwenden liegen in einer anderen Header-Datei und werden durch die Konstanten begrenzt.

    konst.h

    #define MAXSTR1 = 512
    

    globStrings.h

    #include "konst.h"
    
    char command[MAXSTR1] = "";
    

    Aber das funktioniert noch nicht ....
    Muss ich für die Definition des Strings command noch eine *.c-Datei anlegen?

    P.S.:
    Meine Verzeichnisstrutkur sieht wie folgt aus:

    src/inc/.h
    src/obj/
    .o
    src/obj/Makefile
    src/*.c



  • Hallo,

    ich möchte gerne noch eine Frage stellen:
    Ist es möglich zur Laufzeit eine Struktur oder auch ein Feld einer Struktur zu allokieren, die selbst ein Feld beinhaltet, das dynamisch augespannt werden kann?

    Bsp:

    struct MyDataTyp {
     int A;
     float B;
     ....
    }
    

    An der Stelle, die ich mit "..." markiert habe sollte nun noch ein int-Feld erzeugt werden, dass N Elemente besitzt. Wie genau geht das?



  • Phil270307 schrieb:

    Hallo,

    ich möchte gerne noch eine Frage stellen:
    Ist es möglich zur Laufzeit eine Struktur oder auch ein Feld einer Struktur zu allokieren, die selbst ein Feld beinhaltet, das dynamisch augespannt werden kann?

    Si! Do you gucking here:

    typedef struct
    {
    	int n; // speichert die anzahl der dynamic_int elemente.
    	int* dynamic_int;
    
    }DynamicStruct;
    
    DynamicStruct* dynamic_struct_factory ( int n )
    {
    	DynamicStruct* _new = malloc (sizeof(DynamicStruct));
    	if ( _new != NULL )
    	{
    		if ( NULL ==(_new->dynamic_int = malloc ( n*sizeof(int))))
    		{
    			free (_new);
    			_new = NULL;
    		}
    		else
    			_new->n = n;
    	}
    	return _new;
    }
    
    void dynamic_struct_free ( DynamicStruct* pds )
    {
    	free (pds->dynamic_int);
    	free (pds);
    }
    
    int main()
    {	
    	int N = 100;
    	DynamicStruct* pds = dynamic_struct_factory (N);
            if ( pds == NULL )
    	    fprintf(stderr, "Shit happens: %s\n", strerror(errno));
    	// do something with it ...
    	dynamic_struct_free (pds); // free memory.
    	return 0;
    }
    

    SEEYA
    B.B. ( the bigger one )



  • 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

    😃


Anmelden zum Antworten