Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - StringList findet gesuchten Wert nicht


skall - Mo 26.01.09 13:25
Titel: StringList findet gesuchten Wert nicht
und nocheinmal tag :)

da ich wohl einfach zu wenig davon verstehe brauch ich mal wieder eure Hilfe :S


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
procedure DatenEinlesen (DatumWert:String; MittelWert:TStundenMittel; MaxWert:TDatenSatz);
  var buffer : String;
      Volt, NullWert, Minute, Stunden, i, h, m, e, VoltWert : Integer;
      TextDatei : TextFile;
      Liste : TStringList;
Begin
  AssignFile(TextDatei, DatumWert + '.dat');
  FileMode := fmOpenRead;
  Reset(TextDatei);
  h := 0;
    while not Eof(TextDatei) do
      Begin
       ReadLn(TextDatei, buffer);
         Begin
           Read(TextDatei, Volt);
           Read(TextDatei, NullWert);
           Read(TextDatei, Stunden);
           Read(TextDatei, Minute);
           Liste := TStringList.Create;
           Liste.LoadFromFile(DatumWert + '.dat');
         For i := 0 to 12 do
            begin
              h := e + 6;
             If Liste[i][3] = IntToStr(h) then
                begin
                VoltWert := VoltWert + StrToInt(Liste[i][1]);
                ShowMessage(IntToStr(VoltWert));
                end;
            end;
            Liste.Free;
         End;
      End;
  Closefile(TextDatei);
End;


Ihr habt mir dabei ja shcon viel geholfen, aber die Stringlist ist auhc neu für mich... Finde dazu nichts passendes im Internet...

Mein Problem:
Die If-Klausel findet den Wert h nicht... Somit führt er leide rja auch nicht den Then block aus...
Die Werte an der dritten Stelle der Stingsätze, die ich suche ist 7 welcher eigentlich soweit wie ich da durch blicke erkannt werden müsste...

Meine Frage:
Kann mir jemand dabei die Stringlist einwenig erklären und dann mir den Fehler beschreiben? Ausserdem würde ich gerne wissen wie Die Stringlist überhaupt arbeitet? Ist das zu behandeln wie ein zweidimensionales Array?


Blackheart666 - Mo 26.01.09 14:06

Schau mal dort.
http://www.delphitutorials.de/listen-in-delphi.html


jaenicke - Mo 26.01.09 17:00
Titel: Re: StringList findet gesuchten Wert nicht
user profile iconskall hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure DatenEinlesen (DatumWert:String; MittelWert:TStundenMittel; MaxWert:TDatenSatz);
  var buffer : String;
      Volt, NullWert, Minute, Stunden, i, h, m, e, VoltWert : Integer;
      TextDatei : TextFile;
      Liste : TStringList;
Begin
  AssignFile(TextDatei, DatumWert + '.dat');
  FileMode := fmOpenRead;
  Reset(TextDatei);
  h := 0;
    while not Eof(TextDatei) do
      Begin
       ReadLn(TextDatei, buffer);
         Begin
           Read(TextDatei, Volt);
           Read(TextDatei, NullWert);
           Read(TextDatei, Stunden);
           Read(TextDatei, Minute);
           Liste := TStringList.Create;
           Liste.LoadFromFile(DatumWert + '.dat');
         For i := 0 to 12 do
            begin
              h := e + 6;
An der Stelle ist e gar nicht initialisiert, es sollte auch eine entsprechende Warnung vom Compiler kommen...

user profile iconskall hat folgendes geschrieben Zum zitierten Posting springen:
Mein Problem:
Die If-Klausel findet den Wert h nicht... Somit führt er leide rja auch nicht den Then block aus...
Die Werte an der dritten Stelle der Stingsätze, die ich suche ist 7 welcher eigentlich soweit wie ich da durch blicke erkannt werden müsste...
Du schaust nach dem Wert von h, und der ist e + 6, wobei e gar nicht definiert ist.

user profile iconskall hat folgendes geschrieben Zum zitierten Posting springen:
Ausserdem würde ich gerne wissen wie Die Stringlist überhaupt arbeitet? Ist das zu behandeln wie ein zweidimensionales Array?
Jein, du hast eine Liste von Strings.
Liste[0], Liste[1] usw. sind die einzelnen Zeilen.
Wenn du einen String wie z.B. buffer hast, dann kannst du auf die einzelnen Zeichen wie auf ein Array zugreifen. buffer[1], buffer[2], ... sind die einzelnen Zeichen.

Jetzt kombiniere das. Liste[0] ist der erste String. Und jetzt willst du in diesem String auf das dritte Zeichen zugreifen. (Liste[0])[3] oder kurz Liste[0][3]. Das sieht dann aus wie ein zweidimensionales Array, wobei im äußeren Array die Strings und im inneren die Buchstaben der Strings stehen. Wenn du das so gemeint hast, dann: Ja.


MSCH - Mo 26.01.09 21:03

