| Autor |
Beitrag |
DelphiNoob
      
Beiträge: 152
Win 2003 Server
D7 Ent
|
Verfasst: So 23.03.03 12:26
Hi,
ich will nen Shortstring in ein TListitem Data Feld packen! Der ist aber Pointer, und ne umwandlung von ShortString nach Pointer geht ja nicht wirklich.
Wäre nett wenn mir jemand kompatible Typen nenne könnte. Im Shortstring steht übrigens immer eine IP Adresse, vieleicht ist das ja hilfreich zu wissen.
Mfg
DelphiNoob
|
|
SMI
      
Beiträge: 106
Win95-2003 / Debian / Suse
D1/D3/D6/D7
|
Verfasst: So 23.03.03 14:15
Prinzipiell müssten folgende Zeilen helfen.
STRING -> POINTER;
* Zuerst wird genügend Speicher reserviert Stringlänge +1 Zeichen
* Danach wird der String in einen Pointer Of Char umgewandelt
* und schließlich der Pointer zurückgegeben
POINTER -> STRING;
* Mithilfe von dem Cast STRING(PCHAR( pointer)) wandelt man den
Pointer in einen PChar um und dann schließlich ein einen String;
WICHTIG !!!
* Die Länge des Strings kann nicht mehr verändert werden!
* Man muss den Pointer nach Gebrauch per Hand freigeben !
Darüberhinaus sollte man ihn noch mit NIL ins Nirvana schicken
* Der Code ist "Quick & Dirty" als es findet keine Fehler
Überprüfung statt!
SMI
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:
| VAR pp :Pointer;
Function ShortStringToPointer(s:String): Pointer; VAR p : PCHAR; BEGIN GetMem(p,length(s)+1); StrPCopy(p,s); result:= POINTER(p); END;
procedure TForm1.Button1Click(Sender: TObject); VAR str: string[20]; begin str:= 'TEST'; pp := NIL; pp := ShortStringToPointer(str); end;
procedure TForm1.Button2Click(Sender: TObject); begin showmessage('|'+STRING(PCHAR(pp))+'|'); freemem(pp); // WICHTIG !!!! pp:= NIL end; |
_________________ Wenn es im Jahre 1879 schon Computer gegeben hätte, würden diese vorausgesagt haben, daß man infolge der Zunahme von Pferdewagen im Jahre 1979 im Pferdemist ersticken würde.
(John C. Edwards, brit. Zukunftsforscher)
Zuletzt bearbeitet von SMI am So 23.03.03 14:27, insgesamt 1-mal bearbeitet
|
|
DelphiNoob 
      
Beiträge: 152
Win 2003 Server
D7 Ent
|
Verfasst: So 23.03.03 14:19
Danke! Sehr nett erklärt.
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Mo 24.03.03 15:43
Hi!
Eine IP-Adresse? Dann brauchst du gar keinen Shortstring, sondern nur ein Integer. Die Pointer-Variable ist ja genau 32 Bit groß, nimmt also genau den Platz ein, den du für eine IP-Adresse benötigst. Das kannst du einfach mit
"ListItem.Data=Pointer(IPAdress);" zuweisen.
Du musst nur zwei Routinen schreiben die die Umwandlung erledigen, also :
function StrToIP(Str:String):Integer;
function IPToStr(IP:Integer):String;
Die gibt es bestimmt schon irgendwo vorgefertigt.
Cu,
Udontknow
|
|
DelphiNoob 
      
Beiträge: 152
Win 2003 Server
D7 Ent
|
Verfasst: Mo 24.03.03 16:19
Also du meinst wenn die IP Adresse Integer ist, kann ich einfach: Listitem.Data := Pointer(MeinString); machen?
Muss ich da nicht noch groß ne Function schreiben für Pointer()?
Weil den Ursprünglichen String einfach in einen Integer zu wandeln ist ja kein Problem.
|
|
DelphiNoob 
      
