Hilfe: Quelltext für Anfänger übersetzen :)



  • Hallo,

    ich bin absoluter C-Anfäger. Ich muss eine Funktion bis ins kleinste Detail verstehen, um sie mit der Programmiersprache ABAP umzusetzen.

    Es handelt sich um eine Ähnlichkeitsprüfung von zwei Strings.
    ___________________________________________________________________________

    * {{{ php_similar_str
     */
    static void php_similar_str(const char *txt1, int len1, const char *txt2, int len2, int *pos1, int *pos2, int *max)
    {
    	char *p, *q;
    	char *end1 = (char *) txt1 + len1;
    	char *end2 = (char *) txt2 + len2;
    	int l;
    
    	*max = 0;
    	for (p = (char *) txt1; p < end1; p++) {
    		for (q = (char *) txt2; q < end2; q++) {
    			for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
    			if (l > *max) {
    				*max = l;
    				*pos1 = p - txt1;
    				*pos2 = q - txt2;
    			}
    		}
    	}
    }
    /* }}} */
    

    ___________________________________________________________________________

    Ein kleines Beispiel:
    STRING 1: KIRSCHE STRINGLÄNGE 1: 7
    STRING 2: KRISCH STRINGLÄNGE 2: 6

    Ich habe das Zeugs soweit verstanden, dass die Funktion mit php_similar_str(KIRSCHE, KRISCH, 7, 6, 0, 0, 0) aufgerufen wird.
    p und q werden als Variablen für zwei Schleifen gebraucht, die über das erste beziehungsweise verschachtelt über das zweite Wort laufen.

    Probleme habe ich mit der dritten for-Schleife und den Belegungen von pos1 und pos2. Vielleicht kann man "schnell" - wenn das geht - einen kurzen Ablauf von meinen Beispielstrings (oder kürzeren Worten) auflisten. Das würde mir riesig helfen.

    Vielen Dank schon im Voraus.
    Gruß
    Ben

    <hume sagt>Bitte Code-Tags verwenden</hume sagt>



  • Diese Funktion vergleicht zwei strings und sucht die am meisten zusammenhängenden zeichen. dann gibt sie zurück
    max = Anzahl der zusammenhängenden zeichen
    pos1 = beginn im 1. string
    pos2 = beginn im 2. string



  • Ich habe das Zeugs soweit verstanden, dass die Funktion mit php_similar_str(KIRSCHE, KRISCH, 7, 6, 0, 0, 0) aufgerufen wird.

    Das wäre keine gute Idee, denn dein Computer mag es nicht sonderlich wenn Null-Pointer dereferenziert werden.

    Zu den Parameter: Die ersten vier sollten klar sein.
    max ist ein Zeiger auf einen int in dem die Länge der längsten Übereinstimmung der beiden Strings gespeichert wird.
    pos1 und pos2 sind Zeiger auf int in denen die Anfangspositionen (in den beiden Strings) für die längste Übereinstimmung gespeichert wird.

    Bei deinem Beispiel:
    Die längste gemeinsame Zeichenkette in KIRSCHE und KRISCH ist SCH. max hat am Ende also den Wert 3, pos1 den Wert 3 (SCH startet in KIRSCHE an Position 3) und pos2 hat ebenfalls den Wert 3.

    Die wichtigsten Sachen sind:
    1. In C beginnt man beim Zählen bei 0

    2. pos1, pos2, max sind sogenannte out-Parameter. Da C keine Referenzen kennt musst du Adressen auf Variablen an eine Funktion übergeben, wann immer eine Funktion die Variablen nach außen sichtbar ändern können soll.
    Sprich der Aufruf von php_similar_str sieht so aus:

    const char* s1 = "KIRSCHE";
    const char* s2 = "KRISCH";
    int max, pos1, pos2;
    php_similar_str(s1, strlen(s1), s2, strlen(s2), &pos1, &pos2, &max);
    

    Nachher stehen in pos1, pos2 und max die Ergebnisse der Funktion.

    for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
    if (l > *max) {
        *max = l;
        *pos1 = p - txt1;
         *pos2 = q - txt2;
    }
    

    Man achte auf das Semikolon hinter der Schleife. Die if-Bedingung ist also *nicht* der Schleifenkörper.

    Die Schleife zählt ausgehend von den aktuellen Positionen in den beiden Strings
    die Anzahl der gleichen Zeichen.

    4. p - txt1: Die Subtraktion zweier Pointer liefert ein int. txt1 ist die Startadresse des Strings. p ein Zeiger auf die aktuelle Position (p ist immer >= txt1).
    Die Subtraktion dieser beiden Zeiger liefert dir den Abstand von p zur Startposition, also an welcher Position du dich gerade realtiv vom Start befindest. Wenn du den String "KIRSCHE" hast und p zeigt auf das C,
    dann ist p - txt1 = 4.

    Am Beispiel:
    Freie Turner Braunschweig
    FSV Babelsberg

    Die größte Gemeinsamkeit dieser beiden Vereine (bis auf die Tatsache das ich bei beiden gespielt habe) ist ein "er". Einmal bei Turner und einmal
    bei Babelsb[er]g.
    Der Algo sollte also für max 2 liefern für pos1 10 und für pos2 11.

    Gehen wir das Schritt für Schritt durch.
    1. Am Anfang ist p = q = 0. Deine Zeiger zeigen also jeweils auf den Start der beiden Wörter.

    2. Von den aktuellen Positionen aus schauen wir ob die beiden Wörter an dieser Stelle gleich sind.
    -> F aus Freie ist gleich F aus FSV also wird l auf um eins erhöt.
    -> r ist ungleich S also ist dir innere Schleife beendet.
    Da wir max mit 0 initialisiert haben und da l = 1 und 1 > 0 ist, setzen wir max auf 1 pos1 auf p - txt1 = 0 und pos2 auf q - txt2 = 0.
    Bisher ist die längste Gemeinsamkeit das F.

    3. Jetzt erhöhen wir q gehen im ersten Wort also einen Schritt weiter: *q = S
    -> Da SV Babelsberg kein weiteres F mehr enthält kann die innere Schleife keine weitere Übereinstimmung mehr finden.
    Die Schleife für q läuft also vollständig durch.

    4. Wir erhöhen p und fangen bei q von vorne an: *p = r, *q = F
    FSV Babelsberg enthält ein r. Die innerste Schleife wird also zum ersten mal interessant, wenn q an Position 12 steht.
    Allerdings ist der gleiche Teilstring dort wieder nur ein Zeichen lang, denn bei Freie Turner folgt auf das r ein e und bei Babelsberg folgt ein g.
    max wird also nicht weiter aktualisiert.

    Das geht jetzt so weiter bis wir mit p auf dem e von Truner stehen. Also:
    *p = e, *q = F.
    -> Wir durchwandern q bis wir auf ein e treffen. Das erste e ist an Position 7. Von Position 7 im Babelsberg Sting und Position 10 im Turner String suchen wir die längste Übereinstimmung -> Nur ein Zeichen -> Also weiter.
    Das nächste e im Babelsberg String ist an Position 11.
    Von Position 11 im Babelsberg Sting und Position 10 im Turner String suchen wir die längste Übereinstimmung -> Wow. Zwei Zeichen, nämlich e und r sind relativ zu diesen beiden Positionen gleich.
    Da wir damit ein neues Maximum haben, speichern wird die neuen Werte (max,pos1, pos2).

    Der Rest geht analog weiter, ohne ein neues Maximum zu finden.

    Einigermaßen verstanden?



  • sehr schön erklärt hume 😃



  • Vielen Dank euch allen. Vor allem aber dem ehemaligen Spieler der Freien Turner mit dem ich in der Jugend zusammen gespielt habe 🙂

    Wie klein ist doch die Welt.

    Gruß an Benjamin
    Benjamin


Anmelden zum Antworten