struct in struct



  • Also ich habe ein kleines Problemchen.
    Und zwar habe ich bisher immer mit einem Struktur-array gearbeitet welches
    folgendes Format hatte:

    struct wetter
    {
    ....char cJahr[10];
    ....char cMon[10];
    ....char cDay[10];
    ....char cTemp[10];
    };
    

    struct wetter daten[1024];

    zugriff erfolgte duch:

    daten[1].cJahr;

    Nun würde ich meine Programmlaufzeit gerne verbessern in dem ich die suche Optimiere. Dazu würde ich gerne folgender maßen auf eine variable zugreifen:

    jahr[1].mon[1].day[5].cTemp;

    leider schaffe ich es nicht eine struktur dafür zu erstellen...
    Kann mir da vllt einer helfen.

    Herzlichen Dank schon mal an alle
    Marian



  • man kann structs auch verschachteln...

    struct wetter
    {
       struct jahr 
       {
          struct monat 
          {
             struct tag 
             {
                char ctemp[10];
             } tage[31];
          } monate[12];
       } jahre[10];
    } daten[1024];
    

    🙂

    edit: das sind 38092800 bytes 😃



  • so gehts nicht ganz...
    habs aber raus gefunden...

    struct jahr
    {
        struct mon time2;
    };
    struct jahr time[10];
    
    struct mon
    {
        struct day time3;
    };
    
    struct day
    {
        char cTemp;
    };
    

    bei mir gehs so...

    @ten
    Bei deiner art sagt der mir das struct das nicht unterstützt...
    Werde ich aber auch noch mal versuchen... Sieht übersichtlicher aus bei dir.
    trotzdem fettes thx.... Ich hoffe ich kriege deins noch zu laufen...



  • nochmal thx... Habs jetzt so wie du...
    Mein fehler war in der main-function.

    Allerdings würde ich gerne wissen wie du auf die bytes kommst.
    Und in welchem zusammenhang das mit der laufzeit steht wenn ich hinterher suchen muss.

    weil ich muss immer in einem bestimmten jahr und einem bestimmten monat alle temperaturen eines monats finden... Und wenn ich immer aufs neue alles durchgehe um die daten dann zu sortieren dauert das ewig.

    die zahl die ich da grade gelesen habe, finde ich allerdings sehr sehr groß (38092800 😮 ).
    jetzt bin ich leicht verunsichert ob es überhaupt den gewünschten effect hat.

    wäre nett wenn du das mal erläutern könntest

    thx again
    Sqwan 🙂



  • Was du brauchst ist dreidimensionales Array. Eine Struktur taugt dafür nicht.

    struct wetter 
    { 
    ....char cJahr[10]; 
    ....char cMon[10]; 
    ....char cDay[10]; 
    ....char cTemp[10]; 
    };*/  
    
    #define Jahr 10    // Arraywerte für 10 Jahre
    #define Monat 12
    #define Tag 31 
    
    int main () 
    { 
    unsigned char wetter[Jahr][Monat][Tag];    
    
    //jahr[1].mon[1].day[5].cTemp; 
    wetter[1][1][5] = 7; // Grad Celsius
    unsigned char test = wetter[1][1][5];
    }
    

    🙂



  • die struktur habe ich gewählt damit ich aus jeder funktion auf meine wetterdaten zugreifen kann.
    Und ein dreidimensionals Array würde da schnell unübersichtlich.
    Desweiteren dürfen wir in der schule nur befehle verwenden die wir bereits gemacht bzw angesprochen haben.

    #define gehört leider nicht dazu.

    ich habe mitwochs die ersten 4 stunden info.
    Ich frage mal was sich da so machen lässt.
    wichtig ist jedenfalls das ich meine variablen Global überall zur verfügung habe.

    @egon2
    auch ein großes thx an dich
    Habe zwar jetzt wieder ne menge mist im kopf 😃 aber das muss
    man wohl alles mal ausprobieren wenn man programmieren lernen will 👍
    Und irgendwan wird dein vorschlag schon noch in meinem info-unterricht auftauchen 🤡

    so long
    Sqwan



  • und wenn du 10 Temperaturwerte pro Tag speichern willst, muss das Array eben vierdimensional sein.

    unsigned char wetter[Jahr][Monat][Tag][10];
    

    💡



  • Sqwan schrieb:

    Allerdings würde ich gerne wissen wie du auf die bytes kommst.
    Und in welchem zusammenhang das mit der laufzeit steht wenn ich hinterher suchen muss.

    na, 1024*10*12*31*10.
    übelst gross, aber laufzeitmässig das schnellste weil man auf jedes element über index zugreifen kann...

    egon2 schrieb:

    und wenn du 10 Temperaturwerte pro Tag speichern willst, muss das Array eben vierdimensional sein.

    unsigned char wetter[Jahr][Monat][Tag][10];
    

    💡

    das kann aber auch verdammt viel speicher schlucken...

    Sqwan: wenn du mit so vielen daten herumfummelst, dann wär' vielleicht ein kleines dbms nicht schlecht, mysql, sqlite, berkeley-db oder sowas.



  • hm... Unser auftrag wurde heute erweitert...

    jetzt muss ich nicht nur die temperatur ausgeben die zu einem datum gehört, sondern auch zu einer temperatur alle daten, an denen es diese temperatur gab...

    Da kann ich das struktursystem so wie ich es machen wollte nimmer nehmen...
    Und dbs darf ich auch nicht verwenden. Mal davon abgesehen das ich keine ahnung von mysql in C habe (nur in php).

    Aber der aufbau der datei ist leider vorgeschrieben:

    20070206,36.5
    20060825,10.4

    die datei heißt pflichtmäßig TEXT.TXT

    Aber wenn einer etwas findet wo ich mysql in C lernen kann werde ich mir das mal durchlesen (progge auch schon lange hobbymäßig c/cpp).



  • Sqwan schrieb:

    Aber der aufbau der datei ist leider vorgeschrieben:

    20070206,36.5
    20060825,10.4

    csv?
    vielleicht hilft dir das: http://www.ioplex.com/~miallen/libmba/



  • Voilá

    /* TEXT.TXT
       ========
       20070206,-21.4
       20060825,19.4
       20070206,19.4
       20070206,19.5
       20060825,-21.4 */
    
    #include <alloc.h>
    #include <conio.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    struct tTemp
    { long datum;
      float grad;
    };
    struct tBasis
    { int nZeilen;
      struct tTemp *Array;
    };
    
    int ReadIn(char *file, struct tBasis *basis)
    {
      FILE *fp;
      char pclinebuffer[1000];
      char *s;
    
      if ((fp = fopen(file, "rt")) == 0)
        { printf("Eingabedatei konnte nicht geoeffnet werden\n");
          return 0;
        }
      while(fgets(pclinebuffer, sizeof(pclinebuffer), fp))
        { basis->Array = (struct tTemp *)realloc(basis->Array, (basis->nZeilen+1)*sizeof(struct tTemp));
          s = pclinebuffer;
          basis->Array[basis->nZeilen].datum = strtoul(s, &s, 10);
          basis->Array[basis->nZeilen].grad  = strtod(s+1, 0);
          basis->nZeilen++;  
        }
      fclose(fp);
      return 1;
    }
    
    void Print(struct tBasis *basis)
    {
      int i;
    
      printf("/* === Ausgabe === */\n");
      for (i = 0; i < basis->nZeilen; i++)
          printf("%u %u: %6.2f\n", i, basis->Array[i].datum, basis->Array[i].grad);
    }
    
    struct tBasis *CreateBasis(void)
    {
      return calloc(1, sizeof(struct tBasis));
    }
    
    void RemoveBasis(struct tBasis **pb)
    {
      free((*pb)->Array);
      free(*pb);
      *pb = 0;
    }
    
    /* ================================= */
    /* Sortierfunktion für qsort -1/0/+1 */
    /* ================================= */
    
    int fn_cmp(const void *a, const void *b)
    {
      struct tTemp *A = (struct tTemp *)a;
      struct tTemp *B = (struct tTemp *)b;
    
      /* zuerst nach Grad */
      if (A->grad < B->grad)
          return -1;
      if (A->grad > B->grad)
          return 1;
      /* wenn Temperatur gleich    */
      /* dann nach Datum sortieren */
      if (A->datum < B->datum)
          return -1;
      if (A->datum > B->datum)
          return 1;
      return 0;
    }
    
    void Sortieren(struct tBasis *basis)
    {
      qsort(basis->Array, basis->nZeilen, sizeof(struct tTemp), fn_cmp);
    }
    
    int main()
    {
      struct tBasis *basis;
    
      basis = CreateBasis();
      if (ReadIn("TEXT.TXT", basis))
        { Print(basis);
          Sortieren(basis);
          Print(basis);
        }
      RemoveBasis(&basis);
      getch();
      return 0;
    }
    


  • Also mal abgesehen davon das ich das script (NOCH) nicht verstanden habe, gibt es einen fehler aus.

    'alloc.h': No such file or directory

    ^^ leider kriege ich den nicht weg...
    Sowas ist bei mir immer nur bei Vorkompilierten headern vorgekommen.´

    hat einer eine idee wie ich das beheben kann? (der fehler erschient in der zeile bei include)



  • Dieser Fehler ist einfach zu beheben: Einfach "#include <malloc.h>" schreiben.

    Bei Microsoft heißt die Headerdatei für die Speicherreservierung malloc.h, ich compiliere mit Borland.



  • die nötigen deklarationen für 'malloc' o.ä. stecken normalerweise in 'stdlib.h'
    🙂



  • ^^ thx... die header funktionieren jetzt schom mal... Allerdings Progge ich noch nicht so lange... Und deshlalb habe ich ein paar probleme mit den fehlermeldungen, bzw weiß ich nie wodurch diese entstehen und dem entsprechend weiß ich nie wie man sie behebt..

    struct tBasis *CreateBasis(void) 
    { 
      return calloc(1, sizeof(struct tBasis)); 
    }
    

    Naja... mein Compieler sagt mir das es hier einen fehler gibt.
    Und zwar sachter:

    'return' : 'void *' kann nicht in 'struct tBasis *' konvertiert werden
    

    vööt könnt ihr mir da noch mal helfen ...

    MFG Marian



  • Da ich meinen Quellcode immer "main.c" nenne, wendet mein (Borland)Compiler die C-Syntax an. Mit "main.cpp" bekomme ich die gleiche Meldung.

    Da hilft nur casten. Info: calloc() liefert einen "void *"-Zeiger zurück, return will aber einen "struct tBasis *"-Zeiger haben.

    return (struct tBasis *)calloc(...);
    
    //mit malloc und realloc ist es das gleiche.
    


  • keksekekse schrieb:

    Da hilft nur casten.

    neiiiiiiin ⚠



  • @ten...

    return (struct tBasis *)calloc(1, sizeof(struct tBasis));
    

    So gehts...
    Was ist schlim da dran?



  • Sqwan schrieb:

    @ten...

    return (struct tBasis *)calloc(1, sizeof(struct tBasis));
    

    So gehts...
    Was ist schlim da dran?

    guckst du: https://www.securecoding.cert.org/confluence/display/seccode/MEM02-A.+Do+not+cast+the+return+value+from+malloc()
    auch die links ganz unten



  • q also da ich nicht so gut in englisch bin habe ich das mal bei google eingegeben... Da habe ich allerdings gefunden das man das einfach casten soll.

    Tja, nur leider ist der Zeiger vom typ void, den wir nicht gebrauchen können. Das müssen wir ändern, und zwar mit hilfe des cast- operators:
    [code:1:49e50c0f8e]pcPointer = (char*) malloc ( sizeof(char) * nNeeded );
    [/code:1:49e50c0f8e]
    Hier haben wir den Datentyp von void nach char* geändert.

    davon gabs noch mehr seiten wo in etwa das selbe stand.

    dann noch eine frage...
    Wieso werden so viele Zeiger verwendet...
    ich habe variablen immer normal initalisiert, da ich nicht verstanden habe wann man so einen zeiger braucht: looks like char a;
    Vllt kannst du mir mal einen anstoß für eine google suche geben...
    und vllt auch noch einen denkanstoß um malloc nicht casten zu müssen.

    thx for help
    Marian



  • Also ich seh da nur Probleme in C wenn

    sizeof(int) != sizeof(void *)
    

Anmelden zum Antworten