PHP if (($lines[$x] == "\r") || ($lines[$x] == "")) 2x true möglich?

smallwall

Lt. Junior Grade
Registriert
Feb. 2014
Beiträge
446
Hallo,
ich habe hier ein seltsames Problem, es wird 2x der true Zweig angesteuert, hier der Quote:

Code:
    public function readpgnforedits($file) {
        $f = file_get_contents($file);
        $lines = explode("\n", $f);
        $nextgame = 0;
        $moves = array();

        $movesnum = 0;

        echo('<h2>Änderung an &nbsp;' . $file . '</h2>' . "\n");

        echo('<FORM action="writepgn.php" method="POST" class="readpgn">' . "\n");

        for ($x = 0; $x <= count($lines); $x++) {
            $xi = $x + 1;
            // seperate by spaces
            $comp = explode(" ", $lines[$x]);
            //if line begins with [
            if (substr($lines[$x], 0, 1) == "[") {

                if (count($comp) > 2) {
                    $first = substr($comp[0], 1);
                    $lastpart = array_slice($comp, 1);
                    $last = implode(" ", $lastpart);
                    $last = substr($last, 0, -3);
                    $last = substr($last, 1);
                } else {
                    $first = substr($comp[0], 1);
                    $last = substr($comp[1], 0, -3);
                    $last = substr($last, 1);
                }
                    echo('<label for="' . $first . $nextgame . '">' . $first . '&nbsp;&nbsp;&nbsp;</label>' . "\n");
                    echo('<INPUT type="text" VALUE="' . $last . '" name="' . $first . $nextgame . '"><br><br>' . "\n");

            } else {

                // if line doesn't begin with [ it must be a moves line or empty line
/////////
// HIER IST DAS PROBLEM!!!!
////////////
                    if (($lines[$x] == "\r") || ($lines[$x] == "")) {
                    echo('<input type="hidden" name="emptyline">'."\n");
                    } else {
                        array_push($moves, $lines[$x]);
                    }
                // check next line for header line?
                if (substr($lines[$xi], 0, 1) == "[") {

                    echo('<label for="thisismovesline' . $nextgame . '">Moves&nbsp;&nbsp;&nbsp;<div class="small">Änderungen hier sind nicht empfohlen</div></label>' . "\n");
                    echo("\n<textarea name=\"thisismovesline" . $nextgame . "\" rows=\"20\" cols=\"90\">");
                    $moves = implode("\n", $moves);
                    echo $moves;
                    echo('</textarea><br>' . "\n");
                    $nextgame++;
                    unset($moves);
                    $moves = array();
                    echo("<hr>\n");
                }
                // this adds last textarea, sadly condition above is wrong or something..
                if (($xi > count($lines))) {

                    echo('<label for="thisismovesline".$nextgame.">Moves&nbsp;&nbsp;&nbsp;<div class="small">Änderungen hier sind nicht empfohlen</div></label>' . "\n");
                    echo("\n<textarea name=\"thisismovesline" . $nextgame . "\" rows=\"20\" cols=\"90\">");
                    $moves = implode("\n", $moves);
                    echo $moves;
                    echo('</textarea><br>' . "\n");
                    $nextgame++;
                    unset($moves);
                    $moves = array();
                    echo("<hr>\n");
                }
                
            }

        }

        echo $nextgame . " Games in this .pgn file.<br>\n";

        echo("\n" . '<br><input type="hidden" id="file" name="filename" value="' . $file . '">');
        echo("<br>\n");
        echo("\n" . '<label for="pw">Passwort&nbsp;&nbsp;&nbsp;</label>');
        echo("\n" . '<input type="password" name="pw" id="pw" maxlength="64">');
        echo("\n" . '<br><br><input type="submit" id="ok" value=" Ändern ">');
        echo("\n" . '<input type="reset" id="reset" value=" Reset ">');

        echo("\n" . '</FORM>');
    }
Es handelt sich um eine Art Editor für .pgn Dateien (Schachpartien), ich möchte einfach wenn die $lines empty ist oder halt der Windows "\r" einmal das hidden Feld emptyline ausgeben, bei meinen Versuchen wird es aber doppelt ausgegeben oder gar nicht. Versteht das einer? Wieso? Welhalb? Stackoverflow würde ich gerne Fragen, aber die haben mich gesperrt.