ich will ja nicht meckern, aber ich bekomme grad einen grauen star ;-)
Keinerlei Fehlerprüfung oder/und Try/Finally/Exceptions.
Ich will ja nicht als Oberlehrer auftreten, aber ist das nicht auch ein Thema?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
procedure DatenEinlesen (DatumWert:String; MittelWert:TStundenMittel; MaxWert:TDatenSatz);  
// MittelWert und  MaxWert wozu werden diese übergeben?
var buffer : String;      
Volt, NullWert, Minute, Stunden, i, h, m, e, VoltWert : Integer;  //<-- wozu m ?    
TextDatei : TextFile;      
Liste : TStringList;
Begin  
  AssignFile(TextDatei, DatumWert + '.dat');  
  FileMode := fmOpenRead;  //<-- exklusiver Zugriff oder + or fmShare....
  Reset(TextDatei);  // <-- was passiert wenn datei nicht vorhanden -> ioResult<>0
  h := 0;    
  while not Eof(TextDatei) do      
  Begin       
    ReadLn(TextDatei, buffer);// <-- was passiert wenn Datei leer ist ? length(Buffer)=0
    Begin           // <-- wech, keinen sinn
      Read(TextDatei, Volt); // <-- was passiert bei Typ-Fehler, statt Int steht hier ein String?           
      Read(TextDatei, NullWert);  // <-- dito 
      Read(TextDatei, Stunden);   // <-- dito
      Read(TextDatei, Minute);    // <-- dito
      Liste := TStringList.Create;           
      Liste.LoadFromFile(DatumWert + '.dat'); // <-- Autsch, was passiert wenn die Datei nicht existiert         
      For i := 0 to 12 do // <-- wo steht, dass es 12 sind ? Access-Violation wäre die Folge wenn i=12 aber nur 11 existieren
      begin              
        h := e + 6;             
        If Liste[i][3] = IntToStr(h) then                
        begin                
          VoltWert := VoltWert + StrToInt(Liste[i][1]);  //<-- Type Convertierung ohne Prüfung, StrToIntDef verwenden              
          ShowMessage(IntToStr(VoltWert));   // <-- Dito             
        end;            
      end;//<-- wech, keinen Sinn, siehe oben            
      Liste.Free; // <-- was passiert, wenn Liste nicht erzeugt werden konnte?
    End;      
  End;  
  Closefile(TextDatei); // <-- was passiert wenn Datei nicht geöffnet wurde ?
End;// <-- was passiert bei einer Exception.


:-) Msch


skall - Di 27.01.09 10:31

ähhh xD

allet kla... Ding war nur erstens war ja ncoh nicht fertig :D obwohl ich darauf sicher nicht selber gekommen wäre :) und zweitens schon unter Zeitdruck...

Aber danke für den Tipp... Werde mir das unter dem Aspekt nochmal angucken :D


skall - Di 27.01.09 17:30

Kannst du mir vllt n Tipp geben wie ich das mache, dass er mir Bescheid sagt, wenn die Datei nciht vorhanden sit? :o


jaenicke - Di 27.01.09 18:19

Zunächst mal solltest du keine relativen Pfade verwenden, das ist eher Zufall, das das funktioniert.
http://www.delphi-library.de/viewtopic.php?p=499701

Und um festzustellen ob die Datei existiert:
Du willst doch auf englisch übersetzt sagen "if file xy exists then do something". Naja, der Parameter xy muss natürlich hinter den Befehl, ansonsten war es das schon...

Delphi-Quelltext
1:
2:
if FileExists(xy) then
  DoSomething;


MSCH - Mi 28.01.09 16:28

Die erste Frage, die ich mir stellen würde, warum verwendest du eine nicht-typisierte Datei? Du musst dadurch das du eine Textdatei verwendest, eine Menge Fehlermöglichkeiten abfangen - was das ganze nur verkompliziert.
aber ok.

es reicht nicht zu prüfen, ob die Datei vorhanden ist, sondern auch ob man sie lesen sprich öffnen kann. Windows ab 2000 hat da nämlich eine ganze Menge Steine, die man in den Weg legen könnte - stichwort ACL.
also


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if FileExists(Dateiname) then begin
  Reset(Filehandle);
  if IoResult=0 then begin
    // do something
  end;
  FileClose(Filehandle);
end;


weiter; verwende - um kompatible zu sein, nicht den Typ "String". Der mag zwar ok sein, aber ab D2009 könnte das ein Unicode-String sein. Also expliziert AnsiString oder ShortString.
Wenn du Klassen instanziiert, immer in einem Try/Finally Block.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
MyStringList:= TStringList.Create;
try
  // do something
finally
  MyStringlist.Free;
end;


Bei der Konvertierungen von Strings in Zahlen empfehle ich dir die Funktion StrToIntDef(). Bei einer ungültigen
Übergabe wird der Default-Wert (ein Teil der Parameter der Funktion) zurückgegeben.

Beim Lesen einer Datei:

Delphi-Quelltext
1:
2:
3:
4:
while not Eof(TextDatei) do Begin           
  ReadLn(TextDatei, buffer);
  Read(TextDatei, Volt); 
  ...


prüfst du zwar ob nicht EOF(Filehandle) aber du liest mehrfach aus der Datei. Was passiert, wenn das Dateiende
bereits nach dem ersten Readln() erreicht ist?

Eine einfache - nicht die beste - Lösung könnte sein:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
While not eof(Filehandle) do begin
  Readln(Filehandle,ShortStringVariable);
  if not EOF(FileHandle) then
    Read(FileHandle,Variable);
  // and any other 
end;


Cheers
Msch