Beiträge: 152
Win 2003 Server
D7 Ent
|
Verfasst: Mo 24.03.03 16:32
Ich hab das mal ausprobiert, aber er sagt klipp und klar das ne IP Adresse kein gültiger Integer Wert ist. Irgendwie auch klar, weil ich sehe "255.255.255.255" auch nicht als Zahl an. Allein schon wegen den vielen Punkten. Also irgendwie muss man da doch was machen können.
|
|
DelphiNoob 
      
Beiträge: 152
Win 2003 Server
D7 Ent
|
Verfasst: Mo 24.03.03 16:56
OK ERLEDIGT!
Habs auf ne etwas andere art gelöst, indem ich den String umwandle! Aber es funzt jetzt!
DANKE
|
|
SMI
      
Beiträge: 106
Win95-2003 / Debian / Suse
D1/D3/D6/D7
|
Verfasst: Mo 24.03.03 20:26
@Udontknow
ListItem.Data:=Pointer(IPAdress); ist brand gefährlich müsste zudem auch nicht tun, denn du übergibst einen Pointer der auf den Inhalt von IPAdresse zeigt, desweiteren sollten Pointer Speicherplätze sollten gar nie(!) Zweckentfremdet werden. Das kann sehr böse ins Auge gehen. Man weiß nie wie die der übergebene Pointer intern benutzt wird, es kann/könnte zu sporadischen nicht definierbaren abstürzen, sowie zu Datenverlust kommen! Daher setzt man auch Pointer immer zu NIL wenn man sie nicht mehr braucht! Ich kann dazu nur sagen, das Pointer Anfänger vieleicht reizen aber um damit umgehen zukönnen muss man viele Feinheiten wissen, und dass brauch jahrelange Programmiererfahrung!
@All
IP -> INTEGER;
* Zuerst werden 4 Bytes ( entspricht einem Integer) reserviert
* nun wird dem golbalen Pointer of Byte pAscii dir adresse der IP String übergeben.
* NextTriple zerlegt die Tripel einer IP.
* Tripel (1byte lang) wird nun in pByte gespeichert.
* und der Zeiger von pByte um eins erhöht
* selbisges geschieht noch 3 Mal
* Danach wird der Zeiger wieder um 3 zurück geschoben
* pByte übergibt seine Adresse einem Pointer of Integer
* selbiger wid nun derefenziert und übergibt seinen Inhalt an die Funktion
NextTriple
* Rückgabe Wert wird genullt
* Wenn das aktuelle Byte vom String IP dem einem Punkt (Ascii Wert 46 ) entspricht winr die Position im String um eins erhöht
* Solange die Schleife ungleich der Binären 0 oder einem Punkt ist
* wird die Variable result um eine Stelle erhöht
* der Asciiwert des aktuellen Zeichen - dem Zeichen '0' (48) in result addiert.
* Danach wird die Position im String um eins erhöht
Bemerbung:
Quelltext 1: 2: 3:
| // "Ascii" Table // 46 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 // . | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
String 172 entspricht der Ascii Folge 49|55|50 man könnte sie aber auch so darstellen 49-48=1|55-48=7|50-48=2
INTEGER -> IP;
* Die Adresse des Integers wid dem Pointer of Char übergeben
* Das erste Byte des Intergers wird gelesen und in einen String umgewandelt.
* der Pointer wird um eins erhöht
* selbiges geschieht noch drei mal
WICHTIG !!!
* Es findet keine Fehler überprüfung, d.h. statt übergibt man den funktionen Schrott wird es einen bösen Absturz geben!
* Die Funktion NextTriple greift auf die Variable der Funktion IpToInt zurück!
BEISPIEL
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.Button1Click(Sender: TObject); VAR ip : integer;
BEGIN ip := IpToInt('172.20.0.1'); Showmessage(IntToStr(ip)); showmessage(IntToIp(IP)); END; |
CODE:
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: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
| FUNCTION IpToInt(IP:String): Integer; VAR pAscii : ^Byte;
FUNCTION NextTriple : BYTE; BEGIN result:=0; IF (pAscii^=46) THEN INC(pAscii); WHILE (pAscii^<> 0) AND (pAscii^<>46) DO BEGIN result:=result *10; result:= Result + (pAscii^ -48); INC(pAscii); END; END;
VAR pByte: ^Byte; iIp : ^Integer; testInt :Integer; begin GetMem(pByte, 4); pAscii:=POINTER(IP); pByte^:= NextTriple; INC(pByte,1); pByte^:= NextTriple; INC(pByte,1); pByte^:= NextTriple; INC(pByte,1); pByte^:= NextTriple; DEC(pByte,3);
iIP:=POINTER(pByte); result:=iIP^; FreeMem(pByte); end;
FUNCTION IntToIp(Ip:Integer): STRING; VAR pByte: ^Byte; begin
pByte := @IP; // Delphi castet INTEGER nicht zu einem typ geringerer // genauigkeit ohne Schutzverletzunggecastet werden // daher müssen wird via @ explizit nur die Adresse übergeben. // Hier würde POINTER(IP) würde zu einer schutzverletzung führen!!!
result:=IntToStr(pByte^)+'.'; INC(pByte); result:=Result + IntToStr(pByte^)+'.'; INC(pByte); result:=Result + IntToStr(pByte^)+'.'; INC(pByte); result:=Result + IntToStr(pByte^); end; |
_________________ Wenn es im Jahre 1879 schon Computer gegeben hätte, würden diese vorausgesagt haben, daß man infolge der Zunahme von Pferdewagen im Jahre 1979 im Pferdemist ersticken würde.
(John C. Edwards, brit. Zukunftsforscher)
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Mo 24.03.03 21:37
@SMI:
Naja, also als Anfänger würde ich mich nicht gerade bezeichnen. Ich habe da schon so einige Jahre auf dem Buckel... Kommen wir mal zum Thema:
Die Zweckentfremdung ist in keinster Weise brandgefährlich, ich mache es sehr häufig so. Ohne Fehler. Du hast da, glaube ich, ein Verständnis-Problem, was Typenkonvertierung angeht.
| Zitat: | | denn du übergibst einen Pointer der auf den Inhalt von IPAdresse zeigt, |
Nein, das ist falsch. Ich übergebe den Integer-Wert einer IP-Adresse als Pointer. Pointer(Integerwert) gibt nicht einen Zeiger auf den Integerwert zurück, sondern den Integerwert als Zeiger.
Wenn ich den Wert wieder abgreifen will konvertiere ich einfach in die andere Richtung: Ich hole den Wert des Pointers und konvertiere ihn zu Integer.
Deshalb kann es auch gar nicht zu Datenverlust kommen. Weder reserviere ich dynamisch Speicher, noch ändere ich irgendwelche Adressen von Variablenzeigern. Es ist schlicht und ergreifend nur eine Typkonvertierung.
Genau das gleiche macht übrigens die Funktion Ptr:
| Zitat: | function Ptr(Address: Integer): Pointer;
In Delphi konvertiert Ptr die mit Address angegebene Adresse in einen Zeiger. Durch einen Aufruf dieser Funktion wird kein Quelltext erzeugt, der angegebene 32-Bit-Wert wird einfach als Zeiger behandelt. Wie NIL ist der Rückgabewert von Ptr zu allen Zeigertypen zuweisungskompatibel. |
Was deine Routinen angeht:
Du machst es dir meiner Meinung nach unnötig schwer, indem du hier Speicher reservierst, da ein wenig mit der Ascii-Tabelle herumfummelst, und eine wahre Orgie mit Referenzierung und Dereferenzierung veranstaltest. Das kann früher oder später nur Chaos geben. Delphi hat doch IntToStr-beziehungsweise StrToInt-Routinen, warum denn mühselig alles selber zusammenrechnen?
Hier mal meine, wie ich finde, übersichtlicheren Routinen:
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: 36: 37: 38: 39: 40: 41: 42:
| function StrToIP(Str:String):Integer; var B:Array[0..3] of Byte; var i,DotPos:integer; var StrPart:String; begin //Dummypunkt zum Parsen hinzufügen Str:=Str+'.'; //Alle 4 8Bit-Werte ermitteln for i:=0 to 3 do begin //Position des nächsten Punkts ermitteln Dotpos:=Pos('.',Str); //Chars bis zum nächsten Punkt ermitteln StrPart:=Copy(Str,1,DotPos-1); //Alles bis zum nächsten Punkt aus Str ausschneiden Str:=Copy(Str,DotPos+1,255); //Byte-Wert ermitteln B[i]:=StrToInt(StrPart); end;
//Integer aus den Bytes zusammenstellen Result:=B[3]; for i:=2 downto 0 do Result:=Result shl 8 +B[i]; end;
function IPToStr(IP:Integer):String; var B:Byte; var i:integer; begin Result:=''; //Sämtliche Bytes durchgehen for i:=0 to 3 do begin //Speicherstelle des Integers byteweise abtasten B:=Byte(Pointer(Integer(Addr(IP))+i)^); //Byte als Str zum Resultat hinzufügen Result:=Result+IntToStr(B); if i<3 then Result:=Result+'.'; end; end; |
Cu,
Udontknow
|
|
SMI
      
