Dynamischem Array Werte über Zwischenvariable zuweisen



  • Hmm.
    Ich würde Dir vorschlagen, eine Funktion für das erstellen und zerstören von struct messwert einzuführen und auch das einlesen in eine Funktion auszulagern.
    😉

    Das ist mein ernst.
    Evtl. passieren dann auch nicht solche Knaller, dass Du ein ein Array von messwerten allozierst und nur für den ersten in der Reihe das Member objekt zuweist.
    (Du dereferenzierst den NULL pointer in Zeile 39, sobald 0<zaehler ).

    Z.B. koennte das so aussehen:[code0"c"]// alloziert n messwerte
    // gibt einen pointer auf das den ersten der Werte zurück
    // NULL im Fehlerfall.
    messwert* alloc_messwerte(size_t n);

    // gibt ein Array von Messwerten, das mit alloc_messwerte() alloziert wurde
    // wieder frei
    void free_messwerte(messwert* p);[/code]

    Versuch Dich mal dran.



  • DirkB schrieb:

    Du musst für jeden messwert auch ein objekt besorgen.

    Warum strcat (Zeile 40)? Was steht denn vorher da drin?

    Die Schleifenbedinging (feof(file)==0) ist falsch.
    Zu dem Zeitpunkt kann die noch nicht funktionieren.
    Nimm das fscanf in die Schleifenbedingung und vergleiche auf die Anzahl gelesener Werte.

    while (fscanf(file, "%d%c%[^,]%c%d%c%lf\n", &tempobjektnr, &c, &tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert) == 7) {
    

    tempbezeichnung ist ein Array, da komt kein & hin. Mit dem * Modifiere brauchst du das c auch nicht.
    Mit ein paar Leerzeichen im Formatstring, werden auch Whitespaße überlesen.

    while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert) == 4) {
    

    In strcat steht vorher nichts drinn. Da soll ja tempbezeichnung drinn gespeichert werden.

    Aber mir deiner Schleifenbedingung überprüfe ich doch nur, ob auch alle Werte eingelesen und in "temp..." gespeichert werden. Hört diese denn auch am Ende der Datei auf?

    Und wofür steht die 19 bei

    while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert) == 4) {
    

    Und wieso soll

    while (feof(file)==0) {
    

    nicht funktionieren? Wenn ich die Werte aus der Datei in den Zwischenvariablen speicher und ausgeben bekomme ich alle bis zum Ende. Ich denke mal danach springt er dann aus der Schleife raus



  • mezzix schrieb:

    In strcat steht vorher nichts drinn. Da soll ja tempbezeichnung drinn gespeichert werden.

    Wie kommst du darauf?
    Abgesehen davon, das z.Zt. dieser Speicher noch nicht einmal für dich reserviert ist, kannst du nicht davon ausgehen, das da nichts drin steht. (nur globale und static Variablen werden automatisch initialisiert)
    Sonst steht das drin, was vorher mal an der Stelle gespeichert wurde.

    mezzix schrieb:

    Aber mir deiner Schleifenbedingung überprüfe ich doch nur, ob auch alle Werte eingelesen und in "temp..." gespeichert werden.

    Genau. Wenn du nicht alle Werte lesen konntest, hast du ein Problem und solltest abbrechen.

    mezzix schrieb:

    Hört diese denn auch am Ende der Datei auf?

    Was soll sie denn sonst machen?

    mezzix schrieb:

    Und wofür steht die 19 bei

    while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert) == 4) {
    

    Woher weißt du denn, was %[ oder %d machen? -> http://www.cplusplus.com/reference/cstdio/fscanf/
    Das gibt die maximal Anzahl der einzulesenden Zeichen an.

    mezzix schrieb:

    Und wieso soll

    while (feof(file)==0) {
    

    nicht funktionieren? Wenn ich die Werte aus der Datei in den Zwischenvariablen speicher und ausgeben bekomme ich alle bis zum Ende. Ich denke mal danach springt er dann aus der Schleife raus

    Wenn dein Code mit der letzten Zeile fertig ist, dann steht da zumindest noch das '\n' im Eingabestrom. Also gibt feof() 0 zurück und deine Schleife läuft weiter.
    Das fscanf will dann lesen und findet keine Daten mehr, und schreibt auch keine neuen Daten in die Variablen.
    Also wird die letzte Zeile zweimal in deiner Struktur abgelegt.



  • DirkB schrieb:

    mezzix schrieb:

    Und wieso soll

    while (feof(file)==0) {
    

    nicht funktionieren? Wenn ich die Werte aus der Datei in den Zwischenvariablen speicher und ausgeben bekomme ich alle bis zum Ende. Ich denke mal danach springt er dann aus der Schleife raus

    Wenn dein Code mit der letzten Zeile fertig ist, dann steht da zumindest noch das '\n' im Eingabestrom. Also gibt feof() 0 zurück und deine Schleife läuft weiter.
    Das fscanf will dann lesen und findet keine Daten mehr, und schreibt auch keine neuen Daten in die Variablen.
    Also wird die letzte Zeile zweimal in deiner Struktur abgelegt.

    Dann müsste mir doch auch in der Konsole aber auch zwei mal die letzte Zeile ausgegeben werden. Und das passiert nicht.
    Wenn ich jedoch

    while (fscanf(file, "%*d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert )== 4) {
    

    benutze werden nicht alle Werte eingelesen.



  • mezzix schrieb:

    Wenn ich jedoch

    while (fscanf(file, "%*d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert )== 4) {
    

    benutze werden nicht alle Werte eingelesen.

    Dann schau doch mal genau hin, wieviel &c ich in der Zeile mit dem == 4 habe.



  • Hat die letzte Zeile in der Datendatei auch ein '\n' am Ende?



  • mezzix schrieb:

    ich habe momentan das Problem, dass ich einem dynamischem Array Werte über Zwischenvariablen zuweisen möchte. Diese Zwischenvariablen enthalten Daten aus einer .txt. Leider stürzt das Programm beim ausführen immer ab.

    Das weist auf undefinierten Speicherzugriff hin.
    Wenn du unsicher bei malloc & Co. bist, dann nimm erstmal ein statisches Array,
    dynamisieren kannst du später immer noch.
    Wenn das Zeilenformat nicht einheitlich für jede Zeile ist, ist fscanf unbrauchbar.
    Hier bietet sich fgets/sscanf an, fgets liest erstmal jede Zeile ein, mit sscanf entscheidest du dann, welche Zeile gültig ist:

    typedef struct {
            int objektnr;
            char bezeichnung [20];
        } messobjekt;
    
        typedef struct {
            messobjekt objekt;
            int messnr;
            double messwert;
        } messwert;
    
    int main () {
        /* struct-Array mit fester Größe; spart malloc/realloc */
        messwert m[1000];
        char zeile[1000];
        int zaehler = 0;
    
        FILE * file;
        file = fopen("messungen.txt", "r");
    
        if(!file)
          perror("messungen.txt"),exit(1);
    
        while(fgets(zeile,1000,file))
          if( 4==sscanf(zeile,"%d,%19[^,],%d,%lf",&m[zaehler].objekt.objektnr,
                                                   m[zaehler].objekt.bezeichnung,
                                                  &m[zaehler].messnr,
                                                  &m[zaehler].messwert))
                                                  ++zaehler;
        fclose(file);
    
        printf("\n%d Daten eingelesen\n",zaehler);
    
        while(zaehler--)
          printf("\n%d,%s,%d,%f",m[zaehler].objekt.objektnr,
                                 m[zaehler].objekt.bezeichnung,
                                 m[zaehler].messnr,
                                 m[zaehler].messwert);
    
        return 0;
    }
    


  • Oke, zur Übersichtlichkeit hier nochmal der aktuelle Code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
        typedef struct {
            int objektnr;
            char bezeichnung [20];
        } messobjekt;
    
        typedef struct {
            messobjekt *objekt;
            int messnr;
            double messwert;
        } messwert;
    
    int main () {
        int size = 3;
        messwert *dynfeld;
        dynfeld = (messwert*)calloc(size, sizeof(messwert));
        dynfeld->objekt = (messobjekt*)calloc(size, sizeof(messobjekt));
    
        FILE * file;
        file = fopen("messungen.txt", "r");
    
        int tempmessnr;
        double tempmesswert;
        int tempobjektnr;
        char tempbezeichnung [20];
        int zaehler = 0;
        int wieoftdurchlaufen = 0;
        //fseek(file, 50L, SEEK_SET);
        fscanf(file, "%*[^\n]");
        while (feof(file)==0) {
        //while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert ) == 4) {
                fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert);
                //fscanf(file, "%d %c %19[^,] %c%d %c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert);
                //fscanf(file, "%d%c%[^,]%c%d%c%lf\n", &tempobjektnr, &c, tempbezeichnung, &c, &tempmessnr, &c, &tempmesswert);
                //fscanf(file, "%d%c%[^,]%c%d%c%lf\n", &dynfeld[zaehler].objekt->objektnr, &c, &dynfeld[zaehler].objekt->bezeichnung, &c, &(dynfeld[zaehler].messnr), &c, &(dynfeld[zaehler].messwert));
                printf("\nWerte: %d,%s,%d,%lf", tempobjektnr, tempbezeichnung, tempmessnr, tempmesswert);
                //*(dynfeld+zaehler)->objekt->objektnr = tempobjektnr;
    //            dynfeld[zaehler].objekt->objektnr = tempobjektnr;
    //            strcat(dynfeld[zaehler].objekt->bezeichnung, tempbezeichnung);
    //            dynfeld[zaehler].messnr = tempmessnr;
    //            dynfeld[zaehler].messwert = tempmesswert;
                //printf("\nWerte: %d,%s,%d,%lf", dynfeld[zaehler].objekt->objektnr, dynfeld[zaehler].objekt->bezeichnung, dynfeld[zaehler].messnr, dynfeld[zaehler].messwert);
    
                zaehler++;
                //Rechnung noch nicht richtig? evtl wieoftdurchlaufne-1
                if (zaehler == 3*pow(2, wieoftdurchlaufen)) {
                //if (zaehler == 3*(2^(wieoftdurchlaufen)) ) {
                    dynfeld = (messwert*)realloc(dynfeld, 2*zaehler*sizeof(messwert));
                    if (dynfeld == NULL) {
                        printf("Speicher reservieren fehlgeschlagen!");
                        return 1;
                    }
                    wieoftdurchlaufen = 0;
                    printf("\nSpeicher erfolgreich verdoppelt!");
                    wieoftdurchlaufen++;
                }
                //zaehler++;
        }
    
    //    int zaehler2 = 0;
    //    int feldLaenge = sizeof(dynfeld)/sizeof(messwert);
    //    for (; zaehler2 < feldLaenge; zaehler++) {
    //        printf("\n%d,%s,%d,%f", dynfeld[zaehler].objekt->objektnr, dynfeld[zaehler].objekt->bezeichnung, dynfeld[zaehler].messnr, dynfeld[zaehler].messwert);
    //    }
        return 0;
    }
    

    Wenn ich

    while (fscanf(file, "%d %*c %19[^,] %*c%d %*c%lf\n", &tempobjektnr, tempbezeichnung, &tempmessnr, &tempmesswert ) == 4) {
    

    benutze werden wirklich nicht alle Werte eingelesen, mit

    while (feof(file)==0) {
    

    allerdings schon und das auch ohne einen Wert doppelt zu haben. Habs ja ausprobiert indem ich mir in die Zwischenvariablen in der Schleife ausgeben lasse.

    Das weist auf undefinierten Speicherzugriff hin.
    Wenn du unsicher bei malloc & Co. bist, dann nimm erstmal ein statisches Array

    Ich muss nur ein dynamisches Array benutzen.



  • Welche werte werden denn nicht eingelesen?



  • DirkB schrieb:

    Welche werte werden denn nicht eingelesen?

    Eingelesen werden:

    1,tower,2,17.410
    1,tower,4,18.342
    1,tower,6,17.523
    1,tower,7,17.683
    3,building,1,101.334
    3,building,2,107.128
    3,building,3,99.987
    3,building,3,105.821
    2,bridge,3,247.521
    2,bridge,4,248.731
    2,bridge,5,249.008
    

    Insgesamt gibt es:

    objektnummer,objektbezeichnung,messnummer,messwert
    1,tower,1,17.334
    1,tower,2,17.410
    1,tower,3,16.986
    1,tower,4,18.342
    1,tower,5,15.999
    1,tower,6,17.523
    2,bridge,1,249.121
    1,tower,7,17.683
    1,tower,8,18.001
    3,building,1,101.334
    1,tower,9,17.332
    3,building,2,107.128
    1,tower,10,18.019
    3,building,3,99.987
    3,building,3,110.320
    3,building,3,105.821
    2,bridge,2,251.988
    2,bridge,3,247.521
    1,tower,11,16.891
    2,bridge,4,248.731
    2,bridge,5,249.008
    

    Also wird jeder zweite und der letzte Wert gespeichert.



  • Wenn du Zeile 35 aktivierst, musst du auch Zeile 36 auskommentieren.
    Sonst liest du zwei Zeilen ein.



  • Oke das stimmt natürlich.
    Nur hat jemand noch einen Tipp, wie ich die Werte in das Array speichere?



  • Fang erstmal einfach an.

    typedef struct {
            int objektnr;
            char bezeichnung [20];
        } messobjekt;
    
        typedef struct {
            messobjekt objekt;  // mach hier das Objekt rein. Keinen Zeiger.
            int messnr;
            double messwert;
        } messwert;
    

    Das mit dem Speicher verdoppeln solltest du dir nochmal überlegen.
    Warum das 3*pow ?

    In size steht die Größe des Speichers.
    In zaehler der aktuelle Bedarf.
    Wann musst du den Speicher vergrößern?
    Welchen Wert bekommt size danach?



  • In dem Struct soll aber ein Zeiger sein. Ich kann ja nicht einfach die Aufgabe ändern 😃
    Ebenso wie den Speicher verdoppeln.
    Die if-Bedingung hab ich jetzt allerdings verändert.

    if (zaehler == size) {
                //if (zaehler == 3*pow(2, wieoftdurchlaufen)) {
                    dynfeld = (messwert*)realloc(dynfeld, 2*zaehler*sizeof(messwert));
                    if (dynfeld == NULL) {
                        printf("Speicher reservieren fehlgeschlagen!");
                        return 1;
                    }
                    size = 2*size;
                    printf("\nSpeicher erfolgreich verdoppelt!");
                }
    

    War wohl vorher ein bisschen zu kompliziert gedachte. Danke schon mal 😉



  • mezzix schrieb:

    In dem Struct soll aber ein Zeiger sein. Ich kann ja nicht einfach die Aufgabe ändern 😃

    Dann musst du vor jedem Zugriff auf objekt auch dafür Speicher mit malloc besorgen.



  • DirkB schrieb:

    mezzix schrieb:

    In dem Struct soll aber ein Zeiger sein. Ich kann ja nicht einfach die Aufgabe ändern 😃

    Dann musst du vor jedem Zugriff auf objekt auch dafür Speicher mit malloc besorgen.

    Vielen Dank! Da lag der Fehler 👍



  • Sorry, dass das nicht verständlicher war.
    Aber das meinte ich am 13:34:46 15.04.2014 mit "Du musst für jeden messwert auch ein objekt besorgen. "


Anmelden zum Antworten