PHP Newbe: Script zum Verzeichnis erstellen

Hallo,
bin gerade dabei PHP zu lernen und habe aus einem Buch "Programmieren lernen in PHP5" folgendes Script zum erstellen eines Verzeichnisses:
-----
define("DELIMITER", " ");
function fillin($w, $n)
{
 for($i=1; $i<=$n; $i++)
           {
           echo DELIMITER .chr((ord($w)) +$i);
           }
}

$wordlist=array("Depp", "Xara", "Benno", "Aarset", "Ludwig", "Thodor", "Max");
sort($wordlist);
$oldword="A";

foreach($wordlist as $word)
{
$word=strtoupper(substr($word, 0, 1));
$next=strncasecmp($word, $oldword, 1);
if($next>0) fillin($oldword, --$next);
echo DELIMITER ."<b><u><a href='#$word'>$word</a></u></b>";
$oldword=$word;

}
fillin($oldword, strncasecmp("Z", $word,1));
----
Ist ja soweit auch recht schön, aber wenn nun im Array zwei Wörter mit dem gleichen Buchstaben beginnen, wird mir im Verzeichnis der Buchstabe zweimal angezeigt. Das habe ich versucht wie folgt zu unterdrücken:

-----
foreach($wordlist as $word)
{
$word=strtoupper(substr($word, 0, 1));
$next=strncasecmp($word, $oldword, 1);
if(!isset($verz)||$word!=$verz)
                   {
                   if($next>0) fillin($oldword, --$next);
                   echo DELIMITER ."<b><u><a href='#$word'>$word</a></u></b>";
                   $oldword=$word;
                   $verz=$word;
                   }
}
fillin($oldword, strncasecmp("Z", $word,1));
-----
Funktioniert soweit auch (gibt es da eine elegantere Lösung?)
Aber mir sind noch zwei Sachen aufgefallen und da finde ich noch keinen Lösungsansatz:

  1. Wenn im Array kein Element mit A vorkommt, wird das A nicht ausgegeben! - Sollte es aber, ohne Link. (wenn kein A und kein B fängt das Verzeichnis mit B an, Wenn kein A ebenso)

  2. Wenn ich im Array ein Element habe, das mit einem kleinen Buchstaben beginnt (also zum Beispiel "bernd") wird das ABC-Verzeichnis doppelt ausgegeben und das klein geschriebene Element wird in der zweiten ABC Reihenfolge verlinkt(ist das verständlich ausgedrückt?) Wie muß ich das schreiben, dass auch der kleine Buchstabe als gleichwertig erkannt wird?

Und noch ein Problem: ich möchte das Verzeichnis gerne im Format A - B - C - etc. haben.
wenn ich nun
define("DELIMITER", "&nbsp;-&nbsp;");
definiere habe ich natürlich - A - B - C - etc.
Wie kann ich das unterdrücken, daß der Delimiter schon vor dem ersten Element geschrieben wird.

Last but not least soll das Verzeichnis natürlich noch auf etwas verweisen, das habe ich wie folgt geschrieben:
----
foreach($wordlist as $word)
{
$verzeichnis=strtoupper(substr($word, 0, 1));
if(!isset($buchstabe)||$buchstabe!=$verzeichnis)
   {
   echo "<b><a name='$verzeichnis'>$verzeichnis</a></b><br>";
   $buchstabe=$verzeichnis;
   }
echo "$word<br>";
}
----
Funktioniert auch, aber wollte wissen, ob es da nicht eine bessere Lösung gibt, besonders da ich ja im Prinzip die gleiche Syntax/Abfrage oder wie man das nennt, ja schon weiter oben habe um das Verzeichnis zu erstellen.

Wäre euch dankbar, wenn ihr mir weiterhelfen könntet, auch wenn dieses Posting länger ist als geplant....

Danke,
Frank

  1. Hi,

    1. Wenn im Array kein Element mit A vorkommt, wird das A nicht ausgegeben! - Sollte es aber, ohne Link. (wenn kein A und kein B fängt das Verzeichnis mit B an, Wenn kein A ebenso)

    Dann durchlaufe nicht dein Array in einer Schleife - denn dabei kannst du keine Elemente "bekommen", die es im Array nicht gibt.
    Nutze stattdessen eine for-Schleife, in der du die Buchstaben von A bis Z ausgibst.
    Die kann bspw. so aussehen:
    for($i='A'; $i<='Z'; $i++) { ... }

    In dieser Schleife pruefst du dann jeweils, ob es Array-Elemente zu deinem Buchstaben gibt.

    Wie kann ich das unterdrücken, daß der Delimiter schon vor dem ersten Element geschrieben wird.

    Frage einfach ab, ob du gerade das erste Element ausgibst.
    Das waere vorher schon ganz einfach mit einem "Flag" gegangen, Pseudocode:
    $erstesElement = true;
    schleife(...) {
      if($erstesElement) {
        // tue irgendwas besonderes
      }
      $erstesEkement = false;
      // restlicher Code
    }

    Wenn du obige for-Schleife nutzt, musst du nur noch abfragen, ob $i == 'A' ist.

    MfG ChrisB

    --
    „This is the author's opinion, not necessarily that of Starbucks.“
  2. echo $begrüßung;

    bin gerade dabei PHP zu lernen und habe aus einem Buch "Programmieren lernen in PHP5" folgendes Script zum erstellen eines Verzeichnisses:
    Ist ja soweit auch recht schön,

    Nö.

    define("DELIMITER", "&nbsp;");
    function fillin($w, $n)

    Wenn dir das Buch beigebracht hat, unkommentierten Code mit nicht intuitiven Variablennamen zu schreiben, solltest du dich vielleicht nach einem anderen umsehen. Es ist aufwendig, sich in solchen Code einzuarbeiten, dessen Sinn zu verstehen und dann immer noch nicht zu wissen, ob er gemäß der Intention des Autors arbeitet, wenn diese nicht dabei steht. Beschreibe aber nicht das was da steht sondern was du damit bezweckst, den Sinn dahinter. Du wirst dir später selber danken, wenn du das konsequent machst. Wenn nicht, wirst du dich sicher wie so viele erst später ärgern, dass sie aus ihren Fehlern lernen müssen.

    $word=strtoupper(substr($word, 0, 1));

    Es ist keine gute Idee, eine Variable sinnentstellend wiederzuverwenden. Du hast nun kein Wort mehr in $word stehen, sondern nur noch einen Anfangsbuchstaben von einem.

    Wie kann ich das unterdrücken, daß der Delimiter schon vor dem ersten Element geschrieben wird.

    Du könntest zunächst die einzelnen Buchstaben-Daten jeweils in einem Element eines Arrays abzulegen. Dieses kannst du dann mit implode() zu einem String umwandeln lassen. Der Parameter glue wird dabei nur zwischen die Elemente einfügt.

    Last but not least soll das Verzeichnis natürlich noch auf etwas verweisen, das habe ich wie folgt geschrieben:
    [...]
    Funktioniert auch,

    Es funktioniert immer alles irgendwie. Die Frage ist nur, ob es zu deiner Intention passt. Die müsstest du den Lesern mitteilen, denn deine Gedanken kann k(aum)einer erraten.

    aber wollte wissen, ob es da nicht eine bessere Lösung gibt, besonders da ich ja im Prinzip die gleiche Syntax/Abfrage oder wie man das nennt, ja schon weiter oben habe um das Verzeichnis zu erstellen.

    Zum Programmieren gehört auch das Abstrahieren. Das beinhaltet das Erkennen von Mustern und einen Codeteil so zu schreiben, dass er universell verwendbar ist. Diesen kann man in eine Funktion auslagern. Man kann unterschiedliche Werte als Parameter übergeben und die Funktion errechnet mit der immer gleichen Vorschrift das Ergebnis daraus. Sie sollte dabei idealerweise so gestaltet sein, dass sie nur die ihr übergebenen Parameter kennen muss und sonst nichts aus der Umgebung, in der sie mal später ausgeführt werden soll.

    Wenn du beispielsweise an zwei Stellen Werte berechnest, die nur in der Ausgabe unterschiedlich dargestellt werden sollen, könnte der Teil zur Berechnung in eine Funktion ausgelagert werden, in der nur die reinen Werte ermittelt werden. An der Stelle, an der die Werte dann gebraucht werden, bringt man sie dann in die gewünschte Ausgabeform.

    foreach($wordlist as $word)
    {
    $verzeichnis=strtoupper(substr($word, 0, 1));
    if(!isset($buchstabe)||$buchstabe!=$verzeichnis)
       {
       echo "<b><a name='$verzeichnis'>$verzeichnis</a></b><br>";
       $buchstabe=$verzeichnis;
       }
    echo "$word<br>";
    }

    Es gibt ja so einige Einrückungs- und Klammernsetzungsstile. Der von dir gewählte ist in meinen Augen einer der weniger schönen. 1TBS oder Allman findet man wesentlich häufiger in freier Wildbahn. Wenn du einen mit mehr Konsens nimmst, machst du dir weniger Feinde :-) Wenigstens gehörst du nicht zu denen, die unformatierte Codehaufen fabrizieren. Auch erhöht ein Leerzeichen zwischen Operanden und Operatoren die Lesbarkeit. Man ist das ja aus gewohnt von dem üblichen Methode Leerzeichen zwischen zwei Wörter eines Satzes einzufügen. Das Zend Framework ist sicher noch zu hoch für deine Kenntnisse, aber du kannst dir mal dessen Coding Standard anschauen (besonders Kapitel B.4), um mal zu sehen, wie man Code notieren kann, dass er leicht lesbar ist.

    echo "$verabschiedung $name";

    1. Hallo,

      Auch erhöht ein Leerzeichen zwischen Operanden und Operatoren die Lesbarkeit.

      Autsch. Nein. Nur in verschachtelten Ausdrücken.
      In einfachen Ausdrücken erschweren zusätzlich eingestreute Leerzeichen das Lesen, weil sie trennen, was eigentlich zusammengehört. So erkennt man bei

      $ergebnis = ($x1 + 1) * 4;

      den Zusammenhang auf den ersten Blick weniger gut als bei

      $ergebnis = ($x1+1) * 4;

      Dafür hat es sich als guter Stil erwiesen, vor und nach Schlüsselwörtern der gewählten Programmiersprache ein Leerzeichen zu setzen. So ist

      while ($condition)

      augenfreundlicher als die Schreibweise

      while($condition)

      ohne Leerzeichen. Unüblich ist dagegen das Setzen von Leerzeichen nach der öffnenden bzw. vor der schließenden Klammer.

      Man ist das ja aus gewohnt von dem üblichen Methode Leerzeichen zwischen zwei Wörter eines Satzes einzufügen.

      Wörter, ja. Nicht Satzzeichen.

      So long,
       Martin

      --
      Man gewöhnt sich an allem, sogar am Dativ.
      1. Hallo,

        Auch erhöht ein Leerzeichen zwischen Operanden und Operatoren die Lesbarkeit.

        genau mein Empfinden!

        Autsch. Nein. Nur in verschachtelten Ausdrücken.

        Nein.

        In einfachen Ausdrücken erschweren zusätzlich eingestreute Leerzeichen das Lesen, weil sie trennen, was eigentlich zusammengehört. So erkennt man bei

        $ergebnis = ($x1 + 1) * 4;

        (erkenne ich) aufgrund der Leerzeichen den Zusammenhang viel besser als bei

        $ergebnis = ($x1+1) * 4;

        dieser fast nicht lesbaren Codezeile :-)

        Freundliche Grüße

        Vinzenz

      2. echo $begrüßung;

        Auch erhöht ein Leerzeichen zwischen Operanden und Operatoren die Lesbarkeit.
        Autsch. Nein. Nur in verschachtelten Ausdrücken.
        In einfachen Ausdrücken erschweren zusätzlich eingestreute Leerzeichen das Lesen, weil sie trennen, was eigentlich zusammengehört. So erkennt man bei

        $ergebnis = ($x1 + 1) * 4;

        den Zusammenhang auf den ersten Blick weniger gut als bei

        $ergebnis = ($x1+1) * 4;

        Auf den ersten Blick sehe ich die Klammern, die den Zusammenhang hervorheben. Dann muss ich meinen Parser erstmal fokussieren, um bei $x1+1 genau auszuwerten zu können, was Operator, was Operand und was vielleicht Teil eines Operanden ist, wenn noch Punkte als Dezimaltrenner hinzukommen.

        Man ist das ja aus gewohnt von dem üblichen Methode Leerzeichen zwischen zwei Wörter eines Satzes einzufügen.
        Wörter, ja. Nicht Satzzeichen.

        Ein Operator ist auch nur eine Art Wort. Ein Satzzeichen wäre unter PHP das ; sowie das , als Parametertrenner.

        echo "$verabschiedung $name";

        1. Hi,

          $ergebnis = ($x1+1) * 4;
          Auf den ersten Blick sehe ich die Klammern, die den Zusammenhang hervorheben. Dann muss ich meinen Parser erstmal fokussieren, um bei $x1+1 genau auszuwerten zu können, was Operator, was Operand und was vielleicht Teil eines Operanden ist, wenn noch Punkte als Dezimaltrenner hinzukommen.

          dann haben wir wohl deutlich unterschiedliche Wahrnehmungsstrukturen beim Lesen (gilt wohl auch für Vinzenz). Für mich ist ein Leerzeichen beim Lesen von Programmcode in erster Linie eine Zäsur, die etwas trennt. Das hilft mir zwar bei komplexen Ausdrücken, um die einzelnen Terme und Teilausdrücke zu gruppieren - aber wenn etwas zusammengehört, schreibe ich es auch zusammen, weil das für mich leichter zu erfassen ist.
          Ich setze Leerzeichen da, wo auch vom Lesen und Verstehen her ein Schnitt ist.

          Wörter, ja. Nicht Satzzeichen.
          Ein Operator ist auch nur eine Art Wort. Ein Satzzeichen wäre unter PHP das ; sowie das , als Parametertrenner.

          Ich würde jeden Operator, der nicht mit Buchstaben geschrieben wird, als Satzzeichen in diesem Sinn betrachten. Operatoren wie "and", "as" oder "not" würde ich in diesem Sinn als Wörter sehen, Operator-Symbole wie '+', '->' oder '[]' als Satzzeichen.
          Wobei ich zugeben muss, dass ich bei den logischen Operatoren selbst von dieser Maxime abweiche und rechts und links davon ein Leerzeichen setze ...

          Schönen Abend noch,
           Martin

          --
          F: Was ist eigentlich aus deinem schlimmen Durchfall geworden?
          A: Mein Arzt hat mir Valium verschrieben.
          F: Und das hilft?
          A: Naja, ich mach mir immer noch in die Hose. Aber inzwischen ist es mir egal.