Beiträge: 106
Win95-2003 / Debian / Suse
D1/D3/D6/D7
|
Verfasst: Di 25.03.03 04:12
@Udontknow
Du hattest mich da falsch verstanden. Als erstes die Warnung für Anfänger war nicht an dich gerichtet sondern an die Allgemeinheit. Desweitern ist das Problem wo es zu Datenverlust kommen kann, folgendes du weist dem Pointer Speicherplatz TListItem.Data eine " Fake" Adresse. Diese Adresse ist wie du ja beschrieben hattest keine reale Adresse, sondern nur ein als Integer mißbrauchter Pointer, der igendwohin zeigt. Weißt au aber was ListItem intern mitdiesem Pointer macht? Wie sieht es mit zukünftigen Windows Versionen aus? Was ist wenn in einer zukünftigen Windowsversion überprüft wird, ob der Pointer überhaupt zulässig ist. Denn er kann genausogut auf einen geschützten Speicherbereich zeigen, das würde eine nicht deutbare Schutzverletzung geben. Des weiteren könnet Listbox selber den Pointer in einer ähnlich Art und Weise mißbrauchen, oder eine verrsteckte Funktion zur Speicherfreigabe, die bei Fehlern eingreift haben.
Genau das sind die Gründe, warum man Pointer nur als Zeiger verwenden sollte, und nicht als Datenspeicher mißbraucht!
Mit einem muss dir Wohl oder Übel rechtgeben mein Ausführung zu ListItem.Data:=Pointer(IPAdress), dass war und ist ein Denkfehler gewesen und somit Schlichtweg falsch. Zu meiner Verteidigung: Ich habe die Benutzung von Casts und Pointer nicht in Pascal gelernt sonder in C/C++.
Delphi TypeCasts sind eh was besonderes Delphi überprüft intern irgendwie ihre Gültigkeit, oder kanst du mir sagen wie folgendes nur mit einer Typumwandlung ohne zusätzlichen reservierten Speicher funktioniert. Ich wandele einen lokalen String via Cast in einen Pointer um, was an sich ja garnicht gehen kann und darf, da ein Pointer ja nur 4 Bytes speichern kann und mein String eindeutig größer ist. Nun ändere ich meinen String. Wenn ich nun in einer anderen Funktion den Pointer wieder in einen String Caste erhalte ich keine Schutzverletzung sonder den kompletten Stringwert wieder zurück. Warum geht das gut?
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| VAR p:pointer;
procedure TForm1.Button1Click(Sender: TObject); VAR str : String; int : integer; begin str := 'TEST TEST TEST TEST TEST TEST TEST TEST'; p:= POINTER(str); Str:='1234'; showmessage(str); end;
procedure TForm1.Button2Click(Sender: TObject); begin Showmessage(STRING(p)); end; |
Zu dem Thema "Was deine Routinen angeht":
Bei der Routine bin ich etwas anderer Meinung. Der Programmieraufwand war für beides Codes sicherlich gleich groß, ich glaube nicht, dass du merklich weniger Zeit als ich dazu gebraucht hast.
Zugegeben deiner sieht optisch übersichtlicher aus, jedoch viel besser lesbar ist er dadurch auch nicht geworden.
Hingegen ist die Performance meines Codes eindeutig wesentlich besser. Bei der ersten Funktion verwendest du einen String zum Zwischenspeichern, eine langsame for Schleife. Du greifst auf jeden Stringeintrag etwa 3 bis 4 mal zu, zuerst via pos, danach zwei mal via Copy und zuletzt nochmal mit StrToInt. Meine Routine verwendet eine schelle While Schleife und greift auf jeden String Eintrag genau einmal zu!
Die andere Funktion ist eigentlich exakt identisch. Mit dem Unterschied, das ich vollkommen ohne if Abfrage und For Schleife, Zählvariable und Abbruchbedingung auskomme, was eindeutig auch der Übersichtlichkeit dient.
Bei einem Projekt musste ich schonmal "schmerzhaft" feststellen, dass eine einzige "optimierte" Methode Stunden Rechenzeit sparen kann. Daher habe ich es mir angewöhnt alles mit möglichst geringen Schritten, möglichst Effektiv zu programmieren. Was sich bisher eigentlich immer ausgezahlt hat, daher kann ich es nur empfehlen.
Das ich eine "wahre Orgie mit Referenzierung und Dereferenzierung veranstalte" ist auch eine Erbsünde aus der C/C++ Programierung.
Aber dass daraus ein Chaos entsteht möchte ich bezweifeln, ansonsten wären deiner Theorie nach jegliches C/C++ Projekt zum scheitern verurteilt. Nur zur Erinnerung Windows und Linux basieren eigentlich nur auf C/C++ Code der mit Pointer nur so um sich schmeist.
SMI
Moderiert von UGrohne: Code-Tags eingefügt
_________________ Wenn es im Jahre 1879 schon Computer gegeben hätte, würden diese vorausgesagt haben, daß man infolge der Zunahme von Pferdewagen im Jahre 1979 im Pferdemist ersticken würde.
(John C. Edwards, brit. Zukunftsforscher)
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Di 25.03.03 07:50
| SMI hat folgendes geschrieben: | Delphi TypeCasts sind eh was besonderes Delphi überprüft intern irgendwie ihre Gültigkeit, oder kanst du mir sagen wie folgendes nur mit einer Typumwandlung ohne zusätzlichen reservierten Speicher funktioniert. Ich wandele einen lokalen String via Cast in einen Pointer um, was an sich ja garnicht gehen kann und darf, da ein Pointer ja nur 4 Bytes speichern kann und mein String eindeutig größer ist. Nun ändere ich meinen String. Wenn ich nun in einer anderen Funktion den Pointer wieder in einen String Caste erhalte ich keine Schutzverletzung sonder den kompletten Stringwert wieder zurück. Warum geht das gut?
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| VAR p:pointer;
procedure TForm1.Button1Click(Sender: TObject); VAR str : String; int : integer; begin str := 'TEST TEST TEST TEST TEST TEST TEST TEST'; p:= POINTER(str); Str:='1234'; showmessage(str); end;
procedure TForm1.Button2Click(Sender: TObject); begin Showmessage(STRING(p)); end; | |
Also was die TypeCasts angeht kann ich auch mal meinen Senf dazu geben...
Der normale Variablen-Typ String ist (sofern nicht per Projektoptionen oder Compiler-Schalter anders angegeben) nur ein Pointer. Ein String ist einem PChar gar nicht so unähnlich. Er zeigt auf eine Speicherstelle an der die Zeichenkette abgelegt ist, und genauso wie auch beim PChar wird das Ende mit einem Nullzeichen gekennzeichnet. Hier endet aber auch schon die Ähnlichkeit. Delphi verwendet nämlich intern noch eine Länge und einen Referenzzähler (beides 32Bit Integer) welche VOR der eigentlichen Zeichenkette stehen (also praktisch ein negatives Offset haben). Der TypeCast Pointer(String) gibt also eigentlich nur einen Pointer auf das erste Zeichen zurück. Das kann man auch ganz einfach zeigen wenn man dein Beispiel erweitert:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| VAR str: String; p: Pointer begin str := 'TEST TEST TEST TEST TEST TEST TEST TEST'; p:= Pointer(str); ShowMessage(str); ShowMessage(PChar(p));
PChar(p) := 'blablabla' ShowMessage(str); ShowMessage(PChar(p)); end; |
Eine weitere Möglichkeit einen String in einen PChar zu konvertieren ist ein direkter TypeCast PChar(String) oder @String[1]. Je nach Methode führt Delphi intern jedoch verschiedene mappings aus.
Mehr Informationen dazu findest du hier: www.delphipraxis.net/viewtopic.php?t=1188
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Di 25.03.03 08:33
Korrekt @ Motzi.
@SMI:
Du hast natürlich recht, wenn du sagst, daß so ein missbrauchter Pointer dann auf einen Speicherbereich zeigt, der nicht unbedingt initialisiert ist. Aber das ist tatsächlich egal, denn die Benutzung dieser Pointer liegt allein in der Hand des Entwicklers (siehe Hilfe Zu TListItem.Data). Niemals gibt eine (Standard-)Komponente einfach mal irgendeinen Speicherbereich frei, oder führt eine Operation darauf aus. Und da MS immer Wert auf Abwärtskompatibiltät legt, werden sie auch keine versteckte Betriebssystem-Funktion einschleusen, die so etwas macht. Es stellt sich die Frage, ob ein Betriebssystem überhaupt erkennen kann, was ein Pointer ist und was nicht.
Ein weiteres schönes Beispiel für das reibungslose Ablaufen von Typenkonvertierung, das ich häufig einsetze, ist TIntegerList. Du kannst sehr einfach eine Klasse TIntegerlist stricken, die einfach anstelle von Zeigern Integerwerte speichert (jetzt rate mal, wie  ).
Hier mal der Code:
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: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105:
| unit Integerlist;
// Unit mit der Klasse TIntegerlist, einer Liste von Integerwerten (Oh, wirklich??? ;) )
interface
uses classes;
type TIntegerList= class(TObject) private FList:TList; function GetItems(Index: Integer): Integer; procedure SetItems(Index: Integer; const Value: Integer); public procedure LoadFromStream(Stream:TStream); virtual; procedure SaveToStream(Stream:TStream); virtual; function Count:Integer; procedure Clear; function Add(Value:Integer):Integer; function IndexByValue(Value:Integer):Integer; property Items[Index:Integer]:Integer read GetItems write SetItems; default; constructor Create; destructor Destroy; override; end;
implementation
{ TIntegerList }
function TIntegerList.Add(Value: Integer): Integer; begin Result:=FList.Add(Pointer(Value)); end;
procedure TIntegerList.Clear; begin FList.Clear; end;
function TIntegerList.Count: Integer; begin Result:=FList.Count; end;
constructor TIntegerList.Create; begin FList:=TList.Create; end;
destructor TIntegerList.Destroy; begin FList.Free; inherited; end;
function TIntegerList.GetItems(Index: Integer): Integer; begin Result:=Integer(FList.Items[Index]); end;
function TIntegerList.IndexByValue(Value: Integer): Integer; var i:integer; begin Result:=-1; for i:=0 to Self.Count-1 do if Self[i]=Value then begin Result:=i; exit; end; end;
procedure TIntegerList.LoadFromStream(Stream: TStream); var Count:Integer; var i,Value:integer; begin Self.Clear; Stream.ReadBuffer(Count,SizeOf(Count)); for i:=0 to Count-1 do begin Stream.ReadBuffer(Value,SizeOf(Value)); Self.Add(Value); end; end;
procedure TIntegerList.SaveToStream(Stream: TStream); var Count:Integer; var i,Value:integer; begin Count:=Self.Count; Stream.WriteBuffer(Count,SizeOf(Count)); for i:=0 to Count-1 do begin Value:=Self[i]; Stream.WriteBuffer(Value,SizeOf(Value)); end; end;
procedure TIntegerList.SetItems(Index: Integer; const Value: Integer); begin FList.Items[Index]:=Pointer(Value); end;
end. |
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Di 25.03.03 13:56
@Udontknow: Die Idee hat was! Simpel aber effektiv!
Ich hatte vor mir in den nächsten Tagen auch eine Integer-Liste zu schreiben, aber jetzt.. hast du was dagegen wenn ich mir den Code "ausborge"?
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 25.03.03 13:59
Infos findet man auch noch hier: www.optimalcode.com/string.htm
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Di 25.03.03 15:37
@Motzi:
Klar kannst du, dafür habe ich ihn ja gepostet. Ein kleines "ThxTo" wäre alles, wenn du damit groß an die Öffentlichkeit willst...
Cu,
Udontknow
|
|
SMI
      
