AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Gleiche Procedure mit unterschiedlichen ParameterTypen
Thema durchsuchen
Ansicht
Themen-Optionen

Gleiche Procedure mit unterschiedlichen ParameterTypen

Ein Thema von Christopher · begonnen am 28. Aug 2004 · letzter Beitrag vom 1. Sep 2004
Antwort Antwort
Seite 1 von 2  1 2      
Christopher

Registriert seit: 29. Aug 2003
9 Beiträge
 
#1

Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 28. Aug 2004, 23:08
Hallo! Ich brauche mal Hilfe:

Ich habe in einer kleinen Verwaltungssoftware ein Problem. Ich habe zwei File of Records (File of TCustomer & File of TJob) und diese sollen zu Beginn des Programms in verschiedene Arrays (Array of TCustomer & Array of TJob) eingelesen werden. Dabei enthält eine Datei die Kunden und die andere die Termine.
Ich würde gerne eine Procedure haben die diese beiden Dateien in die beiden Arrays liest OHNE diese blöde Wiederholung des Quelltextes, wie unten zu sehen. Es ist ja alles genau zweimal vorhanden. Das finde ich äußerst unvorteilhaft. Am liebsten hätte ich eine Procedure, der ich den Dateinamen und das Array übergebe, in das die Datei geschreiben werden soll. Aber da die jeweiligen Datei und Arraytypen unterschiedlich sind (TJob / TCustomer) bekomme ich das nicht hin! Eine überladene Procedure würde ja zwar vom Aufruf her genau das bewirken, aber dann hab ich den Code trotzdem zweimal!

Hätte da jemand ne Lösung? Ich komm einfach nicht drauf.... DANKE!!!

Delphi-Quellcode:
procedure TFrmMain.ReadFileToArray();
var
  i : LongInt;
begin
  assignfile(CustomerFile, 'Customer.dat');
  if fileExists('Customer.dat')
  then
    begin
    Reset(CustomerFile);
    i := 0;
      while not EOF(CustomerFile) do
      begin
        setlength(Customer, i + 1);
        Seek(CustomerFile, i);
        read(CustomerFile, Customer[i]);
        inc(i);
      end;
    CloseFile(CustomerFile);
    end
  else
    begin
    setlength(Customer, 0);
    end;

//Und jetzt genau das gleiche mit TJob

  assignfile(JobFile, 'Job.dat');
  if fileExists('Job.dat')
  then
    begin
    Reset(JobFile);
    i := 0;
      while not EOF(JobFile) do
      begin
        setlength(Job, i + 1);
        Seek(JobFile, i);
        read(JobFile, Jobr[i]);
        inc(i);
      end;
    CloseFile(JobFile);
    end
  else
    begin
    setlength(Job, 0);
    end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von Manzoni
Manzoni

Registriert seit: 15. Feb 2004
Ort: Berlin
120 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 28. Aug 2004, 23:35
Hab schon lange nichts mehr in Delphi gemacht, aber meine spontane Idee wäre, ob es nicht eine gemeinsame Oberklasse (TArray???) gibt?
Bob
  Mit Zitat antworten Zitat
Christopher

Registriert seit: 29. Aug 2003
9 Beiträge
 
#3

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 28. Aug 2004, 23:44
Hab ich leider nicht gefunden. Aber soweit ich weiß, gibt es auch keine Oberklasse TFile. die bräuchte ich dann ja auch, wenn ich dich richtig verstanden habe.

Edit: Jetzt habe ich schonwieder das gleiche Problem an einer anderen Stelle:
Ich will eine Procedure die ein element eines der Arrays löscht. Dazu muss ich das array als var Parameter übergeben. Aber die Arrays sind unterschiedlich deklariert! Deswegen geht das auch wieder nicht! HILFE!
  Mit Zitat antworten Zitat
Assarbad
(Gast)

n/a Beiträge
 
#4

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 29. Aug 2004, 00:14
Zitat von Christopher:
Hab ich leider nicht gefunden. Aber soweit ich weiß, gibt es auch keine Oberklasse TFile. die bräuchte ich dann ja auch, wenn ich dich richtig verstanden habe.

Edit: Jetzt habe ich schonwieder das gleiche Problem an einer anderen Stelle:
Ich will eine Procedure die ein element eines der Arrays löscht. Dazu muss ich das array als var Parameter übergeben. Aber die Arrays sind unterschiedlich deklariert! Deswegen geht das auch wieder nicht! HILFE!
Zum ersten Problem:
Nimm den Kerncode (ResetFile bis CloseFile) und schreibe ihn nur einmal generisch auf - für das Auslesen des spezifischen Records benutze eine Callback-Funktion welche vom Kerncode aufgerufen wird.

Zum zweiten Problem ist die Lösung analog. Hilfreich könnte sich erweisen, daß ein Array ein kontinuierlicher Speicherbereich ist und man ein Array of Struct wie ein Pointer auf Struct ansprechen kann ... so kann das Füllen komplett unabhängig von Struct geschehen.

Unter C++ gäbe es dann noch template-Funktionen *g*
  Mit Zitat antworten Zitat
Christopher

Registriert seit: 29. Aug 2003
9 Beiträge
 
#5

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 29. Aug 2004, 00:30
Danke für deine Antwort: Aber ich da ein paar fragen

Zum ersten Problem:
Nimm den Kerncode (ResetFile bis CloseFile) und schreibe ihn nur einmal generisch auf


Was heißt generisch? Kenne den Ausdruck leider nicht.
Du meinst warscheinlich "allgemein mit Variablen" oder?
Aber dann brauche ich doch eine Variable die zu TJob UND
zu TCustomer "kompatibel" ist. Oder hab ich das jetzt falsch
verstanden?

- für das Auslesen des spezifischen Records benutze eine Callback-Funktion welche vom Kerncode aufgerufen wird.
Heul... Was ist eine CallBack-Funktion? Ist das um im Code zurückzuspringen?
Wenn ja, wie macht man das? Ich kenne das nur mit Labels im Code.

Zum zweiten Problem ist die Lösung analog. Hilfreich könnte sich erweisen, daß ein Array ein kontinuierlicher Speicherbereich ist und man ein Array of Struct wie ein Pointer auf Struct ansprechen kann ... so kann das Füllen komplett unabhängig von Struct geschehen.

Unter C++ gäbe es dann noch template-Funktionen *g*


Na und da verstehe ich nur noch Bahnhof. Array of Struct konnte mir die Delphi-Hilfe auch nicht erläutern. Man so ein Mist, bi ich wirklich so doof, dass ich das alles nicht verstehe?
  Mit Zitat antworten Zitat
Assarbad
(Gast)

n/a Beiträge
 
#6

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 29. Aug 2004, 09:58
Zitat von Christopher:
Was heißt generisch? Kenne den Ausdruck leider nicht.
Du meinst warscheinlich "allgemein mit Variablen" oder?
Generisch bedeutet "allgemein gehalten".

Zitat von Christopher:
Aber dann brauche ich doch eine Variable die zu TJob UND
zu TCustomer "kompatibel" ist. Oder hab ich das jetzt falsch
verstanden?
Pointer ist kompatibel.

Zitat von Christopher:
Heul... Was ist eine CallBack-Funktion? Ist das um im Code zurückzuspringen?
Wenn ja, wie macht man das? Ich kenne das nur mit Labels im Code.
Also, stell dir vor du willst eine Textdatei auslesen (ist ja hier ganz ähnlich). Nun hast du die Aufgabe, daß du zwar für das Auslesen zuständig sein sollst (und auch für das Trennen der Token), aber daß ein weiterer Programmierer ohne Kenntnis deines Codes in die Lage versetzt werden soll die Konfigurationstextdatei zu parsen. Was tust du also? Genau, du gibst einen Prototypen für eine Funktion vor, Beispiel:
type TFNMyCallback=function(Identifier:PChar; Value:PChar); Deine generische Funktion welche durch den Code geht, sieht nun zB folgendermaßen aus:

function ReadMyFile(fName:PChar; FNcallback:TFNMyCallback); Ist der Funktionspointer, welcher als Parameter übergeben wurde, NIL, tust du nichts. Sonst rufst du die Callbackfunktion ganz normal auf und übergibst die Daten aus Kernfunktion die du benötigst (sagen wir mal Recordgröße und Pointer zu Puffer o.ä.)

if Assigned(FNcallback) FNcallback(Identifier, Value);
Zitat von Christopher:
Na und da verstehe ich nur noch Bahnhof. Array of Struct konnte mir die Delphi-Hilfe auch nicht erläutern. Man so ein Mist, bi ich wirklich so doof, dass ich das alles nicht verstehe?
Nennen wir es Array of Record, okay? Nun verstanden. Sorry, bin derzeit etwas zu sehr in meine C++-Programmierung vertieft

Template-Funktionen funktioniern unabhängig vom Typ. Beispiel (Funktion welche Maximalwerte herausfindet):
Code:
template <class T> T Max(T Wert1, T Wert2);
Beim Aufruf tust du nun dies:
Code:
double d = Max<double>(d1, d2);
int i = Max<int>(i1, i2);
unsigned char u = Max<unsigned char>(c1, c2);
Wie du siehst, mußt du den Prototypen (und konsequenterweise auch den Rumpf) nur einmal schreiben und kannst ihn dann für verschiedene Typen (nicht nur, wie oben, Basistypen) nutzen. Wäre hier für dich ideal.
  Mit Zitat antworten Zitat
Christopher

Registriert seit: 29. Aug 2003
9 Beiträge
 
#7

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 29. Aug 2004, 11:26
Ich sitz hier jetzt schon fast ne Stunde und versuche umzusetzen was du mir geschrieben hast. Aber irgendwie ist mir der Sinn/das Ziel noch nicht 100% klar, weshalb ich nicht so richtig weiß vorauf ich hinarbeite. Das macht es für mich unmöglich deinen Vorschlag umzusetzen. Ich gebe mir echt mühe, aber ich verstehe das einfach nicht. Du hast ja schon so viel geschrieben, ich mag dich garnicht mehr fragen: Aber würdest du mir den gefallen tuen und mir ein kleines Beispiel in Delphi programmieren? Denn das ist für meinen Wissensstand einfach zu abgehoben, weswegen ich das auch sehr genre lernen würde...
  Mit Zitat antworten Zitat
Assarbad
(Gast)

n/a Beiträge
 
#8

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 29. Aug 2004, 11:58
Wenn es bis morgen Zeit hat, dann schreib mir morgen nochmal ne PN. Ich bräuchte dann auch noch die Prototypen der beiden Records (Customer, Job).
  Mit Zitat antworten Zitat
Christopher

Registriert seit: 29. Aug 2003
9 Beiträge
 
#9

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 29. Aug 2004, 12:03
Wird gemacht... Danke!
  Mit Zitat antworten Zitat
Assarbad
(Gast)

n/a Beiträge
 
#10

Re: Gleiche Procedure mit unterschiedlichen ParameterTypen

  Alt 1. Sep 2004, 14:34
Ich hab da mal was vorbereitet. Bedienungsanleitung ist als Kommentar dabei. Habe es noch nicht getestet. Probiers mal und beschwer dich wenn es nicht funzt.

Delphi-Quellcode:
(*
  Diese Funktion liest aus einer Datei mit einer beliebigen Anzahl von Records
  einer festen Größe (wobei die Dateigröße 2 GB nicht überschreiten darf) die
  Reccords in ein Array. Dabei ist für die Funktion irrelevant wieviele Records
  sie lesen soll oder wie die Struktur eines Records oder des Arrays ist.

  Die Funktion erfüllt gleichzeitig eine zweite Aufgabe:

  [...]
    xArray : array[] of TMyRecordType;
  begin
  // Get number of records in the file
    dwNumRecordsBefore := ReadFileIntoArray('datei.dat', Nil, 0, sizeof(TMyRecordType));
  // Adapt array size
    SetLength(xArray, dwNumRecords);
  // Read into the array
    dwNumRecordsAfter := ReadFileIntoArray('datei.dat', @xArray, dwNumRecordsBefore, sizeof(TMyRecordType));
  end;

  Wie man sehen kann, holt der erste Aufruf, bei dem die Anzahl zu lesender
  Elemente auf Null gesetzt wurde, die Anzahl von Records in der Datei.
  Danach wird die Arraygröße angepaßt und das Array wird ausgelesen.

  Wenn man will, kann man danach dwNumRecordsAfter und dwNumRecordsBefore
  vergleichen.

  ACHTUNG: Diese Funktion checkt nicht, ob die Dateigröße ein ganzzahliges
  Vielfaches der Recordgröße ist, also quasi ob die Anzahl von Records exakt
  paßt. Stattdessen wird die maximale Anzahl von Records ermittelt, die in eine
  Datei der entsprechenden Größe passen würden.
*)


function ReadFileIntoArray(
// Holds the filename of the file to read
  sFileName: string;
// Pointer to the first element of a sized array
  lpArray: Pointer;
// Number of elements to read
// --> if this is 0 the function returns the number of records in the file
  dwNumToRead:DWORD;
// Size of a single record in the file - MUST NOT be zero!!!
  dwSizeOfElement: DWORD
// Return number of elements read
  ): DWORD;
var
  hFile: THandle; // Handle to the file to read
  i, // Loop counter
    dwRead, // Holds the number of read bytes
    dwNumrecords: DWORD; // Holds the number of records to read
  lpBuffer:Pointer; // Intermediate pointer - holds current offset inside array
  bError:Boolean;
begin
  Result := 0;
  bError := False;
// Open file read-only
  hFile := CreateFile(@sFileName[1], GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
// If successfully opened
  if hFile <> INVALID_HANDLE_VALUE then
  try
// Check filesize, get number of records to read!
    dwNumRecords := GetFileSize(hFile, nil);
// Only read if the function succeeds
    if dwNumRecords <> INVALID_FILE_SIZE then
    begin
// Calculate the number of elements to read ...
      dwNumRecords := dwNumRecords div dwSizeOfElement;
// If the array pointer is not assigned ...
      if dwNumToRead = 0 then
      begin
// Return maximum number of records in the file
        Result := dwNumRecords;
        Exit;
      end;
// If the array buffer is NIL
      if not Assigned(lpArray) then
        Exit;
// Adjust number of records to read in case the caller wants less records than are in the file
      if dwNumToRead < dwNumRecords then
        dwNumRecords := dwNumToRead;
// Read the calculated number of records
      for i := 0 to dwNumRecords - 1 do
      begin
// Calculate the offset at which to read
        lpBuffer := Pointer(DWORD(lpArray) + i * dwSizeOfElement);
// Read the record into the buffer
        bError := not ReadFile(hFile, lpBuffer, dwSizeOfElement, dwRead, nil);
// Check for size read - if smaller than required or Error -> quit
        if (dwSizeOfElement <> dwRead) or bError then
        begin
// Fill buffer with zeroes ... - maybe obsolete
          ZeroMemory(lpBuffer, dwSizeOfElement);
// Upon failure quit here
          Break;
        end;
// Set the number of successfully read records
        Result := i;
      end;
    end;
  finally
// Close file
    CloseHandle(hFile);
  end;
end;
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz