Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi String buchstabenweise in array einlesen (https://www.delphipraxis.net/161016-string-buchstabenweise-array-einlesen.html)

basti2011 12. Jun 2011 19:07

String buchstabenweise in array einlesen
 
Hallo,
Ich würde gerne in ein dyn. Array einen string einlesen und zwar buchstabenweise.
Anschließend soll ein buchstabe in ein edit feld eingegeben werden und eine procedure gibt aus wie oft dieser buchstabe in dem oben eingelesenen array vorkommt.

Momentan bin ich beim einlesen in das array soweit :
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var i,laenge :integer;
    wort :string;
    BS_array: array of string;
begin
 wort := edit1.text;
 laenge := Length(wort);
 Setlength(BS_array,laenge);
 For i := 1 to (laenge-1) do
  begin
   BS_array[1] := wort;  // ich nehme an in diesem Bereich brauch ich einen befehl der den string zerlegt und damit einzelne Stellen belegt
  end;

Danke im Vorraus ! :wink:

Luckie 12. Jun 2011 19:12

AW: String buchstabenweise in array einlesen
 
Du kannst die einzelnen Zeichen einer Zeichenkette über den Index ansprechen. Zu beachten ist dabei, dass der erste Buchstabe den Index eins hat: wort[1] gibt dir das erste Zeichen zurück.

Dynamische Arrays sind immer null-basierend.

Warum machst du das Array so lang wie das Wort und nutzt dann nur das erste Element: BS_array[1] := wort;

basti2011 12. Jun 2011 19:19

AW: String buchstabenweise in array einlesen
 
Ja es scheitert nur daran dass mir die Idee fehlt wie ich jeden einzelnen Buchstaben ( ich weiß ja vorher nicht wie viele es sind)
einzeln in das array schreibe.



Im selben Zug muss ja auch dann ein bestimmter Buchstabe gesucht werden und gleichzeitig soll mitgezählt werden wie oft er existiert.

s.h.a.r.k 12. Jun 2011 19:34

AW: String buchstabenweise in array einlesen
 
Delphi-Quellcode:
function StrToArray(Value: String): TArray<Char>;
// oder: function StrToArray(Value: String): array of Char;
var
  L : Integer;
  C : Char;
  i : Integer;
begin
  L := Length(Value);
  SetLength(Result, L);
  if (L > 0) then
  begin
    for i := 0 to L - 1 do
      Result[i] := Value[i + 1];
  end;
end
Eigentlich liefere ich nur sehr ungerne eine komplette Methode, da man dabei halt nichts lernt. Wichtig ist hier, wie Luckie schon gesagt hatte, dass Arrays (meist) 0-basierend sind, also der Zugriff via Index, und Strings 1-basierend.

Aber ich habe dies bzgl. auch noch eine Frage, daher die komplette Methode :stupid: Gibt es hierfür eine schnellere Methode!?

Aphton 12. Jun 2011 19:39

AW: String buchstabenweise in array einlesen
 
Diese Variante wird nicht klappen!

Berücksichtige immer, dass Neulinge nicht wirklich die neusten Delphi Versionen benutzen und dadurch auch die neuersten Sprachfeatures nicht benutzen können!
(Ne kleine Änderung würde es kompilierbar machen, aber das dann nur Seitens erfahreneren Programmierer :P)

Edit:
oder: function StrToArray(Value: String): array of Char;
Dieses array of Char; müsste zuvor als Typ deklariert werden...

juergen 12. Jun 2011 19:40

AW: String buchstabenweise in array einlesen
 
Hallo,

ich habe leider keine Ahnung von Arrays (noch nicht), könnte es mir aber so vorstellen:
Delphi-Quellcode:
 ...
For i := 0 to (laenge-1) do
   begin
    BS_array[i] := wort[i+1];
   end;
...
Edit: roter Kasten, war zu langsam

zeras 12. Jun 2011 19:41

AW: String buchstabenweise in array einlesen
 
Du musst dir irgendwo merken, wie oft ein Buchstabe vorgekommen ist. Dazu vielleicht ein Array definieren, welche sich die Anzahl merken kann. Dann ist noch zu klären, ob du Großbuchstaben anderst behandelst als Kleinbuchstaben.

Versuche es doch einmal so (nicht optimiert):

Delphi-Quellcode:
procedure TForm11.Button1Click(Sender: TObject);
var i,laenge :integer;
    wort :string;
    BS_array: array ['a'..'z'] of byte;
    c   : char;

begin
 wort := 'hallo';
 laenge := Length(wort);

 for c:=low(BS_array) to high(BS_array) do BS_array[c]:=0;


 For i := 1 to (laenge) do begin
   c := wort[i];
   BS_array[wort[i]] := BS_array[wort[i]] +1;
  end;
end;

basti2011 12. Jun 2011 20:18

AW: String buchstabenweise in array einlesen
 
Also erstmal danke für die vielen Antworten,

Ich bin im ersten Jahr und benutze momentan Delphi 7.
Daher sind mir ziemlich viele Komponenten und funktionen die genannt wurden sehr unbekannt :|

Besonders mit den Begriffen - value, high , low - kann ich nicht wirklich was damit anfangen und es ist so dass ich momentan für einen Test lerne und dieses Beispiel zur Übung bekommen hab ;)

