Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Innere Struktur von TStrings / TMemo (https://www.delphipraxis.net/184449-innere-struktur-von-tstrings-tmemo.html)

p80286 27. Mär 2015 13:30

Delphi-Version: 7

Innere Struktur von TStrings / TMemo
 
Hallo zusammen,
es ist Freitag und vllt. Zeit für eine Frage neben dem täglichen Stress.
In der letzten Woche bin ich über einen der nicht auszurottenden Fehler gestoßen, eine Vis. Komponente als Datenspeicher mißbrauchen. Und zwar war folgendes:

Delphi-Quellcode:
procedure procc(const l1:tstrings);
var
  ll : tstrings;
begin
  ll:=tstringlist.Create;
  {fülle ll}
  for i:=0 to ll.count-1 do
    if pos('irgendwas',ll[i])>0 then l1.add(ll[i]); {!BP!}
  ll.free;
end;
Ist natürlich nicht der Originalcode, aber es reicht.

Irgendwo im programm gab es dann ein
Delphi-Quellcode:
procc(memo1.lines);
und ein for
Delphi-Quellcode:
i:=0 to l2.count-1 do ..
wobei l2 natürlich auch einen Bezug zu Memo1.Lines hat. Hier waren die Ergebnisse nun überhaupt nicht so wie ich es erwartet hatte, mit ein wenig Debuggerbenutzung bin ich dann auf folgendes gestoßen:

nach BP habe ich folgende Dateninhalte:

ll[0] = 'ganz schön langer string mehr als 255 Zeichen'
ll[1] = 'ganz schön langer string1 mehr als 255 Zeichen'
ll.Text = 'ganz schön langer string mehr als 255 Zeichen'x0Dx0A'ganz schön langer string1 mehr als 255 Zeichen'x0Dx0A

l1.Text = 'ganz schön langer string mehr als 255 Zeichen'x0Dx0A'ganz schön langer string1 mehr als 255 Zeichen'x0Dx0A
l1[0] = 'ganz schön langer'
l1[1] = 'string mit mehr als'
l1[2] = '255 Zeichen'
l1[3] = 'ganz schön langer' ... usw

Klar ist mir daß der "Zeilenumbruch" der Darstellung des TMemo geschuldet ist, doch müßte es doch dann korrekter Weise auch in .Text zu finden sein:
Code:
'ganz schön langer'x0Dx0A'string mit mehr als'x0Dx0A'255 Zeichen'
und eben das ist nicht der Fall.

habt Ihr dafür eine schlüssige Erklärung?

Gruß
K-H

himitsu 27. Mär 2015 13:35

AW: Innere Struktur von TStrings / TMemo
 
Nur TStringList kann innerhalb eines "Strings" Zeilenumbrüche verwalten, aber nur solange man die Strings dort drin belässt.
> Text, SaveTo... usw. lössen das auf

Grundsätzlich ist es also nicht möglich, außer du kodierst dir "diese" Zeilenumbrücke in etwas anderes (z.B. StringReplase in '<br>' oder sonstwas)

Anstonsten sollte man bei Zeilenlängen ab 255 1024 oder 4048 aufpassen, da einige Editoren damit nicht klar kommen. (z.B. der Codeeditor im Delphi ab 4047).

BadenPower 27. Mär 2015 14:00

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von p80286 (Beitrag 1295078)
Delphi-Quellcode:
procedure procc(const l1:tstrings);
var
  ll : tstrings;
begin
  ll:=tstringlist.Create;
  {fülle ll}
  for i:=0 to ll.count-1 do
    if pos('irgendwas',ll[i])>0 then l1.add(ll[i]); {!BP!}
  ll.free;
end;
Ist natürlich nicht der Originalcode, aber es reicht.

Wenn schon nicht OriginalCode, dann doch bitte einen Code, der dem originalen entsprechen könnte.

Deine übergebene Strings (Memo.Lines) im Parameter l1 wird in dieser Prozedure niemals irgendetwas hinzugefügt werden, da die For-Schleife niemals durchlaufen wird.

DeddyH 27. Mär 2015 14:12

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von BadenPower (Beitrag 1295080)
Deine übergebene Strings (Memo.Lines) im Parameter l1 wird in dieser Prozedure niemals irgendetwas hinzugefügt werden, da die For-Schleife niemals durchlaufen wird.

Jetzt könnte man raten, was
Zitat:

Delphi-Quellcode:
{fülle ll}

wohl zu bedeuten hat :roll:

BadenPower 27. Mär 2015 14:22

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von DeddyH (Beitrag 1295083)
Jetzt könnte man raten, was
Zitat:

Delphi-Quellcode:
{fülle ll}

wohl zu bedeuten hat :roll:

Wir wollen ja ein Problem lösen und nicht raten, wie sein PseudoCode aussehen SOLLTE.

Da steht {fülle ll} aber seine Anweisungen danach sagen "Füge zu l1 etwas hinzu" und zwar aus ll.

Ja was will er denn jetzt wirklich?

DeddyH 27. Mär 2015 14:53

AW: Innere Struktur von TStrings / TMemo
 
ll wird lokal erzeugt und irgendwie (interessiert hier auch nicht wirklich, wie genau) befüllt, anschließend zeilenweise durchlaufen und nach bestimmten Kriterien wird die aktuelle Zeile der übergebenen Liste hinzugefügt. Ich verstehe gar nicht, wieso Du nun hier die Welle machst.

BadenPower 27. Mär 2015 15:12

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von DeddyH (Beitrag 1295092)
Ich verstehe gar nicht, wieso Du nun hier die Welle machst.

Ich mache ja keine Welle, sondern will nur EINDEUTIG verstehen, was er tun möchte.

Den Kommentar hast Du so verstanden, dass dort ll befüllt wird. Aslo statt des Kommentars die Füllanweisung steht.

Ich jedoch war mir nicht sicher, denn der Kommentar kann auch aussagen, dass jetzt das Befüllen ll in der For-Schleife stattfinden soll. Es könnte ja ein verbleibendes Kommentarreststück aus dem OriginalCode sein.

Und dann wäre schon der Code falsch.

Und wenn für Dich alles so einleuchtend ist, dann hätte er auch eine globale Variable i.

DeddyH 27. Mär 2015 15:19

AW: Innere Struktur von TStrings / TMemo
 
Ich kenne K-H nun schon lange genug, um zu wissen, dass er so blöd nicht ist. Einerseits wird immer darauf gepocht, nur den relevanten Code zu posten, andererseits wird sich dann darüber echauffiert, wenn man ihn entsprechend eindampft. Aber gut, wenn das hier wieder so ein 40-Seiten-Thread werden soll, weil man sich an Niggeligkeiten hochzieht, dann bitteschön, ich bin hiermit raus, zumal himitsu ja wohl den entscheidenden Hinweis bereits gegeben hat.

himitsu 27. Mär 2015 15:28

AW: Innere Struktur von TStrings / TMemo
 
Ach ja, nur um nochmal den Grund zu erklären, warum das nicht so geht, mit Zeilenumbrüchen in Zeilen.
  • TMemoStrings (die Komponente in TMemo.Lines) ist ein Wrapper auf die Zeilen des Memos
  • eine Zeile ist eine Zeile
  • eine Zeile mit Zeilenumbrüchen drin ist mehrere Zeilen :roll:
  • TStringList dagegen verwaltet jede "Zeile" als einen eigenen "String" und da kann alles rein, was es so gibt, ohne daß es auswirkungen auf Nachbar-Strings hat, jedenfalls solange man die Strings als String belässt und es nicht zwischenzeitlich zusammengemanscht als "gemeinsamen" Text behandelt.


[edit]
Noch ein Post hat Platz, bis die Seite voll ist. :stupid:

schöni 27. Mär 2015 20:11

AW: Innere Struktur von TStrings / TMemo
 
Wir füllen ja sie Stringliste mit der Funktion Add.

Diese hängt offensichtlich den WagenrücklaufUndZeilenvorschub x0d0a automatisch an. Nicht das Tmemo ist dafür zuständig, sondern das TStringlist Objekt.

p80286 27. Mär 2015 21:45

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von himitsu (Beitrag 1295097)
TMemoStrings (die Komponente in TMemo.Lines) ist ein Wrapper auf die Zeilen des Memos

Danke! ich denke das war's
in .Lines finden sich die angezeigten Zeilen des Memos bzw. die Zeilen so wie sie angezeigt würden.

Gruß
K-H

hoika 27. Mär 2015 21:54

AW: Innere Struktur von TStrings / TMemo
 
Hallo,
schön wäre es gewesen, mal anständige Variablennamen zu benutzen ...

Heiko

Popov 27. Mär 2015 22:56

AW: Innere Struktur von TStrings / TMemo
 
@ #10

Also ich erkenne auf dem Weg zum Speicher keine Änderung an dem String. Zu beachten ist auch, dass der String stets als Konstante übergeben wird.
Delphi-Quellcode:
function TStringList.Add(const S: string): Integer;
begin
  Result := AddObject(S, nil);
end;

function TStringList.AddObject(const S: string; AObject: TObject): Integer;
begin
  if not Sorted then
    Result := FCount
  else
    if Find(S, Result) then
      case Duplicates of
        dupIgnore: Exit;
        dupError: Error(@SDuplicateString, 0);
      end;
  InsertItem(Result, S, AObject);
end;

procedure TStringList.InsertItem(Index: Integer; const S: string; AObject: TObject);
begin
  Changing;
  if FCount = FCapacity then Grow;
  if Index < FCount then
    System.Move(FList^[Index], FList^[Index + 1],
      (FCount - Index) * SizeOf(TStringItem));
  with FList^[Index] do
  begin
    Pointer(FString) := nil;
    FObject := AObject;
    FString := S;
  end;
  Inc(FCount);
  Changed;
end;

function TStringList.Find(const S: string; var Index: Integer): Boolean;
...

Sir Rufo 27. Mär 2015 23:12

AW: Innere Struktur von TStrings / TMemo
 
@Popov

Das war und ist auch nicht das Problem, sondern das spezielle Verhalten der konkreten
Delphi-Quellcode:
TStrings
Klasse bei einem
Delphi-Quellcode:
TMemo
.

Der gesamte Code mit dem kopieren und befüllen von
Delphi-Quellcode:
TStrings
ist irrelevant und eher störend. Das beobachtete Verhalten kann man ganz simpel mit einem
Delphi-Quellcode:
TMemo
nachstellen.
Delphi-Quellcode:
procedure TForm1.Button2Click( Sender: TObject );
begin
  Memo1.Width := 105;
  Memo1.Text := 'Dieses ist ein toller langer Text der in einem Memo angezeigt werden soll.';
  ShowMessage( IntToStr( Memo1.Lines.Count ) ); // 5
  ShowMessage( Memo1.Lines.Text ); // trotzdem nur eine Zeile ohne Zeilenumbrüche
end;

Popov 27. Mär 2015 23:45

AW: Innere Struktur von TStrings / TMemo
 
Das genannte Problem von p80286 eine Komponente als Datenspeicher zu missbrauchen ist in diesem Fall ein Ausnahmeproblem. Es ist kein TStrings Problem, auch kein TListBox Problem, sondern nur ein TMemo Problem.

Meine Antwort bezog sich übrigens auf den Hinweis in Post #10.

Hätte p80286 statt TMemo TListBox genommen, sein Problem wäre vermutlich nicht aufgefallen. TListBox ändert nichts, speichert aber ähnlich wie TMemo. Nur das Bearbeiten des Textes geht nicht so einfach wie bei TMemo.

Ich weiß nicht wo ich den Hinweis gelesen habe, ob im Code oder der Hilfe, auf jeden Fall stand dort, das bei TMemo TStrings nicht so arbeitet wie es eigentlich tun sollte.

jaenicke 28. Mär 2015 03:46

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von Popov (Beitrag 1295139)
Ich weiß nicht wo ich den Hinweis gelesen habe, ob im Code oder der Hilfe, auf jeden Fall stand dort, das bei TMemo TStrings nicht so arbeitet wie es eigentlich tun sollte.

Doch, TMemoStrings arbeitet schon genau so wie es das tun soll. Nur ist es eben nicht dafür gedacht zu etwas anderes als zur Anzeige oder Benutzereingabe zu dienen wie ja richtigerweise auch schon im Eingangspost steht.

Dejan Vu 28. Mär 2015 07:40

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von jaenicke (Beitrag 1295141)
Nur ist es eben nicht dafür gedacht zu etwas anderes als zur Anzeige oder Benutzereingabe zu dienen wie ja richtigerweise auch schon im Eingangspost steht.

Wenn Du mal einen 'Zeilenumbruch' anhand von Buchstabenbreiten implementieren willst, dann ist ein TMemo offensichtlich genau das Richtige. :lol:

Popov 28. Mär 2015 09:48

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von jaenicke (Beitrag 1295141)
Doch, TMemoStrings arbeitet schon genau so wie es das tun soll. Nur ist es eben nicht dafür gedacht zu etwas anderes als zur Anzeige oder Benutzereingabe zu dienen wie ja richtigerweise auch schon im Eingangspost steht.

Mit "das bei TMemo TStrings nicht so arbeitet wie es eigentlich tun sollte." meinte ich nicht, dass TStrings in TMemo unberechenbar ist und sonderbar arbeitet, sondern, dass es nicht 100% die Eigenschaft hat die es haben müsste. Beispiel: Lines von TMemo ist TStrings. TStrings kann Objekte fassen, Lines nicht. Obwohl es TStrings ist. Das meinte ich u. a. mit: "wie es eigentlich tun sollte".

Wenn man eine Klasse kennt, dann erwartet man immer gleiches Verhalten. Hier ist es nicht der Fall.

himitsu 28. Mär 2015 09:58

AW: Innere Struktur von TStrings / TMemo
 
Es verhällt sich alles genau so, wie es soll.

Bezüglich der Zeilenumbrüche funktioniert alles vollkommen richtig, genau so wie es die Definition der Komponente besagt.

TStrings bietet die Möglichkeit Objekte zu speichern, aber es muß nicht implementiert sein.
Gut, ich empfinde es schon immer als Fehler, daß der Objects-Setter von TMemoStrings keine Exceptions wirft, aber auf mich hört ja keiner.
Und nein, da MEMO es nicht anbietet, daß Zeilenbasiert Informationen gespeichert werden können, kann auch Lines dieses Feature nicht anbieten.
Bei TStringList und dn Items einer TListBox ist das was Anderes, denn dort besitzen die Komponenten einen Speicher dafür.

Popov 28. Mär 2015 10:20

AW: Innere Struktur von TStrings / TMemo
 
Sonderbar, im ersten Post steht etwas über Probleme, aber kaum geht man drauf ein, schon behaupten alle, dass alles so ist wie es sein soll. Wozu dann die Frage?

Natürlich ist es so wie es sein soll. Deshalb auch der Hinweis in der Hilfe. Hat zwar jetzt nichts mit dem Thema zu tun, aber mit TStrings:
Zitat:

Hinweis: Obwohl die Eigenschaft Lines von TStrings abgeleitet ist, implementiert sie keine Unterstützung für das Zuordnen von Objekten zu den Listen-Strings.
Hinweise sind ja auch dazu da übliches Unübliches üblich zu machen.

Sir Rufo 28. Mär 2015 10:23

AW: Innere Struktur von TStrings / TMemo
 
Wie sollte denn das Speichern von Objekten bei einem Memo funktionieren?

Richtig, es ist nicht sinnvoll implementierbar ... darum hat man es sich verkniffen irgendeinen Quatsch zu implementieren.

Falls jemand da aber eine zündende Idee hat, immer her damit.

himitsu 28. Mär 2015 10:26

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von Sir Rufo (Beitrag 1295154)
Falls jemand da aber eine zündende Idee hat, immer her damit.

Eine Exception beim Zuweisen, damit man sofort mitbekommt, daß der Zuweisung ins Nichts ging.

Einfach so nichts zu machen ist jedenfalls nicht die beste Lösung.

jaenicke 28. Mär 2015 18:14

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von Sir Rufo (Beitrag 1295154)
Wie sollte denn das Speichern von Objekten bei einem Memo funktionieren?

Richtig, es ist nicht sinnvoll implementierbar ...

So allgemein stimmt das nicht, man muss nur neu hinzugefügte Zeilenumbrüche tracken usw., nur dass ich das eben manuell mache. In meinem Fall füge ich Inhalte von mehreren Dateien in einem Editor zusammen und markiere die Herkunft farblich. (Es handelt sich um eine spezielle Skriptsprache.)
Wenn nun eine neue Zeile hinzugefügt wird, wird das Tracking entsprechend hinzugefügt, zu welcher realen Datei diese Zeile dann gehören wird. (Zu der Datei, in dessen Zeile Enter gedrückt wurde.)
Und am Ende wird dann alles in die einzelnen Dateien wieder gespeichert.

Dieses Tracking gibt es bei Syntaxeditoren ja auch.

Dass der Aufwand für TMemo als allgemeiner Komponente nicht sinnvoll gewesen wäre, sehe ich aber auch so. Möglich wäre es durchaus gewesen.

Popov 28. Mär 2015 18:52

AW: Innere Struktur von TStrings / TMemo
 
Zitat:

Zitat von Sir Rufo (Beitrag 1295154)
Wie sollte denn das Speichern von Objekten bei einem Memo funktionieren?

Richtig, es ist nicht sinnvoll implementierbar ... darum hat man es sich verkniffen irgendeinen Quatsch zu implementieren.

Falls jemand da aber eine zündende Idee hat, immer her damit.

Zuerst, ich gebe dir zuerst mal Recht (unabhängig dessen was jaenicke geschrieben hat, das ist aber ein anderes Thema).

Auf der anderen Seite, und da muss ich mal zugeben, dass ich mich inzwischen selbst bisschen blöd vorkomme, stellt sich mir die Frage wieso wir darüber überhaupt diskutieren? Ich mache mal ein Beispiel: User1 sagt: "Der Smart ist ein schönes Auto, man kann damit wunderbar in der Stadt fahren und findet leicht Parkplätze. Hat aber wenig PS." Darauf antwortet User2: "In der Stadt braucht man auch nicht viel PS." Woraus User3 antwortet: "Wieso sollte man den Smart in der Landwirtschaft als Tragtorersatz einsetzten. Dafür fehlen ihm die PS und das Gewicht und die Räder." Darauf erwidert User2: "Der Smart ist auch ein Stadtauto." Wozu User3 wieder sagt: "Es ist absolut unsinnig den Smart als Traktor zu nehmen. Dafür ist er absolut ungeeignet."

Sonderbarerweisen hat niemand unrecht, aber warum redet man plötzlich über Traktoren?


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:49 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