xNeTworKx: Ich versteh die Logik hierbei nicht

Hello,
kleines Problem:
Ich frage das Verzeichnis nach der Datei datenbank.txt ab, falls diese nicht gefunden wird, wird das Array @daten logischerweise nicht mit Daten gefüllt und ist somit leer.
So die Datei datenbank.txt existiert jetzt zur Probe nicht, und ich will mir zur Probe den Text "Leer" ausgeben lassen, falls @daten leer ist, aber das tut er nicht. Wenn ich jetzt auf if (@daten ne '') gehe, gibt er mit "Leer" aus. Kann mir jemand sagen warum ?

#!C:\Perl\bin\Perl.exe -w

use CGI;
$query = new CGI;
@daten = '';
$verzeichnis = ".";

print $query->header;

opendir(DIR, "$verzeichnis") or die "Verzeichnis kann nicht geoeffnet werden : $!\n";
  while ($file = readdir(DIR))  {
    if ($file =~ /datenbank.txt/)  {
    open(FILE,"datenbank.txt") or die "Kann Datenbank nicht oeffnen : $!\n";
    @daten = <FILE>;
    }
  }
  if (@daten eq '')  {
  print 'Leer!';
  }

  1. hi!

    if (@daten eq '')  {

    Array ^^^^^^    ^^ String

    Was glaubst du, was passiert, wenn du ein Array mit einem String
    vergleichst?

    bye, Frank!

    1. Hallo, danke für eure Hilfe,

      Ich habs jetzt folgendermaßen gemacht:

      #!C:/Perl/bin/Perl.exe -w

      use CGI;
      $query = new CGI;
      $verzeichnis = ".";

      print $query->header;

      opendir(DIR, "$verzeichnis") or die "Verzeichnis kann nicht geoeffnet werden : $!\n";
        while ($file = readdir(DIR))  {
          if ($file =~ /^datenbank.txt$/)  {
          open(FILE,"$verzeichnis/datenbank.txt") or die "Kann Datenbank nicht oeffnen : $!\n";
          @daten = <FILE>;
          }
        }
      $ae = @daten;
      if ($ae == 0)  {
      print "Leer!\n";
      }

      So gehts zwar, aber ich versteh das mit @daten eq '' oder "" noch nicht ganz.
      Wie kann ich eigentlich "Falls Array leer ist" sagen? if (@array ???

      1. So gehts zwar, aber ich versteh das mit @daten eq '' oder "" noch nicht ganz.
        Wie kann ich eigentlich "Falls Array leer ist" sagen? if (@array ???

        if (scalar(@array)==0) oder if ((@array+0))==0).
        HTH
        Erik

        1. Ok verstanden, danke =)

        2. Hi!

          if (scalar(@array)==0) oder if ((@array+0))==0).

          Oder einfach
            if (@array == 0)
          Da die Vergleichsoperatoren sowieso nur auf Skalaren arbeiten, bringt == das @array schon in skalaren Kontext, daher ist das 'scalar' redundant.

          So long

          1. Hallo Calocybe,

            if (scalar(@array)==0) oder if ((@array+0))==0).

            Oder einfach
              if (@array == 0)
            Da die Vergleichsoperatoren sowieso nur auf Skalaren arbeiten, bringt == das @array schon in skalaren Kontext, daher ist das 'scalar' redundant.

            Noch viel einfacher und voll funktional wäre:

            if(@array) {...} oder if (!@array) {...}

            Ein Array ist nämlich afaik wahr, sobald es wenigstens ein Elment enthält.

            Gruß Alex
            --
            http://www.google.de/search?hl=de&safe=off&q=Rechtschreibung+Standart

      2. Hallo,

        Ich habs jetzt folgendermaßen gemacht:

        [...]

        So gehts zwar,

        Hier nochmals mein Vorschlag:

        <code>
        #!C:/Perl/bin/Perl.exe -w

        use strict;
        use CGI;
        my $query = new CGI;
        my $verzeichnis = '.'; # wobei noch anzmerken ist, das das aktuelle Verzeichnis nicht wirklich definiert ist
        my  @daten;
        print $query->header;

        if(-e "$verzeichnis/datenbank.txt")
          {
          open(FILE,"$verzeichnis/datenbank.txt") or die "Kann Datenbank nicht oeffnen : $!\n";
          @daten = <FILE>;
          close FILE or die "Kann Datenbank nicht schliessen : $!\n";
          }

        if( scalar @daten == 0)
         {
         print 'Datei nicht gefunden oder es steht nix drin';
         }
        </code>

        aber ich versteh das mit @daten eq '' oder "" noch nicht ganz.

        Weil Du hier ein Array (anscheinend die Anzahl der Arrayelemente) mit einem Text vergleichst. Und da ist die Wahrscheinlichkeit ziemlich groß, daß nicht das gewünschte Ergebnis erzielt wird.

        Wie kann ich eigentlich "Falls Array leer ist" sagen? if (@array ??

        ( scalar @daten == 0)
        oder (inzwischen etwas verpönt)
        ($#daten == -1)

        Grüße
          Klaus

        1. Hi, ok ich hab jetzt dein Script genommen

          Das versteh ich aber noch nicht so ganz

          my $verzeichnis = '.'; # wobei noch anzmerken ist, das das aktuelle Verzeichnis nicht wirklich definiert ist

          wieso eigentlich nicht ?

          und zu use strict : Ich hab jetzt mal das use strict beibehalten, aber ich habs nie verwendet weil ich nie weis wann man my setzen muss, immer nur am Anfang ? Ich bild mir ein ich hab mal wo gesehen, daß mitten im Script auch ein my vorgekommen is, oder nicht ?

          1. Hallo,

            my $verzeichnis = '.'; # wobei noch anzmerken ist, das das aktuelle Verzeichnis nicht wirklich definiert ist
            wieso eigentlich nicht ?

            Weil im Webumfeld es nicht sicher ist, daß das aktuelle Verzeichnis beim Scriptaufruf auch dort ist, wo Du es erwartest.

            und zu use strict : Ich hab jetzt mal das use strict beibehalten, aber ich habs nie verwendet weil ich nie weis wann man my setzen muss, immer nur am Anfang ? Ich bild mir ein ich hab mal wo gesehen, daß mitten im Script auch ein my vorgekommen is, oder nicht ?

            Kurze Antwort:

            Du kannst my verwenden, wann Du willst, nicht nur am Anfang. In jedem Fall mußt Du, es in Verbindung mit 'use script', vor, oder spätestens bei, der ersten Verwendung der Variable benutzen.

            Längere Antwort:

            my bestimmt eigentlich den Gültigkeitsbereich einer Variable. Wenn Du eine Variable mittels my innerhalb eines Blocks deklarierst, dann ist diese Variable auch nur innerhalb dieses Blocks 'vorhanden', also gültig).
            eigentlich kannst Du jederzeit eine neue Variable mit my einführen, sie gilt eben bis zum Ende des Blocks.
            Wird eine Variable nicht innerhalb eines Blocks definiert, dann gilt sie ab dem Zeitpunkt der Definition innerhalb der restlichen Scriptdatei, aber nur innerhalb dieser Scriptdatei. Das ist vor allem bei der Modulentwicklung wichtig.
            Einen Block erkennst Du an den geschwungenen Klammern, welche Anweisungen einfassen, nicht zu verwechseln mit den Klammern, die Du bei Hashes verwendest.

            Beispiel:

            #!/usr/bin/perl -w
            use strict;

            ab sofort müssen Variablen deklariert sein

            zu diesem Zeitpunkt gibt es eigentlich nur die, die 'vordefiniert' sind

            also b.B. $_, $!, $|, %ENV usw.

            Du kannst einfach Variablen definiert:

            my $zeile;

            hier könnten beliebige Anweisunge stehen, welche auf $zeile zugreifen können

            aber nicht auf $dateiname, da sonst einf Fehler produziert werden würde

            Du kannst auch Variablen gleich mit Werten vorbelegen:

            my $dateiname = '/wo/auch/immer/wasauchimmer.txt';

            open(IN,$dateiname);

            hier gibts noch kein @werte

            while($zeile = <IN>)
              { # hier beginnt ein Block
              chomp $zeile; # auch innerhalb dieses Blocks ist $zeile das gleiche wie außerhalb

            my(@werte) = split(';',$zeile); #  ab hier ist @werte deklariert, und gilt bis zum Ende des Blocks
              # weitere Anweisungen
              } # hier endet der Block

            hier gibts @werte wieder nicht, wohl aber noch $zeile, $dateiname

            Hilfreich ist my unter anderem auch, weil Du in einem Block Variablen verwenden kannst, unabhängig davon, ob sie außerhalb schon verwendet werden oder nicht.

            Beispiel:

            my $zeile = 'wasauchimmer';

            print $zeile; # gibt 'wasauchimmer' aus, da $zeile so belegt wurde

            if(-e $dateiname)
              {
              open(IN,$dateiname);
              my $zeile; # hier wird $zeile für den Block neu definiert
              print $zeile; # gibt einen leeren String aus, da $zeile in diesem Block noch leer ist

            while($zeile = <IN>)
                {
                print $zeile; # gibt den inhalt der Datei zeilenweise aus
                }
              }

            print $zeile;

            gibt wieder 'wasauchimmer' aus, unabhängig davon,

            was in der Datei stand

            Das ist vor allem beim Schreiben von Funktionen ein äußerst hilfreiches Verhalten.

            Du siehst, my ist nicht nur zur Vermeidung von Fehlermeldungen bei 'use strict' interessant, sondern auch für viele andere interessante Anwendungsfälle.

            Seit Perl 5.6 gibt es auch 'our', wodurch es auch möglich wurde, wirklich globale Variablen zu deklarieren. Bei frühere Versionen von Perl mußte man sich entscheiden, ob man 'use strict', oder globale Variablen verwenden wollte.
            In den meisten Fällen sind globale Variablen zwar unsauber, aber ab und zu kann man damit eine Sache dann doch eleganter lösen, unabhängig davon, was Puristen davon halten.

            Es gibt da noch eine Funktionalität, deren Verhalten zwar 'my' nicht unähnlich ist, aber intern vollkommen anders arbeitet. Ich rede hier von 'local'.  Aber Du solltest Dich nicht mehr damit abgeben, da es IMHO noch ein Relikt aus vergangenen Tagen ist. Ich wollte es nur der Vollständigkeit halber erwähnt haben.

            Jetzt hoffe ich, daß ich etwas Licht in die Sache gebracht habe, ohne vollständig zu verwirren.

            Grüße
              Klaus

            1. Hi,
              danke für die Info, ich glaub jetzt kapier ichs =)

  2. Hallo,

    #!C:\Perl\bin\Perl.exe -w

    use CGI;

    Und ich dachte, 'use strict' hat sich inzwischen rumgesprochen;-)

    $query = new CGI;

    @daten = '';

    Dir ist hoffentlich klar, daß Du damit kein leeres Array erzeugts, sondern eines in dem im ersten Arrayelement ein leerer String steht.

    $verzeichnis = ".";

    print $query->header;

    opendir(DIR, "$verzeichnis") or die "Verzeichnis kann nicht geoeffnet werden : $!\n";
      while ($file = readdir(DIR))  {
        if ($file =~ /datenbank.txt/)  {
        open(FILE,"datenbank.txt") or die "Kann Datenbank nicht oeffnen : $!\n";
        @daten = <FILE>;
        }
      }

    Hier drei Anmerkungen von mir:
    1.) Du kannst die Existenz einer Datei auch mit
    if(-e $datei)
      {
      # mach was mit der Datei
      }
    else
      {
      # hmm, nix gefunden
      }
    überprüfen. Abgesehen davon, daß es einfach zu schreiben ist, ist es auch wesentlich performanter.

    2.) wenn Du schon $verzeichnis durchsuchst, solltest Du dann auch
    open(FILE,"$verzeichnis/$file") or die "blablabla";
    für den gewünschten File machen.

    Das macht zwar im aktuellen Zustand Deines Scripts keinen Unterschied, aber irgendwann änderst Du vielleicht die Zeile
    $verzeichnis = '.';
    auf
    $verzeichnis = '/and/now/to/something/complete/different';

    und suchst dann bis zur Verzweiflung, warums das Script plötzlich nicht mehr funktioniert.

    3.)

    if ($file =~ /datenbank.txt/)  {
        open(FILE,"datenbank.txt") or die "Kann Datenbank nicht oeffnen : $!\n";

    Ist eigentlich auch 'suboptimal', da das Matching auch auf Dateinamen wie 'kopie von datenbank.txt', 'datenbank2txt'  oder 'was auch immer fuer eine datenbank,txt sollte auf jeden fall dabei sein' anspringt.
    wenn dann
    if ($file =~ /^datenbank.txt$/)  {

    if (@daten eq '')  {
      print 'Leer!';
      }

    Hmm, was da genau passiert, ist mir auch schleierhaft. Wird @daten in einen String gejoint (anscheinend nicht) oder implizit ein 'scalar @daten' ausgeführt, oder irgendwas anderes. Weiß auch nicht. Unsicher ist das allemal.
    Hier zwei mögliche Lösungen
    unless(-e "$verzeichnis/datenbank.txt")
     {
     print 'Leer!';
     }
    else
     {
     # einlesen und verarbeiten der Daten
     }

    (Das unless deshalb, um elegant den codemäßig kürzeren Teil eventuell nach vorne zu bringen, was die Lesbarkeit des Scripts erhöht.)

    oder
    my @daten;

    hier der Code, der die Daten eventuell aus der Datei einliest

    if(scalar @daten ==0)
     {
     print 'Leer!';
     }

    Grüße
      Klaus