Der genaue Aufgabenlaut wäre : Schreib ein Programm welches ein eingegebenes Wort buchstabenweise in ein dyn. Array einliest. Nach Eingabe eines Buchstabens soll ausgegeben werden wie oft dieser Buchstabe im eingegebenen Wort vorkommt.

Groß und klein Buchstaben ist vollkommen egal eigentlich es geht rein um die Funktionlität dessen was in der Angabe steht.

Also vielleicht ergibt sich noch ne "einfache" Lösungsmöglichkeit die im Grunde genommen nur ein dyn. Array, eine For - Schleife und eine Function für die Überprüfung behinhaltet , weil viel weiter sind wir mit dem Stoff nicht. :thumb:

DeddyH 12. Jun 2011 21:24

AW: String buchstabenweise in array einlesen
 
Delphi-Quellcode:
L := Length(String);
SetLength(Array, L);
for i := 1 to L do
  Array[i - 1] := String[i];
Strings beginnen mit dem Index 1, dynamische Arrays hingegen mit 0, daher muss im obigen Code von i 1 abgezogen werden. Zum Auswerten kannst Du ja dann ein statisches Array['A'..'Z']: of integer verwenden, mit 0 füllen und je Buchstaben bei Fund um 1 erhöhen. Das ist zwar immer noch case-sensitive, aber das bekommst Du schon hin, es gibt ja Wandlungsfunktionen ;)

s.h.a.r.k 12. Jun 2011 21:52

AW: String buchstabenweise in array einlesen
 
Es geht auch noch schneller :mrgreen: Zeitersparnis ist je nach Stringlänge sehr hoch:
Delphi-Quellcode:
function StrToArray(Value: String): TCharArray;
var
  L : Integer;
begin
  L := Length(Value);
  SetLength(Result, L);
  if (L > 0) then
    Move(PChar(Value)^, Result[0], L * SizeOf(Char));
end;
Hier mal ein kleiner Benchmark (QuadCore Q6600):
Code:
Rounds: 10000000

Length: 21
naive: 2428ms
optimized: 1128ms
Time Saved: 54%

Length: 168
naive: 9179ms
optimized: 1831ms
Time Saved: 80%
Eine CountDiverseChars-Methode kommt auch bald ;)

himitsu 12. Jun 2011 21:55

AW: String buchstabenweise in array einlesen
 
Zeichen zählen:

Delphi-Quellcode:
var
  Anzahl: array[Char] of Integer;
  C: Char;
  i: Integer;

for C := Low(Char) to High(Char) do
  Antahl[C] := 0;

for i := 1 to Length(Wort) do
  Anzahl[Word[i]] := Anzahl[Word[i]] + 1;
Delphi-Quellcode:
var
  Anzahl: array[Char] of Integer;
  C: Char;

FillChar(Anzahl, SizeOf(Anzahl), 0);
for C in Wort do Inc(Anzahl[C]);
nun steht zu jedem Char die Anzahl im Array drin, z.B.
Delphi-Quellcode:
AnzahlVonGroßA := Anzahl['A'];

Luckie 12. Jun 2011 22:30

AW: String buchstabenweise in array einlesen
 
Ich glaube, von solchen extremen Optimierungen sollte man eher absehen, das es hier eher um das allgemeine Verständnis geht.

basti2011 12. Jun 2011 22:30

AW: String buchstabenweise in array einlesen
 
Vielen Dank ich werds trotz eher geringem Verständnis einfach durchprobieren :thumb:

DeddyH 12. Jun 2011 23:58

AW: String buchstabenweise in array einlesen
 
Ich hatte das bewusst möglichst einfach gehalten, aber manche Egos scheinen einfach stärker zu sein :evil:

Bjoerk 13. Jun 2011 00:02

AW: String buchstabenweise in array einlesen
 
Vermutlich meint dein Lehrer lediglich das:

Delphi-Quellcode:
type
  TCharArray = array of Char;


function LowerCaseChar (const C: char): char;
begin
  Result:= C;
  if (Result in ['A'..'Z', 'Ä', 'Ö', 'Ü']) then
    Inc(Byte(Result), 32);
end;


function FindChar (const S: TCharArray; const C: char): integer;
var
  I: integer;
