Grenzen bei verschachtelten Schleifen



  • Hallo

    Eigentlich dachte ich, dass ich verschachtelte for Schleifen inzwischen verstanden habe, doch nun stocke ich bei folgendem Problem, was mir zeigt das ich es doch noch nicht wirklich verstanden habe.

    Ich habe eine Matrix A mit zwei Zeilen und vier Spalten und eine Matrix B mit vier Zeilen und vier Spalten, bzw. allgemein (r x n)-Matrix A und (s x n)-Matrix B. Nun möchte ich von jedem Zeilenvektor von A und jedem Zeilenvektor von B den Hammingabstand berechnen um zu testen ob Matrix A und B gleiche Zeilenvektoren besitzen (Hamming Abstand Null). Die Abstandsfunktion habe ich ausgegliedert und mit einem Unit Test auf Richtigkeit getestet. Nur bei den Schleifen erhalte ich immer eine Speicherfehler aufgrund der Unterschiedlichen Zeilenzahl von A und B.

    Wie würde man hier die Grenzen der for Schleifen richtig testen und ist es evtl. sinnvoller mit einer while und for Schleife zu arbeiten?

    Danke für Tipps und Grüße



  • Zwischen for- und while-Schleife besteht eigentlich kein Unterschied.

    Du kannst die (fast) jederzeit gegeneinader austauschen.

    Initialisierung;
    while(Bedingung){
      Schleifenkörper
      Inkrement
    }
    
    for(Initialisierung; Bedingung;Inkrement){
      Schleifenkörper
    }
    

    Der Unterschied liegt in der Gültigkeit der Schleifenvariablen, wenn du sie erst bei der Initialisierung definierst.

    Ohne Code von dir, wird das nichts.



  • Hallo

    Danke für deine Antwort. Etwas sehr schönes ist heute passiert. Ich konnte zum ersten mal eigenständig debuggen, indem ich mir immer alle Variable ausgeben ließ und so meine Fehler fand und dadurch sah ich wie man es richtig machen muss. Es läuft jetzt 🙂

    Falls jemand mal ein ähnliches Problem haben sollte hier mein Code. Falls man etwas besser machen kann würde ich mich über Tipps freuen.

    In meinem Header Routine.h

    int HammingDistance(std::vector<int> &vecA, std::vector<int> &vecB);
    void MatricesRowComparison(std::vector< std::vector<int> > &MatrixA, std::vector< std::vector<int> > &MatrixB);
    

    Die Source Datei Routine.cpp

    // _____________________________________________________________________
    // Hamming distance of two vectors
    int Routine::HammingDistance(std::vector<int> &vecA, std::vector<int> &vecB) {
    int hm_distance; hm_distance=0;
    
    for(size_t i=0; i<vecA.size(); i++){
    if(!(vecA[i]==vecB[i])){hm_distance++;} else{hm_distance=hm_distance+0;}
    }
    
    return hm_distance;
    }
    // _____________________________________________________________________
    // Compare the Hamming distance for each possible row of two matrices 
    void Routine::MatricesRowComparison(std::vector< std::vector<int> > &MatrixA, std::vector< std::vector<int> > &MatrixB) {
    std::ofstream print("./Output.txt",std::ios_base::app);
    
    int rowsA, columnsA, rowsB, dist;
    rowsA=MatrixA.size(); columnsA=MatrixA[1].size(); rowsB=MatrixB.size(); 
    
    std::vector<int> vectorsA(columnsA);
    std::vector<int> vectorsB(columnsA);
    
    for(int r=0; r<rowsA; ++r) {
      for(int s=0; s<rowsB; ++s) {
        for(int n=0; n<columnsA; ++n) {
          vectorsA[n]=MatrixA[r][n]; 
          vectorsB[n]=MatrixB[s][n]; 
        }  
      dist = Routine::HammingDistance(vectorsA, vectorsB); // Calculate Hamming distance
      if(dist==0) {print << std::endl << "Attractor " << s+1 << " is fixpoint for pattern " << r+1;} 
      else{continue;}
      }
    }
    
    }
    // _____________________________________________________________________
    

    Und in der main Funktion wird das dann aufgerufen

    Routine::MatricesRowComparison(pattern, attractors);
    

    (Bei mir heißt die Matrix A pattern und B heißt attractors)

    Grüße



  • Ein paar Kommentare dazu:

    • Mir gefällt dein Einrückstil nicht. Während vieles davon Geschmackssache ist, ist es doch überwiegender Konsens, dass du sowas wie if(!(vecA[i]==vecB[i])){hm_distance++;} else{hm_distance=hm_distance+0;} auf mehrere Zeilen aufteilen solltest. Außerdem würde ich auch den Code in Funktionen einrücken. Und Zeilen 29-31 sind falsch eingerückt. Ich persönlich mal clang-format sehr gerne zum automatischen Formatieren (Ich persönlich mag 4 Spaces Einrückung am liebsten).
    • vector::size() liefert size_t zurück, nicht int . Das ist bei dir durchgehend ignoriert. Sowas wie
    int rowsA, columnsA, rowsB, dist;
    rowsA=MatrixA.size(); columnsA=MatrixA[1].size(); rowsB=MatrixB.size();
    

    kannst du besser schreiben wie folgt:

    auto rowsA = MatrixA.size();
    auto columnsA = MatrixA[1].size();
    auto rowsB = MatrixB.size();
    

    und das dist kannst du später direkt in auto dist = HammingDistance(...) deklarieren.

    • Den ofstream würde ich von außen in die Funktion hineingeben, er hat ja mit der eigentlichen Berechnung nix zu tun (wenn es denn wirklich ein stream sein muss und die Funktion nicht vielleicht das Resultat in anderer Form zurückgeben könnte). Und print klingt eher nah dem Namen einer Funktion als nach einem Stream. Ich würde os als Namen vorschlagen.
    • Du solltest Parameter als const deklarieren, wenn du sie nicht änderst (Parameter von HammingDistance).
    • Wozu soll hm_distance=hm_distance+0; gut sein?!
    • Den Code habe ich nicht ganz genau durchgeguckt, aber du kopierst 2 Vectoren. Es sollte doch reinen, nur einen Matrix zu transponieren, aus der anderen kannst du die Zeilen doch direkt nehmen.

    Und zum Ende: ISLAND VOR!!!!!



  • Als Beispiel wie man es macht, ist das aber nicht geeignet.

    Wenn der else-Zweig keinen Effekt hat (+ 0), dann lass ihn komplett weg.

    Die n-Schleife kannst du weglassen,

    Ein

    dist = Routine::HammingDistance(vectorsA[r], vectorsB[s]);
    

    sollte reichen.



  • Danke für die Kritik. Ich werde versuchen sie umzusetzen.

    const-correctness ist etwas woran ich derzeit in meinen Büchern lese. Ich muss gestehen ich verstehe bei konkret diesem Punkt noch einiges nicht. Ich sah mir vor kurzem einen Vortrag an, der hat mich ehrlich gesagt aber nur mehr verwirrt. Dieser hier:

    https://www.youtube.com/watch?v=Y1KOuFYtTF4

    In meinem Buch steht aber auch noch viel das ich noch nicht gelesen habe. Ich bleibe am Ball und hoffe, dass das mit der Zeit und Übung schon wird.

    Grüße


Anmelden zum Antworten