mfg
 
Das wüsste ich auch gern. "You have reached your question limit" steht halt dort. "Stack Exchange has automatic filters in place to ban questions from accounts that have contributed many low-quality questions in the past"
 
smallwall schrieb:
"Stack Exchange has automatic filters in place to ban questions from accounts that have contributed many low-quality questions in the past"

Sagt eigentlich alles oder?
Sorry, aber das ist kein PHP, das ist Kauderwelsch. Einrückungen sind wirr, Variablen sprechen auch nicht für sich. Das ist einfach Chaos. Python würde dir den Text sowas von um die Ohren hauen, der würde gar nicht mal versuchen den auszuführen.
Versuchs mal mit einer schönen Formatierung, dann liest man sich das auch freiwillig als nicht Betroffener durch und meist sieht man dann die Logikfehler auch viel schneller selbst
 
Naja bis auf die eine if-Sache läuft es ohne Probleme durch. Eingerückungen sind nicht wirr, Netbeans hat das eingerückt. Variablen namen sind auch nicht sooo wirr, es wird eine $file gelesen, dann auf \n (newlines) explodiert und dann wird Zeile für Zeile gelesen. Es gibt 2 verschiedene Arten von Zeilen, die, die mit [ beginnen und die, die eben nicht mit [ beginnen. Wenn [ am Anfang steht, wird die Zeile bis zum ersten " " Leerzeichen gelesen und als name des Input Felds genommen, der Rest wird als Wert verwendet (+ etwas zurechtgestutze). Naja dann die besagte Stelle, wenn die Zeile leer ist, soll das hidden Feld "emptyline" EINMAL statt 2x oder gar nicht ausgegeben werden.

Ok, hier ist das ganze nochmal neu, ich hatte eine sehr dumme Wiederholung im Code.

Code:
    public function readpgnforedits($file) {
        $f = file_get_contents($file);
        $lines = explode("\n", $f);
        $gamenum = 0;
        $moves = array();

        echo('<h2>Änderung an &nbsp;' . $file . '</h2>' . "\n");

        echo('<FORM action="writepgn.php" method="POST" class="readpgn">' . "\n");

        for ($x = 0; $x <= count($lines); $x++) {
            $xi = $x + 1;
            // seperate by spaces
            $spaces = explode(" ", $lines[$x]);
            //if line begins with [
            if (substr($lines[$x], 0, 1) == "[") {

                if (count($spaces) > 2) {
                    $headername = substr($spaces[0], 1);
                    $headervalue = array_slice($spaces, 1);
                    $headervalue = implode(" ", $headervalue);
                    $headervalue = substr($headervalue, 0, -3);
                    $headervalue = substr($headervalue, 1);
                } else {
                    $headername = substr($spaces[0], 1);
                    $headervalue = substr($spaces[1], 0, -3);
                    $headervalue = substr($headervalue, 1);
                }
                
                echo('<label for="' . $headername . $gamenum . '">' . $headername . '&nbsp;&nbsp;&nbsp;</label>' . "\n");
                echo('<INPUT type="text" VALUE="' . $headervalue . '" name="' . $headername . $gamenum . '"><br><br>' . "\n");
                
            } else {
                // if line doesn't begin with [ it must be a moves line or empty line
                // HIER IST DAS PROBLEM!!!
                if (($lines[$x] == "\r") || ($lines[$x] == "")) {
                    echo('<input type="hidden" name="emptyline">' . "\n");
                }
                
                array_push($moves, $lines[$x]);
                
                // check next line for header line, or is it end of $lines?
                if ((substr($lines[$xi], 0, 1) == "[") || ($xi > count($lines))) {

                    echo('<label for="thisismovesline' . $gamenum . '">Moves&nbsp;&nbsp;&nbsp;<div class="small">Änderungen hier sind nicht empfohlen</div></label>' . "\n");
                    echo("\n<textarea name=\"thisismovesline" . $gamenum . "\" rows=\"20\" cols=\"90\">");
                    $moves = implode("\n", $moves);
                    echo $moves;
                    echo('</textarea><br>' . "\n");
                    $gamenum++;
                    unset($moves);
                    $moves = array();
                    echo("<hr>\n");
                }
            }
        }

        echo $gamenum . " Games in this .pgn file.<br>\n";

        echo("\n" . '<br><input type="hidden" id="file" name="filename" value="' . $file . '">');
        echo("\n<br>");
        echo("\n" . '<label for="pw">Passwort&nbsp;&nbsp;&nbsp;</label>');
        echo("\n" . '<input type="password" name="pw" id="pw" maxlength="64">');
        echo("\n" . '<br><br><input type="submit" id="ok" value=" Ändern ">');
        echo("\n" . '<input type="reset" id="reset" value=" Reset ">');

        echo("\n" . '</FORM>');
    }
Und $x ist die Zeilennummer, $lines[$x] ist halt die Zeile $x...
Wenn die Zeile nicht mit [ beginnt, wird eine Textarea geschrieben, sonst die Inputs mit $headername, $headervalue. Die leeren Zeilen sollten einmal die emptyline ausgeben, nicht 2x oder 6x oder gar nicht.
 
Zuletzt bearbeitet:
Das macht für die besagte if Abfrage keinen Unterschied, das wäre ganz am Ende der Datei interessant, aber ich liegt jetzt schon im Bett :-)
 
du machst halt vieles falsch.. schreib ertsmal ordentlichen code.. dann wirst du den fehler bestimmt finden..

du hast halt halt ein if else in einer for welches weitere verschachtelungen etnhält.. das kann kein mensch lesen.. und html ausgabe gehört da nicht rein.
 
Ist halt einfach engstirnig zu behaupten, der Code wäre "Falsch" oder "nicht ordentlich". Falsch ist es doch erst, wenn der Interpreter es sagt, und der sagt es erst, wenn er es nicht verstehen kann. In diesem Fall scheint er es ja so gut zu verstehen, dass er es gleich 2x ausführt. Gültige Syntax ist niemals falsch. Wenn es für ein Problem 20 Lösungen gibt und ich die schlechteste schreibe, ist es immer noch nicht falsch, im Höchstfall ineffiziennt, aber deshalb nicht gleich falsch.

Was genau ist denn bitte "falsch" oder "nicht ordentlich"? Den oberen Teil der ersten if-condition könnt ihr ja komplett ignorieren, es gibt dort kein Problem. Und wieso sollte man keine HTML-Ausgaben schreiben? Jede dynamische Seite macht das doch, sonst könnte sie nicht dynamisch sein.
 
Zuletzt bearbeitet:
PHP interpretiert deinen Code sicherlich nicht falsch. Wenn, dann ist deine Programmlogik fehlerhaft. Gib lieber mal ein Beispiel für eine solche pgn-Datei, die du auswerten willst. Dann kann man das auch mal besser nachvollziehen, was du überhaupt willst.
 
Meinst Du bei der for-Schleife? Das ist nicht das Problem, wenn ich $x<count.. statt $x<=count... schreibe wird die letzte Zeile nicht beachtet, $x<=count($lines) ist richtig und notwendig, ebenso wenn ich bei $x=1 statt $x=0 anfange, wird die erste Zeile nicht beachtet.
if .... then.. sollte so eindeutig sein, dass es dort keine Zaunpfahlprobleme geben sollte, dafür gibt es ja genug Operatoren. Verstehe beim besten willen nicht, was mit der Zeile los ist, aber ich habe inzwischen einen extrem dreckigen Workaround geschrieben, der bisher bei meinen Tests immer funktioniert hat, hoffentlich bleibt das so :)

Eine Beispieldatei findet ihr hier: http://www.devphp.de/pgn/pgnfiles/pach.pgn
Weitere unter http://devphp.de/pgn/pgnfiles/, die pach.pgn ist deshalb so intressant, da sie mehrere Partien beinhaltet und somit sich "Headerlines mit [" und Zug/Kommentar-Zeilen sich abwechseln.
 
Zuletzt bearbeitet:
Wie gesagt: Das Programm verhält sich richtig, deine Logik bzw. deine Erwartung an das, was das Programm machen soll, ist allerdings falsch.

Dazu gibt es allerdings noch zu sagen: Schalte das Error-Reporting an. Direkt beim Start hat mir es mir zig Fehler um die Ohren gehauen, allesamt bezogen auf Zugriff auf Indexpositionen, die es nicht gibt. Siehe dazu die anderen Kommentare.

Die doppelten und dreifachen "Leerzeilen" (mit den hidden inputs) kommen dadurch, dass dein Script alle Leerzeilen in der pgn-Datei "einsammelt". Erst kommen die Zeilen, die mit [ anfangen, dann üblicherweise eine Leerzeile (das ist das erste "hidden input"-Feld), dann kommt der Textblock mit den Spielzügen (der wird in der for-Schleife komplett übergangen), danach kommen wieder eine oder mehrere Leerzeilen, die jetzt wieder eingefangen und ausgegeben werden. Und dann hast du halt deine zig Leerzeilen hintereinander. Vom Programmablauf ist das alles genau das, was da steht.
 
Hi,
ihr braucht das nicht weiter anschauen, der Workaround funktioniert erstmal.

Ich habe genau null Fehlermeldungen mit error_reporting(E_ALL);

Zu der Logik: In Zeile 43 wird "in die nächste Zeile geschaut" ($lines[$xi] und nicht $lines[$x], $xi ist immer $x+1), wenn diese wieder mit [ beginnt (oder es sie gar nicht gibt), wird die Textarea geschrieben mit $moves als Inhalt.
Kurz davor ist die besagte Zeile mit
PHP:
if (($lines[$x] == "\r") || ($lines[$x] == "")) {
                    echo('<input type="hidden" name="emptyline">' . "\n");
                }
Diese bewirkt, dass das hidden Feld 2x geschrieben wird. Wieso auch immer, für mich ist das nicht "alles genau das, was da steht." Es sollte nur das hidden Feld ausgegeben werden, wenn die aktuelle Zeile leer ist.

Naja ihr könnt hier dicht machen, problem "solved" bzw workedaround.

http://www.devphp.de/pgn/readpgnerr.php
 
Zuletzt bearbeitet:
Ja, und dein $xi wird am Ende IMMER größer sein als die maximale Anzahl an Zeilen. Und da du nicht überprüfst, ob der Index zu groß ist sondern direkt auf den nicht vorhandenen Index zugreifen willst, kommt hier zwangsläufig ein Fehler.
Und noch einmal zum Problem: Lass dir vor Zeile 41 in dem Code aus Post #1 einfach ausgeben, was in $x steht, dann siehst du genau, woher die Leerzeilen kommen und warum auf einmal mehrere direkt hintereinander stehen.
 
Wieso sollte $xi immer größer sein als die Zeilenanzahl? Es steht doch $xi = $x + 1; in der for-Schleife, also ist $xi immer 1 mehr als $x.
Und erst NACH der emptyline Zeile wird darauf zugegriffen.
Code:
if ((substr($lines[$xi], 0, 1) == "[") || ($xi > count($lines)))
Zu deutsch: wenn die nächste Zeile wieder mit [ beginnt oder $xi größer als die Zeilenanzahl.... schreibe die Textarea, lösche die gesammelten Zeilen aus $moves und lege $moves neu an.
Danach fängt die Zeile $x wieder mit [ an und es werden Input fields geschrieben mit den zurechtgestutzen $headername, $headervalue.

Code:
if (($lines[$x] == "\r") || ($lines[$x] == "")) { echo('<input type="hidden" name="emptyline">' . "\n");  }
Ist doch recht einfach zu lesen. Wenn die Zeile =="" oder =="\r" ist->emptyline. Sonst nix, einfach einmal ausgeben. $xi ist hier nicht zu sehen und ist komplett egal.
 
Sorry, ich kenne keine weiteren Worte, mit denen ich dir die Logikfehler in deinem Script noch deutlicher beschreiben könnte. Aber da es ja für dich jetzt funktioniert, ist doch alles in Ordnung. Belassen wir es dabei.
 
Genau, es funktioniert wie gewünscht mit meinem Workaround und beinhaltet somit genau null Logikfehler, die der Interpreter auf magische Weise sonst kompensieren würde. Den Workaround könnte ich auch noch Posten, aber das Interesse wird wohl eher gering sein.
 
Zurück
Oben