begin
  Result:= 0;

  for I:= 0 to Length(S)-1 do
    if S[I] = C then Inc(Result);
end;


procedure TForm1.Edit2Change(Sender: TObject);
var
  I, L1, L2, N: integer;
  C: char;
  S: TCharArray;
begin
  Label1.Caption:= '';

  L1:= Length(Edit1.Text);
  L2:= Length(Edit2.Text);

  if ((L1 > 0) and (L2 > 0)) then
  begin
    SetLength(S, L1);

    for I:= 1 to L1 do
      S[I-1]:= LowerCaseChar(Edit1.Text[I]);

    C:= LowerCaseChar(Edit2.Text[1]);

    N:= FindChar(S, C);
    Label1.Caption:= 'Buchstabe ' + C + ' kommt ' + IntToStr(N)+' mal vor.';

    SetLength(S, 0);
  end;
end;

DeddyH 13. Jun 2011 00:07

AW: String buchstabenweise in array einlesen
 
Tragt nur ruhig ein wenig mehr zur Verwirrung bei, ich halte mich jetzt da raus.

himitsu 13. Jun 2011 00:22

AW: String buchstabenweise in array einlesen
 
FillChar ist doch keine extreme Optimierung?

Und den Rest kann man sich aus jedem guten Delphi-Lehrbuch rausholen. :angle:

Gut, das For-In ist vielleicht neu und es geht nicht in vielen älternen Delphiversionen, aber zu Extremoptimiert würde ich auch das nicht zählen.


Zitat:

Zitat von zeras (Beitrag 1105992)
Versuche es doch einmal so (nicht optimiert):
Delphi-Quellcode:
procedure TForm11.Button1Click(Sender: TObject);
var i,laenge :integer;
    wort :string;
    BS_array: array ['a'..'z'] of byte;
    c   : char;

begin
 wort := 'hallo';
 laenge := Length(wort);

 for c:=low(BS_array) to high(BS_array) do BS_array[c]:=0;

 For i := 1 to (laenge) do begin
   c := wort[i];
   BS_array[wort[i]] := BS_array[wort[i]] +1;
  end;
end;

Wozu das C in der letzen Schleife, wenn es dann nicht genutzt wird?
Ich vermute mal du wolltest
Delphi-Quellcode:
BS_array[c] := BS_array[c] +1;
schreiben.

PS: gegenüber einiger anderer Codes hier ist mein Cod sogar fehlerunanfälliger.

z.B. das
Delphi-Quellcode:
array ['a'..'z'] of byte;
im gerade gezeigten Code kann zu einem Pufferüberlauf führen,
wenn in
Delphi-Quellcode:
wort
nicht nur Kleinebuchstaben von A bis Z vorkommen.
Schließlich ist fast immer die Index- und Bereichsprüfung deaktiviert.

Das Array[Char] ist beim Unicode zwar ein 1/4 MB groß, aber dafür liegen garantiert alle Zeichen irgendwo in dessen Bereich.

Luckie 13. Jun 2011 00:37

AW: String buchstabenweise in array einlesen
 
Ich bezog mich auf die Version mit dem Move.

himitsu 13. Jun 2011 01:20

AW: String buchstabenweise in array einlesen
 
achso das. :lol:

Aber wenn das schon Hochoptimiert ist, dann kenn ich etwas Höchstoptimiertes (auch wenn mich die Grammatikfreunde dafür erschlagen werden).

Delphi-Quellcode:
function StrToArray(Value: String): TCharArray;
begin
  String(Pointer(Result)) := Value; // geht zwar, also wenn man das Char-Array nur auslesen will und nicht verändert
end;
ACHTUNG:
* ich weiß was ich mache (denn ich weiß wie beide Typen intern aufgebaut sind, wie sie verwaltet werden und daß ein String eigentlich "nur" ein aufbemotztes CharArray ist)
* und ich würde jeden standrechtlich erschießen, welcher sowas produktiv einsetzt
* also macht es besser nicht nach :warn:

Stevie 13. Jun 2011 01:27

AW: String buchstabenweise in array einlesen
 
Zitat:

Zitat von DeddyH (Beitrag 1106024)
Ich hatte das bewusst möglichst einfach gehalten, aber manche Egos scheinen einfach stärker zu sein :evil:

Hätte er Delphi 2010 oder höher könnte er auch das hier machen:
Delphi-Quellcode:
  ShowMessageFmt('"%s" kommt %d mal in "%s" vor', [Edit2.Text,
    TDelegateEnumerable<Char>.Create(
      procedure
      var
        c: Char;
      begin
        for c in Edit1.Text do Yield<Char>(c);
      end).Where(
    function(c: Char): Boolean
    begin
      Result := SameText(c, Edit2.Text);
    end).Count,
    Edit1.Text]);
Sorry, ich konnte nicht widerstehen. :oops: :stupid:

Luckie 13. Jun 2011 01:30

AW: String buchstabenweise in array einlesen
 
Also, wenn ihr ihn verwirren wollt, dann habt ihr das sehr wahrscheinlich mittlerweile geschafft. :?

himitsu 13. Jun 2011 01:31

AW: String buchstabenweise in array einlesen
 
Nur noch Begin und End ersetzt und man hätte einen typischen C-Code :lol:

Stevie 13. Jun 2011 01:36

AW: String buchstabenweise in array einlesen
 
Zitat:

Zitat von Luckie (Beitrag 1106037)
Also, wenn ihr ihn verwirren wollt, dann habt ihr das sehr wahrscheinlich mittlerweile geschafft. :?

Du meinst dich, nicht ihn, oder? :twisted:

Zitat:

Zitat von himitsu (Beitrag 1106038)
Nur noch Begin und End ersetzt und man hätte einen typischen C-Code :lol:

Pff, du erkennst ja nur nicht die Kapazität und Flexibilität dieses Codes ;)

mkinzler 13. Jun 2011 09:46

AW: String buchstabenweise in array einlesen
 
Ihr seid schon komische Vögel, der Te offenbart, dass ihm das grundlegende Verständnis fehlt und ihr offenbart ihm eure "speziallösungen", die er bestimmt nicht versteht.

DeddyH 13. Jun 2011 11:33

AW: String buchstabenweise in array einlesen
 
Meine Rede :thumb:

Blup 14. Jun 2011 11:53

AW: String buchstabenweise in array einlesen
 
Einfach an die Aufgabenstellung halten, offensichtlich soll der Umgang mit dyn. Array geübt werden:
Zitat:

Schreib ein Programm welches ein eingegebenes Wort buchstabenweise in ein dyn. Array einliest.
Delphi-Quellcode:
type
  TCharDynArray = array of Char;

function StringToDynArray(const AValue: string): TCharDynArray;
begin
  // Strings beginnen bei Index 1, Arrays bei 0   => wichtiges Lernziel
  SetLength(Result, Length(AValue));
  for i := 0 to Length(Result) - 1 do
    Result[i] := AValue[i + 1];
end;
Zitat:

Nach Eingabe eines Buchstabens soll ausgegeben werden wie oft dieser Buchstabe im eingegebenen Wort vorkommt.
Delphi-Quellcode:
// Array-Parameter immer als "const" oder "var" übergeben, sonst wird beim Funktionsaufruf eine Kopie angelegt
function GetBuchstabenAnzahl(const ACharDynArray: TCharDynArray; AValue: Char): Integer;
begin
  Result := 0;
  for i := 0 to Length(ACharDynArray) - 1 do
  begin
    if ACharDynArray[i] = AValue then
      Result := Result + 1;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  a: TCharDynArray;
  s: string;
  n: Integer;
begin
  // Text der durchsucht werden soll
  s := edit1.text;
  if Length(s) = 0 then
  begin
    MessageBox('Geben Sie einen Text an der durchsucht werden soll!', Caption);
    Exit;
  end;
  a := StringToDynArray(s);

  // Buchstabe der gesucht wird
  s := edit2.text;
  if Length(s) = 0 then
  begin
    MessageBox('Geben Sie einen Buchstaben an der gesucht werden soll!', Caption);
    Exit;
  end;
 
  if Length(s) > 1 then
  begin
    MessageBox('Geben Sie nur einen Buchstaben an der gesucht werden soll!', Caption);
    edit2.text := '';
    Exit;
  end;

  n := GetBuchstabenAnzahl(a, s[1]);
  s := Format('Der Buchstabe %s ist %d mal enthalten.', [s, n]);
  MessageBox(s, Caption);
end;

Neutral General 14. Jun 2011 12:01

AW: String buchstabenweise in array einlesen
 
Zitat:

Zitat von Stevie (Beitrag 1106036)
[...]
Sorry, ich konnte nicht widerstehen. :oops: :stupid:

Der Code ist ja einfach nur .. iih :pale:
Und dazu noch inklusive Speicherleck :duck:

Stevie 14. Jun 2011 12:25

AW: String buchstabenweise in array einlesen
 
Zitat:

Zitat von Neutral General (Beitrag 1106292)
Der Code ist ja einfach nur .. iih :pale:
Und dazu noch inklusive Speicherleck :duck:

Ja, mit lambdas und linq syntax säh's schicker aus 8-)

Speicherleck stimmt, hab nicht mehr an das Problem mit Interface als Functionsergebnis gedacht, lokale Variable wär die Lösung :stupid:


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