Arraylaenge an Daten anpassen



  • Poste doch mal bitte deinen bisherigen Code. Dann könnte man hier ansetzen.



  • Wenn du sowieso zuerst die Anzahl der Zeilen ermittelst, kannst du auch gleich explizit malloc verwenden, anstatt nochmal realloc zu bemühen.



  • Du weißt also schon vor der ersten Benutzung Deines Arrays, wieviel Speicher Du benötigst. Dann brauchst Du gar kein realloc, sondern ein Aufruf von malloc besorgt Dir den benötigten Speicher.



  • @Belli: Ja, ich weiss vorher zwar wie viele Zeilen meine Datei hat. Das aendert
    sich auch waehrend der Programmausfuehrung nicht.

    Hier erstmal was Code von mir, bisher ohne malloc() und unvollstaendig.
    Ich bin darueber hinaus auch nicht ganz glueklich mit dem auslesen der Zeilen, vll gibt es da eine andere Loesung fuer..

    #define BUFFER 999 /* Array Size Buffer */ 
    
    int main() 
    { 
    FILE *fp; 
    fp = fopen("Signal.dat","r"); 
    if (fp == NULL) 
    { 
    printf("Error: can't open sample file!\n"); 
    } 
    
    /* Hier will ich nun die Anzahl der Zeilen bestimmen */ 
    int i; 
    int len++; 
    while (i != EOF) 
    { 
    i = fgetc(fp); 
    if (i == '\n') 
    { 
    len++; 
    } 
    } 
    rewind(fp); 
    
    if (len != BUFFER) 
    { 
    /* Mache mein Array um soviel Groesser wie fehlt */ 
    } 
    
    double Signal_Array[BUFFER];
    


  • So, ich hab jetzt noch ein bisschen rumprobiert und denke das sollte so funktionieren:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        FILE *fp;
        fp = fopen("Signal_Data.dat","r");
    
        if (fp == NULL)
        {
            printf("Error: can't open sample file!\n");
        }
    
        int i;
        int len = 0;
        while((i = fgetc(fp)) != EOF)
        {
            if (i == '\n')
            {
                len++;
                printf("%d\n",len);
            }
        }
        rewind(fp);
    
        double *A;
        A = malloc(sizeof(double)*(len+1));
        if (NULL == A)
        {
            printf("No Memory!\n");
            return EXIT_FAILURE;
        }
    
        int j;
        for(j = 0; j < len+1; j++)
        {
            double temp;
    		fscanf(fp, "%lf\n", &temp);
    		A[j] = temp;
        }
        fclose(fp);
        free(A);
    
        return 0;
    }
    

    Passt das so mit dem aufruf von malloc() etc.?



  • #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
      FILE *fp;
      fp = fopen("Signal_Data.dat", "r");
    
      if (fp)
      {
        int blocksize = 1000, i = 0;
        double *a = malloc(blocksize*sizeof*a);
    
        while (1 == fscanf(fp, "%lf", &a[i]))
        {
          if (++i >= blocksize)
            a = realloc(a, (blocksize *= 2) * sizeof*a);
        }
        fclose(fp);
    
        while (i--)
          printf("%f\n", a[i]);
    
        free(a);
      }
    
      return 0;
    }
    


  • Danke Wutz.
    Allerdings gibt das Programm meine Daten in umgedrehter Reihenfolge aus.
    Das Erste Element steht an letzter Stelle usw..



  • Ist doch egal, wierum es ausgegeben wird?!

    Wutz' Programm verdeutlicht, wie du mit malloc und realloc das Problem elegant lesen kannst. Ohne das Zählen von '\n' in der Datei.



  • Das stimmt und ich finde diese Moeglichkeit auch wesentlich besser.
    Nur soll ja im weiteren Verlauf mit den Daten im Array gerechnet werden
    und dafuer brauche ich die natuerlich in der richtigen Reihenfolge.



  • Die Daten sind in der "richtigen" Reihenfolge, nur die (Test)Ausgabe läuft rückwärts.



  • Okay, ich werde es mal versuchen einzubinden in mein Programm.

    Koenntest du mir vielleicht noch kurz erklaeren wie folgender Teil des Pogramms
    funktioniert:

    while (1 == fscanf(fp, "%lf", &a[i]))
    

    Was ist 1?



  • Mark_W schrieb:

    while (1 == fscanf(fp, "%lf", &a[i]))
    

    Was ist 1?

    Gegenfrage: was ist der Rückgabewert von fscanf() ?



  • Ich denke mal die Anzahl der Argumente und das waere in diesem Fall 1.
    Okay, das macht jetzt etwas mehr Sinn. Leider sagt mir das Programm wenn ich
    aus der if-Bedingung rausgehe und Irgendwas mit dem Array anstellen will, dass das leer ist.. Irgendwas mache ich falsch.. 😕 Ich versuche vll noch ein kleines Beispiel zu bringen.



  • Bis zum fclose steht in i die Anzahl der gelesenen Werte.
    In der while -Schleife danach wird i bis 0 runter gezählt.



  • Mark_W schrieb:

    Ich denke mal die Anzahl der Argumente und das waere in diesem Fall 1.

    Nein. Kein Foto für Dich.

    Du wirst irgendwoher die Dokumentation der C-Standardbibliothek brauchen...
    Ohne die kann man kaum von Dir verlangen, richtige Programme zu schreiben.

    Z.B. für scanf() hier http://en.cppreference.com/w/c/io/fscanf



  • Mark_W schrieb:

    Ich denke mal die Anzahl der Argumente und das waere in diesem Fall 1.
    Okay, das macht jetzt etwas mehr Sinn. Leider sagt mir das Programm wenn ich
    aus der if-Bedingung rausgehe und Irgendwas mit dem Array anstellen will, dass das leer ist..

    Natürlich. Bei 'free' wird der Speicher ja auch wieder freigegeben (in Wutzs Code).
    Der ist nämlich ein Beispiel, ein Muster. Jetzt wäre der richtige Zeitpunkt für ein bisschen Eigenleistung ...



  • Das ist mir schon klar, ganz kopflos handel ich hier auch nicht. 😉
    Ich habe mein komplettes Programm jetzt auch stehen mithilfe des Muster von
    Wutz.

    Ich zeige hier noch schnell meine Abaenderungen und fuer mich ist dieser Thread
    dann sehr erfolgreich gewesen. Ich danke euch allen fuer eure schnelle Hilfe! 🙂

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
      FILE *fp;
      fp = fopen("Signal_Samples.txt", "r");
    
      int blocksize = 1000, i = 0;
      double *a = malloc(blocksize*sizeof*a);
    
      if (fp)
      {
        while (1 == fscanf(fp, "%lf", &a[i]))
        {
          if (++i >= blocksize)
            a = realloc(a, (blocksize *= 2) * sizeof*a);
        }
      }
    
      int j;
      for (j = 0; j < i; j++)
      {
          printf("%d: %lf\n", j, a[j]);
      }
    
      fclose(fp);
      free(a);
      return 0;
    }
    


  • Deine Datei könnte viel eher geschlossen werden:

    fclose(fp);
    

    könntest Du zwischen Zeile 18 und 19 packen.



  • IMHO solltest Du auch mal überlegen, was passiert, wenn malloc() oder realloc() fehlschlagen. Insbesondere letzteres zwingt Dich noch zu einer Erweiterung von Wutz' Minimalbeispiel ohne Fehlerbehandlung.
    Wirst auch nochmal in die Dokumentation gucken müssen... 🙂

    Ausserdem ist das ja alles ganz nett, aber früher oder später willst Du Deine Daten an Funktionen übergeben oder noch Daten anhängen...
    Zu diesem Zeitpunkt lohnte sich dann, dass ganze zu kapseln, das könnte z.B. so aussehen:

    typedef struct {
      int size;       // aktuelle Anzahl Elemente
      int max_size;   // maximale Elemente vor realloc
      double values[]; // Elemente (ein sogenanntes "Flexible Array Member")
    } vector;
    
    // Die drei sind zu implementieren:
    vector* vector_alloc();
    void vector_free(vector* v);
    void vector_grow(vector** v);
    
    // Benutzung ist dann Pipifax:
    void vector_print(const vector* v) {
      for(int i=0; i<v->size; ++i)
        printf("%lf\n", v->values[i]);
    }
    

Anmelden zum Antworten