Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Abstracter Fehler bei Parsefunktion (https://www.delphipraxis.net/151658-abstracter-fehler-bei-parsefunktion.html)

Jens Hartmann 27. Mai 2010 08:48


Abstracter Fehler bei Parsefunktion
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,

ich habe ein Problem, das in meinem Programm seid neustem ein Abstracter Fehler beim Parsen von String Zeilen auftritt. Leider kann ich mit der unten angehangen Fehlermeldung recht wenig anfangen. Kann mir da eventuell jemand was genauers zu sagen?

Hier zeige ich mal kurz den Code bei dem der Fehler auftritt...
Delphi-Quellcode:
  ...
  ParserTreeViewMB100.ParseMB100(DataMB100); /Fehlerzeile wenn Daten kommen
  ...

  //Klasse zum Parsen

  TMyBaseParser = class
  private
    Data: String;
    DataPointer: Integer;
    function OemToAnsi(const OemStr: string): string;
    procedure SkipSpaces;
    procedure SkipTrash;
    function GetTextLength(UpToLineEnd: Boolean): Integer;
    function ReadLine: String;
  public
    EntriesMB256: array of TMyDataEntryMB256;
    EntriesMB100: array of TMyDataEntryMB100;
    EntriesUEZ : array of TMyDataEntryUEZ;
    EntriesIQ8 : array of TMyDataEntryIQ8;
    procedure ParseMB256(Text: String); virtual; abstract;
    procedure ParseMB100(Text: String); virtual; abstract;
    procedure ParseUEZ(Text: String); virtual; abstract;
    procedure ParseIQ8(Text: String); virtual; abstract;
  end;

  //Der Teil der Klasse wo es eigendlich passieren muss

  TMyParserMB100 = class(TMyBaseParser)
  private
  public
    procedure ParseMB100(Text: String); override;
  end;

  //Die Procedure ParseMB100

procedure TMyParserMB100.ParseMB100(Text: String);
var
  CurEntry : ^TMyDataEntryMB100;
  TempDatum : String;
  TempUhr  : string;
  Temp1     : String;
  Temp2     : String;
  Temp3     : String;
  Temp4     : string;
  Temp5     : String;
  Temp6     : String;
  Temp1Int : Integer;
  iPos     : Integer;
  iPosString: Integer;
  DatenMB100: TStringList;
  iSL : integer;
begin
try
  try

  SetLength(EntriesMB100, Length(EntriesMB100) + 1);
  CurEntry := @EntriesMB100[High(EntriesMB100)];

  DatenMB100 := TStringList.Create;
  while Pos(#$D#$A, Text) > 0 do
    begin
      iPos := Pos(#$D#$A, Text);
      Data := Copy(Text,1,iPos-1);
      DatenMB100.Add(Data);
      Delete(Text,1,iPos+1);
    end;

  for iSL := 0 to DatenMB100.Count -1 do
    Form1.DatenMemo.Lines.Add(DatenMB100[iSL]);

  Form1.DatenMemo.Lines.Add('');

  Temp1 := DatenMB100[0];
  Temp1 := Copy(Temp1, 11, 4);
  TryStrToInt(Temp1,Temp1Int);

  Temp2 := DatenMB100[1];
  Temp2 := Copy(Temp2, 1, 22);

  TempUhr := DatenMB100[1];
  TempDatum := DatenMB100[1];

  TempUhr := Copy(TempUhr, Length(TempUhr)-7, 8);
  TempDatum := Copy(TempDatum, Length(TempDatum)-17,9);

         if Pos('JAN', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('01.20', TempDatum , 4);
          end;

        if Pos('FEB', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('02.20', TempDatum , 4);
          end;

        if Pos('MRZ', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('03.20', TempDatum , 4);
          end;

        if Pos('APR', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('04.20', TempDatum , 4);
          end;

        if Pos('MAI', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('05.20', TempDatum , 4);
          end;

        if Pos('JUN', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('06.20', TempDatum , 4);
          end;

        if Pos('JUL', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('07.20', TempDatum , 4);
          end;

        if Pos('AUG', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('08.20', TempDatum , 4);
          end;

        if Pos('SEP', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('09.20', TempDatum , 4);
          end;

        if Pos('OKT', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('10.20', TempDatum , 4);
          end;

        if Pos('NOV', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('11.20', TempDatum , 4);
          end;

        if Pos('DEZ', TempDatum)= 4 then
          begin
            Delete(TempDatum, 4, 4);
            Insert('12.20', TempDatum , 4);
          end;

case DatenMB100.Count of
2: begin
      CurEntry.LfdNr := Temp1Int;
      CurEntry.Datum := TempDatum;
      CurEntry.Uhrzeit := TempUhr;
      CurEntry.Ereignis := Trim(Temp2);
    end;
3: begin
      CurEntry.LfdNr := Temp1Int;
      CurEntry.Datum := TempDatum;
      CurEntry.Uhrzeit := TempUhr;
      CurEntry.Ereignis := Trim(Temp2);
      if pos('Einbruch HA',Temp2) or pos('Überfall HA', Temp2)
        or pos('Bereich', Temp2) or pos('Sabo', Temp2) > 0 then
        CurEntry.Bereich := Trim(DatenMB100[2])
      else
        CurEntry.Teilnehmer := Trim(DatenMB100[2]);
    end;
4: begin
      CurEntry.LfdNr := Temp1Int;
      CurEntry.Datum := TempDatum;
      CurEntry.Uhrzeit := TempUhr;
      CurEntry.Ereignis := Trim(Temp2);
      CurEntry.Bereich := Trim(DatenMB100[2]);
      CurEntry.Teilnehmer := Trim(DatenMB100[3]);
    end;
5: begin
      CurEntry.LfdNr := Temp1Int;
      CurEntry.Datum := TempDatum;
      CurEntry.Uhrzeit := TempUhr;
      CurEntry.Ereignis := Trim(Temp2);
      CurEntry.Bereich := Trim(DatenMB100[2]);
      CurEntry.Teilnehmer := Trim(DatenMB100[3]+' '+DatenMB100[4]);
    end;
6: begin
      CurEntry.LfdNr := Temp1Int;
      CurEntry.Datum := TempDatum;
      CurEntry.Uhrzeit := TempUhr;
      CurEntry.Ereignis := Trim(DatenMB100[3]+' '+Temp2);
      CurEntry.Bereich := Trim(DatenMB100[2]);
      CurEntry.Teilnehmer := Trim(DatenMB100[4]+' '+DatenMB100[5]);
    end;
  end;
  except
    Form1.ServiceMemo.Lines.Add('Fehler beim Parsen von Eingangsstring aufgetreten');
  end;
finally
  DatenMB100.Free;
end;
end;
Ich weiß, das der Code wahrscheinlich nicht viel hergibt. Allerdings, hoffe ich das mir trotzallem jemand helfen kann.

Danke schon mal und Gruß Jens

mkinzler 27. Mai 2010 08:54

Re: Abstracter Fehler bei Parsefunktion
 
Stimmt den der Typ der Klasse?
Btw. Wenn es mehrere Subklassen gibt, welche verschiedene Parser bieten, würde ich nur eine abstrakte Parsermethode in der Basisklasse deklarieren, welche dann entsprechend von den abgeleiteten Klassen implemnetiert wird.

DeddyH 27. Mai 2010 08:56

Re: Abstracter Fehler bei Parsefunktion
 
Wenn Du in der Basisklasse abstrakte Methoden deklarierst, musst Du diese in den Ableitungen auch überschreiben.
Blödsinn, hast Du ja (bin wohl noch nicht ganz wach) :oops:

Jens Hartmann 27. Mai 2010 09:08

Re: Abstracter Fehler bei Parsefunktion
 
Das seltsame ist, das ich daran eigendlich gar nichts geändert habe, und der Fehler jetzt aufeinmal da ist. Sicher ich weiß, das kann nicht sein. Aber irgendwie ist es schon seltsam...

Gruß Jens

himitsu 27. Mai 2010 09:08

Re: Abstracter Fehler bei Parsefunktion
 
Beim Debuggen bekommst'e nicht das Wo und Warum raus?

Notfalls einfach mal in TMyBaseParser alle Methoden implementieren (abstrakt entfernen)
und stattdessen testweise eine Dummy-Methode mit Fehlermeldung verbauen.

Delphi-Quellcode:
procedure TMyBaseParser.ParseMB256(Text: String);
begin
  raise EAbstractError.Create('Fehler: "ParseMB256" wurde aufgerufen');
end;

procedure TMyBaseParser.ParseMB100(Text: String);
begin
  ...
Aber eigentlich sollte der Compiler ja eine Meldung ausgeben, wenn man eine Klasse mit abstrakten Methoden instanziieren will. :gruebel:

EAbstractError, bzw. SysUtils.AbstractErrorHandler wird eigentlich "nur" ausgelöst, wenn versucht wird eine abstrakte Methode aufgerufen.

Blup 27. Mai 2010 10:42

Re: Abstracter Fehler bei Parsefunktion
 
Eigentlich kommt als Ursache nur in Betracht, dass nicht die richtige Klasse erzeugt oder die falsche Methode zum Parsen benutzt wird.

Die Klassenstruktur scheint mir so nicht wirklich sinnvoll. Die Klasse sollte entscheiden wie der Text zu verarbeiten ist, nicht derjenige der die Klasse benutzt.
Delphi-Quellcode:
TMyBaseParser = class
  private
    Data: String;
    DataPointer: Integer;
    function OemToAnsi(const OemStr: string): string;
    procedure SkipSpaces;
    procedure SkipTrash;
    function GetTextLength(UpToLineEnd: Boolean): Integer;
    function ReadLine: String;
  public
    procedure Parse(Text: String); virtual; abstract;
  end;

  //Der Teil der Klasse wo es eigendlich passieren muss

  TMyParserMB256 = class(TMyBaseParser)
  private
    EntriesMB256: array of TMyDataEntryMB256;
  public
    procedure Parse(Text: String); override;
  end;

  TMyParserMB100 = class(TMyBaseParser)
  private
    EntriesMB100: array of TMyDataEntryMB100;
  public
    procedure Parse(Text: String); override;
  end;

{usw.}
Damit entfällt die Notwendigkeit Klassen zu verwenden, die noch abstrakte Methoden besitzen.

Jens Hartmann 27. Mai 2010 18:45

Re: Abstracter Fehler bei Parsefunktion
 
Hallo zusammen und besten dank für die Tips.

Ich habe das ganze jetzt nochmal überarbeitet und ganz ohne abstract und overide realisiert. Ich habe die Methoden direkt in TMyBAseParser integriert und jetzt funktioniert es.

Kann mir trotzallem mal jemand das mit den abstracten etc erklären. Fehler ist zwar weg, aber ob es so wie ich es jetzt habe besser ist und wo der Fehler eventuell her gekommen ist, ist mir nicht so ganz klar.

Hier mal meine jetzige Klasse...
Delphi-Quellcode:
  TMyBaseParser = class
  private
    Data: String;
    DataPointer: Integer;
    procedure SkipTrash;
    function GetTextLength(UpToLineEnd: Boolean): Integer;
    function ReadLine: String;
  public
    EntriesMB256: array of TMyDataEntryMB256;
    EntriesMB100: array of TMyDataEntryMB100;
    EntriesUEZ : array of TMyDataEntryUEZ;
    EntriesIQ8 : array of TMyDataEntryIQ8;
    procedure ParseMB256(Text: String);
    procedure ParseMB100(Text: String);
    procedure ParseUEZ(Text: String);
    procedure ParseIQ8(Text: String);
  end;
Danke nochmal und Gruß

Jens

DeddyH 27. Mai 2010 18:48

Re: Abstracter Fehler bei Parsefunktion
 
Die Problematik hatten wir gestern erst hier.

Jens Hartmann 27. Mai 2010 20:58

Re: Abstracter Fehler bei Parsefunktion
 
Danke DeddyH,

das sieht interesant aus. Ich werde mir das mal genauer an sehen.

Gruß Jens


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz