Matrix aus Datei einlesen volldynamisch mehrdimensional



  • Hallo an alle,

    da ich hier neu bin, erst mal n wenig zu mir - ich bin 'n recht frischer Informatikstudent
    und seit neuestem auf nem C Trip - in der Uni bieten se nur Java 🙂

    Genug der Worte nun zum Problem:

    Ich würde gerne eine Matrix aus einer Datei einlesen, dabei können die Dimensionen
    der Matrix von Datei zu Datei variieren.
    Um die Matrixgrösse anzupassen hab ich mir mal das folgende Codeschnipsel geschrieben - läuft merkwürdigerweise nur in einem von 3 Compilern.
    Die Frage wär nun, was soll ich anders/besser machen 🙂

    #include  <stdio.h>
      #include  <iostream.h>
      #include  <stdlib.h>
    
    struct x
    {
        int a;
        char *b;
    };
    
    main() {
        struct x z;
        z.a = 10;
        z.b = "test";
        cout << z.a;
        cout << z.b;
        cout << "\n";
    
        //Array
    
        int zeile = 4;
        int spalte =4;
        int i;
        struct x ** matrix;
    
        //Speicher zuweisen Zeilen
    
        matrix = (struct x **)malloc(zeile * sizeof(struct x));
    
        //Speicher für Spalten zuweisen
        i = 0;
        for ( i;i<zeile;i++) {
    
            matrix[i] = (struct x *)malloc(spalte * sizeof(struct x));
    
        }
    
        // Matrix mit Werten belegen
    
        for (int l=0;l<4;l++) {
            struct x g[l];
            if(l==1)
            g[l].b = "Erster Wert";
            else
            g[l].b = "Zweiter Wert";
            matrix[l][l] = g[l];
    
            cout << l << ". Lauf \n";       //Kontrollausgabe
        }
    
        struct x t;
    
        for (int w=0;w<4;w++) {
            t = matrix[w][w];
            cout << t.b << "\n";
        }
    
        // (realloc) Dynamische Erweiterung der Matrix
    
        // Neue Grösse
        zeile = 5;
        spalte = 5;
    
        matrix = (struct x **)realloc(matrix,zeile * sizeof(struct x));
        cout << "--------------------------\n"; // Kontrollausgabe
        for (int v=0;v<zeile;v++) {
            cout << "--------------" << v << "------------ \n";  // Kontrollausgabe
            matrix[v] = (struct x *)realloc(matrix[v],spalte * sizeof(struct x));
        }
    
       cout << "\nAusgabe nach Erweiterung\n\n";
    
        //Testwerte einfüllen
        for (int l=0;l<5;l++) {
            struct x g[l];
            g[l].b = "RR";
            matrix[0][l] = g[l];
        }
        matrix[4][4] = z;
        //Testwerte Ausgeben
        for (int w=0;w<5;w++) {
            cout << w << ". Wert : ";
            t = matrix[w][w];
            cout << t.b << "\n";
        }
    
        system("pause");
    }
    

    Und ist das überhaupt eine gute Idee das so zu machen - wie könnte man das anders machen?
    Vorallem bei Zeile 45 bin ich mir recht unsicher, wie bekomme ich denn das schön
    dynamisch gebacken? (Erzeugen von x char Speicherplätzen, die nicht löschen und
    ihren Anfang ins Array speichern)

    EDIT: Ok die structs auserhalb der Schleifen zu deklarieren und ohne Variable hat schon mal geholfen, es läuft nun überall...
    Wenn ich zeile 85 allerdings auskommentiere, dan wirft mir borland einen Fehler
    - Speicherzugrifsverletzung - ich denk mal, weil dann ein Wert gefragt wird, der nicht gesetzt wurde, andere Compiler geben da dann halt Müll zurück -
    Wie kann ich denn das elegant lösen?

    MfG



  • Hallo,

    ich weiss zwar nicht, was du mit deinem Programm bewirken moechtest, aber ich
    habe da mal ein paar Zeilen geaendert. Unter Linux kompiliert und laeuft as Programm so mit g++:

    [b]#include <iostream> //Die Klasse heisst nun so[/b]
    [b]#include <string.h> //wird fuer memset benoetigt[/b]
    
    [b]using namespace std; //sonst gibt es kein cout [/b]
    
    struct x {
         int a;
         char *b; 
    };
    
    struct x ** resize_matrix (struct x ** matrix, int old_z, int old_s, int new_z, int new_s) {
         [b]matrix = (struct x **)realloc(matrix, new_z * sizeof(struct x *)); //Hier hattest du einen Fehler[/b]
         cout << "--------------------------" << endl; // Kontrollausgabe
         for (int v=0; v<new_z; ++v) {
             cout << "--------------" << v << "------------ " << endl;  // Kontrollausgabe
             matrix[v] = (struct x *)realloc(matrix[v], new_s * sizeof(struct x));
             [b]if (v>=old_z) memset(matrix[v], 0x0, new_s * sizeof(struct x));[/b]
             [b]else memset(matrix[v]+old_s, 0x0, (new_s-old_s) * sizeof(struct x));[/b]
         } 
    
         return matrix;
    }
    
    int main(void) {
         struct x z; 
         z.a = 10; 
         z.b = "test"; 
         cout << z.a << "  " << z.b << endl; 
    
         //Array 
    
         int zeile  = 4; 
         int spalte = 4; 
         int i; 
    
         struct x ** matrix; 
    
         //Speicher zuweisen Zeilen 
    
         [b]matrix = (struct x **) malloc(zeile * sizeof(struct x *)); //Hier hattest du einen Fehler[/b]
    
         //Speicher für Spalten zuweisen 
         for (i=0; i<zeile; ++i) {
            matrix[i] = (struct x *) malloc(spalte * sizeof(struct x));
            [b]memset(matrix[i], 0x0, spalte * sizeof(struct x)); // Speicher, der mit malloc alloziert wurde, sollte initialisiert werden[/b]
         }
    
         // Matrix mit Werten belegen 
    
         for (int l=0; l<4; ++l) {
            if (l == 1)  matrix[l][l].b = "Erster Wert"; [b]//das scheint zu klappen, ob das richtig ist, weiss ich nicht [/b]
            else         matrix[l][l].b = "Zweiter Wert"; [b] // dito [/b]
            cout << l << ". Lauf " << endl;       //Kontrollausgabe
         } 
    
         struct x t; 
    
         for (int w=0; w<4; ++w) {
             t = matrix[w][w]; 
             cout << t.b << endl; 
         } 
    
         // (realloc) Dynamische Erweiterung der Matrix
    
         // Neue Grösse 
         [b]matrix = resize_matrix(matrix, 4, 4, 5, 5); //Laengere Programmteile in Funktionen auslagern[/b]
    
         cout << "\nAusgabe nach Erweiterung\n\n";
    
         //Testwerte einfüllen 
         for (int l=0; l<5; ++l) matrix[0][l].b = "RR";
         matrix[4][4] = z; 
    
         //Testwerte Ausgeben 
         for (int w=0; w<5; ++w) cout << w << ". Wert : " << matrix[w][w].b << endl;
    
        return 0;
    }
    

    Da ich nicht so recht weiss, was du eigentlich mit machen moechtest, kann ich
    nichts weiter zu sagen. Vielleicht nur noch eins: mir gefaellt es nicht.

    Da ich eher in C statt in C++ bewandert bin, kann es sehr gut sein, dass ich
    Fehler uebersehen habe.

    Was meinst du mit volldynamisch und mit mehrdimensional?

    Viel Spass damit
    mcr



  • Ach uebrigens,

    was du hier schreibst ist kein reiner C-Code, sondern eher C++.
    Gehoert also nicht hier hin. 😉

    Gruss mcr



  • mcr schrieb:

    Ach uebrigens,

    was du hier schreibst ist kein reiner C-Code, sondern eher C++.
    Gehoert also nicht hier hin. 😉

    Gruss mcr

    Bis auf das cout ist der Code aber sehr C-isch. Der OP darf selbst entscheiden, ob der diese durch printf()s ersetzt oder ob ich ihn zu den C++-Leuten verschiebe, die ihm sicher std::vector und ähnliches um den Latz knallen werden 😉



  • Hi,

    danke erst mal für deine Mühe 🙂
    Immerhin war ich nah dran...
    Das mit dem initialisieren is gut, wusst nicht wie das geht...
    Ok, das cout wird gestrichen 🙂 Soll eigentlich reiner C Code sein!!
    Witziger Weise hats der Borlandcompiler trotz angehaktem C verstanden...

    Das Ziel vom Ganzen soll sein, 2 oder mehr Textdateien ein zu lesen, welche
    Matrixform haben, dabei kann aber auch so was auftreten
    ->

    ...23 44 47
    ...34 34... <- Lücke
    34 34 -6..3

    Und diese dann eben bequem zu verarbeiten, dachte mir Arrays sint da ganz nützlich.
    Das abenteuerliche Struct Konstrukt kommt daher, das ich mir nicht Helfen konnte
    als es darum ging char Werte vernünftig im Array zu Lagern, ich weis ja nicht
    wie gross die Zahlen werden...

    MfG



  • Hallo,

    ok, man muesste noch ein zwei stellen weiter aendern, damit da dann ansi c draus wird.

    1. iostream gibt es in es nicht, da heisst es dann stdio.h
    2. Variablen muessen am Anfang eines Blockes deklariert werden (ok, nach dem neuen Standard nicht)
    3. // ist kein gueltiges Kommentarzeichen. Hier verwendet man /* */

    Bei Zuweisungen wie z.b = "test" bin ich mir nicht sicher. Ich haette
    ausreichend Speicher mit malloc alloziert und dann sprintf oder memcpy
    gemacht.

    Das mit den Luecken habe ich nicht so ganz verstanden.
    Wenn du die Moeglichkeit hast auf die Gestaltung der Dateien Einfluss zu nehmen, wuerde ich vorschlagen, du gibst ein Format fuer diese vor. So z.B.:

    1.Zeile: Anzahl Zeilen Anzahl Spalten
    jede weitere Zeile: immer Anzahl Spalten viele Zahlen

    Dadurch waere das Einlesen deutlich leichter gemacht und kannst dich dann deiner eigentlichen Aufgabe widmen.

    Hier noch mal mein Code nach Ansi C konvertiert:

    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    
    #include <string.h>
    
    struct x {
         int a;
         char *b;
    };
    
    struct x ** resize_matrix (struct x ** matrix, int old_z, int old_s, int new_z, int new_s) {
         int v;
         matrix = (struct x **)realloc(matrix, new_z * sizeof(struct x *));
         printf("--------------------------\n");
         for (v=0; v<new_z; ++v) {
             printf("--------------%d------------\n", v);
             matrix[v] = (struct x *)realloc(matrix[v], new_s * sizeof(struct x));
             if (v>=old_z) memset(matrix[v], 0x0, new_s * sizeof(struct x));
             else memset(matrix[v]+old_s, 0x0, (new_s-old_s) * sizeof(struct x));
         }
    
         return matrix;
    }
    
    int main(void) {
         struct x ** matrix;
         struct x z;
         int zeile  = 4;
         int spalte = 4;
         int i;
    
         z.a = 10;
         z.b = "test";
         printf("%d  %s\n", z.a, z.b);
    
         /* Speicher zuweisen Zeilen */
         matrix = (struct x **) malloc(zeile * sizeof(struct x *));
    
         /* Speicher für Spalten zuweisen */
         for (i=0; i<zeile; ++i) {
            matrix[i] = (struct x *) malloc(spalte * sizeof(struct x));
            memset(matrix[i], 0x0, spalte * sizeof(struct x));
         }
    
         /* Matrix mit Werten belegen */
         for (i=0; i<4; ++i) {
            if (i == 1) matrix[i][i].b = "Erster Wert";
            else matrix[i][i].b = "Zweiter Wert";
            printf("%d.Lauf\n", i);
         }
    
         for (i=0; i<4; ++i) printf("%s\n", matrix[i][i].b);
    
         /* (realloc) Dynamische Erweiterung der Matrix */
         /* Neue Grösse */
         matrix = resize_matrix(matrix, 4, 4, 5, 5);
    
         printf("\nAusgabe nach Erweiterung\n\n");
    
         /* Testwerte einfüllen */
         for (i=0; i<5; ++i)  matrix[0][i].b = "RR";
    
         matrix[4][4] = z;
    
         /* Testwerte Ausgeben */
         for (i=0;i<5;++i) printf("%d. Wert : %s\n", i, matrix[i][i].b);
    
         return 0;
    }
    


  • Hi,

    ich denke du hast Recht, ich werde mich vorerst mit einer vorgegebenen Formatierung
    der Textfiles zufrieden geben 🙂
    Und danke nochmals für das Umstricken meines Codes...

    MfG,
    RZ


Anmelden zum Antworten