Beiträge: 106
Win95-2003 / Debian / Suse
D1/D3/D6/D7
|
Verfasst: Di 25.03.03 17:00
@Luckie
Danke.
@Udontknow
| Zitat: | | Aber das ist tatsächlich egal, denn die Benutzung dieser Pointer liegt allein in der Hand des Entwicklers (siehe Hilfe Zu TListItem.Data) |
In Hilfen kann viel stehen, genauso in Dokumentationen, aber hast du den Quellcode dazu gesehen? Da Microsoft ihn nicht rausrückt, weißt du also nicht, ob irgendo in TListItem.Data eine "versteckte" Freigabe steht. Besonders in der WinApi gibt es viele Befehle die sich entgegen der offiziellen Dokumentation verhalten.
Aber Prinzipiell ist es dein Problem, es ist nur so eine Sache wie mit dem Label und Goto Befehlen, sie existiern einwand frei, aber man sollte sie einfach nicht nicht verwenden!
SMI
_________________ Wenn es im Jahre 1879 schon Computer gegeben hätte, würden diese vorausgesagt haben, daß man infolge der Zunahme von Pferdewagen im Jahre 1979 im Pferdemist ersticken würde.
(John C. Edwards, brit. Zukunftsforscher)
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Di 25.03.03 17:27
| Udontknow hat folgendes geschrieben: | @Motzi:
Klar kannst du, dafür habe ich ihn ja gepostet. |
Dankeschön!
| Zitat: | Ein kleines "ThxTo" wäre alles, wenn du damit groß an die Öffentlichkeit willst...  |
Aber selbstverfreilicht!  Bist somit in der AboutBox meines X-Spys verewigt!  Wenn du willst kann auch dein richtiger Name rein...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Di 25.03.03 19:35
@SMI: Es ist irgendwie müssig, über so etwas zu diskutieren. Es steht nunmal in der Hilfe, und wenn es nicht so wäre, wie es dort steht, würde Borland bereits viele recht zornige Kommentare bekommen haben.
Wenn man sich auf gar nichts verlassen will, darf man gar nicht erst mit dem Programmieren anfangen. Und wie ich bereits sagte, ich bezweifle, dass das Betriebssystem erkennen kann, wie ein Programm bestimmte Speicherbereiche nutzt.
Cu,
Udontknow
|
|
|