Autor Beitrag
oPPi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 66

MS Win 7 Pro, WinXP Pro
D3 Pro, TurboDelhi, Kylix 3 Pro
BeitragVerfasst: Di 22.10.02 22:16 
Hallo,

ich möchte die gesammte Anzahl eines bestimmten Zeichens (z.B. "E") in einem String (Memo1.Text) ermitteln. Ich habe ein Memofeld, ein Editfeld für die Eingabe des zu suchenden Zeichens u. ein Label für die Ausgabe der Anzahl.

Ich hab jetzt schon die Hilfe u. hier im Forum rumgesucht aber Length u. Pos haben mir nicht so recht weitergeholfen. Wie ich die Anzahl aller Zeichen in einem String ermittle das hab ich.

Anzahl aller Zeichen:
ausblenden Quelltext
1:
2:
3:
4:
var
Zeichen : Integer;
...
Zeichen := Length(Memo1.Text);


Kann mir jemand mal auf die Sprünge helfen? :autsch:

Gruß
oPPi

_________________
... Manchmal kommt man nicht auf die einfachsten Sachen obwohl
die Lösung ganz nah liegt ...
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 22.10.02 22:37 
Mit einer for-Schleife durch den Text gehen und mit if jedes Zeichen mit vergleichen und wenn es übereinstimmt einen Zähler erhöhen.
Popov
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mi 23.10.02 00:02 
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  Temp: String;
  e, i: Integer;
begin
  e := 0;
  Temp := Memo1.Text;
  for  i:= 1 to Length(Temp) do if UpperCase(Temp[i]) = 'E' then Inc(e);
  ShowMessage(Format('"e" kütt %d mal vor', [e]))
end;


Et kütt wie et kütt :wink:
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Mi 23.10.02 15:30 
Darf ich fragen, warum du UpperCase benutzt? Damit wird in diesem Fall nur unnötig Rechenzeit verbraucht: Du holst dir mit Temp[i] einen Char. Diesen muss Delphi nun automatisch in einen String umwandeln, der dan an UpperCase übergeben wird. Diesen Umwandlungsprozess kann man sich sparen indem man die Funktion UpCase einsetzt, die für Char gedacht ist.

ausblenden Quelltext
1:
for  i:= 1 to Length(Temp) do if UpCase(Temp[i]) = 'E' then Inc(e);					

_________________
Ist Zeit wirklich Geld?
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mi 23.10.02 15:55 
Hi!

Folgende Funktion könnte bei langen Strings eine bessere Laufzeit haben:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
function anzahl (text : STRING; zeichen : CHAR) : Integer;
VAR position : INTEGER;
begin
  position:=Pos(zeichen,text);
  if position=0 then result:=0 else
  result:=1+anzahl(Copy(text,position+1,Length(text)-position),zeichen);
end;


MfG,
Peter

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Popov
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mi 23.10.02 19:15 
@AndyB

Schande über mich. UpCase kannte ich noch nicht. Hab gerade festgestellt, daß es die Funktion schon seit mindesten Delphi 1 gibt. Hab bis jetzt noch nie nur ein Zeichen konvertiert. Wieder was gelernt.

Allerdings sehe ich hier nicht ein Problem. Forumsantworten dürfen kleinere Fehler enthalten. Das hier ist schließlich keine Schule, sondern ein Platz wo man Ansätze für Lösungen bietet. Ist meine Definition von "Programmieren ist mehr als Copy&Paste."
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Mi 23.10.02 20:37 
Popov hat folgendes geschrieben:
Allerdings sehe ich hier nicht ein Problem.

Ich auch nicht.

Popov hat folgendes geschrieben:
Forumsantworten dürfen kleinere Fehler enthalten.

Dein Code enthält keine Fehler.

Popov hat folgendes geschrieben:
... sondern ein Platz wo man Ansätze für Lösungen bietet.

... und Alternativen bzw. Verbesserungsvorschläge bringen kann.

_________________
Ist Zeit wirklich Geld?
oPPi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 66

MS Win 7 Pro, WinXP Pro
D3 Pro, TurboDelhi, Kylix 3 Pro
BeitragVerfasst: Mi 23.10.02 22:36 
Hallo,

@Popov
Dein Code funzt einwandfei.

@AndyB
Dein Code ist auch einwandfei und dazu noch schneller in der Verarbeitung.

Ich hab das mal mit dem Buchstaben 'A' probiert:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
g,w,z : Double;
p,s : String;
---
z := Length(Memo1.Text);
  p:= Format('%d', [e]);
  txt_gesZeich.Text := p;
  w := 100;
  g := StrToFloat(p) * w / z;
  Memo_Prozent.Lines.Add('A = ' + FloatToStr(rund(g,2)) + ' %');


Jetzt hab ich noch ne Frage. Wie kann ich automatisieren das er alle Zeichen (a-z, A-Z) überprüft und mir die Werte in einem Memo anzeigt?

Das ganze soll wenns fertig ist ne Häufigkeitsanalyse werden als Ergänzung zu [url]www.auq.de/viewtopic.php?t=3229[/url]

Gruß
oPPi

_________________
... Manchmal kommt man nicht auf die einfachsten Sachen obwohl
die Lösung ganz nah liegt ...
Popov
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mi 23.10.02 23:32 
Du wirst deine Probleme haben da wo du lernst. Das was du wissen willst ist eigentlich nur noch einfaches Pascal mit zwei Gastkomponenten. Wenn du hier bereits Probleme hast, dann hast du später noch mehr.

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
function Anzahl(Ch: Char): Integer;
var
  Temp: String;
  e, i: Integer;
begin
  e := 0; 
  Temp := Form1.Memo1.Text;
  for  i:= 1 to Length(Temp) do if UpCase(Temp[i]) = Ch then Inc(e);
  Result := e;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  Str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
  i, a: Integer;
begin
  for i := 1 to Length(Str) do begin
    a := Anzahl(Str[i]);
    ListBox1.Items.Add(Format('"%s" kommt %d mal vor', [Str[i], a]));
  end;
end;


Deinen Code hab ich nicht hinzugefügt. Das kannst du alleine machen. Wenn du Unterscheid machst zwischen groß und klein, dann mußt du daß bereits bei denem ersten Postig sagen. Entferne einfach UpCase und erweitere Str um die Kleinbuchstaben.
oPPi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 66

MS Win 7 Pro, WinXP Pro
D3 Pro, TurboDelhi, Kylix 3 Pro
BeitragVerfasst: Do 24.10.02 06:21 
Hallo,

ich weiß wo meine Schwächen sind :( , ich habe Probleme mit Arrays u. den For-Schleifen und dieses umzusetzen. Mir liegt eigentlich auch mehr das Technische (Hardware usw.). Ein richtiger Programmierer werd ich woll nicht werden, aber für den Hausgebrauch reicht mir das schon. Und man lernt außerdem nie aus. Wenn ich einen Quellcode sehe wie er arbeitet dann verstehe ich auch wie ich das dann für die Zukunft umsetzten kann, aber wenn ich irgendwas hingeschmissen bekomme u. es heißt mach mal u. der jenige kann selbst keine Ratschläge oder Tipps geben wie man was eventuell verbessern kann, dann biste halt am Verzweifeln. Ich arbeite jetzt mit Delphi seit Ende letzten Jahres, das was ich bislang kann hab ich mir selber beigebracht, in der Schule haben wir nur den oberflächlichen Kram in VB,VBA,Java gemacht aber so richtig rein in die Materie .... gings nie :cry:

Also nichts für ungut Popov, ich danke dir sehr für deine Hilfe u. deine Worte werd ich mir zu Herzen nehmen u. mich noch mehr mit den Arrays u. For-Schleifen befassen.

Gruß
oPPi

_________________
... Manchmal kommt man nicht auf die einfachsten Sachen obwohl
die Lösung ganz nah liegt ...
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 24.10.02 06:55 
Popov hat folgendes geschrieben:
UpCase kannte ich noch nicht. Hab gerade festgestellt, daß es die Funktion schon seit mindesten Delphi 1 gibt.

Eigentlich gab´s die schon seit TurboPASCAL für DOS. :roll:
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 24.10.02 08:09 
Peter Lustig hat folgendes geschrieben:
Folgende Funktion könnte bei langen Strings eine bessere Laufzeit haben

Die Laufzeit spielt keine große Rolle. Ich habe mal eben popovs Funktion (mit Andys Bearbeitung), meine eigene Funktion und deine an einer Textdatei mit 8.443 Bytes ausprobiert. Eine größere habe ich auf die Schnelle nicht gefunden, mache ich aber auch noch. Die Unterschiede sind -wie die Teuerungsrate durch den Euro- nur "subjektiv fühlbar" :wink:

Allerdings unterschlägt deine Funktion ein paar Zeichen, was sich im direkten Vergleich nachweisen lässt:
ausblenden volle Höhe 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:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
function CalcChar(const szInString: AnsiString;
  const sChar: char): integer;
var
  pSrc : pchar;
begin
  Result := 0; if(length(szInString) = 0) then exit;

  pSrc   := pointer(szInString);
  if(pSrc = nil) or (pSrc^ = #0) then exit;

  while(pSrc^ <> #0) do
    begin
      if(UpCase(pSrc[0]) = UpCase(sChar)) then inc(Result);
      inc(pSrc);
    end;
end;

function peter(text: STRING; zeichen: CHAR): integer;
VAR
  position : INTEGER;
begin
  position := Pos(zeichen,text);
  if position = 0 then result := 0
    else result := 1 + peter(Copy(text,position+1,Length(text)-position),zeichen);
end;

function popov(temp: string; zeichen: char): integer;
var
  i: Integer;
begin
  Result := 0;
  for i  := 1 to length(temp) do
    if(upcase(temp[i]) = Upcase(zeichen)) then inc(Result);
end;

procedure TForm1.Button7Click(Sender: TObject);
var
  s : string[1];
begin
  s := InputBox('Buchstabensuche','Geben Sie den Buchstaben an','A');
  ShowMessage(
  Format('Der Buchstabe %s wurde von meiner Funktion %d mal gefunden,' + #13#10 +
    'von Peters Funktion %d mal,' + #13#10 + 'und von popovs Funktion %d mal.',
    [s[1],
     CalcChar(Memo1.Lines.Text,s[1]),
     peter(Memo1.Lines.Text,s[1]),
     popov(Memo1.Lines.Text,s[1])]));
end;

Bei besagter Datei erschien dann folgendes Ergebnis:
Zitat:
Der Buchstabe e wurde von meiner Funktion 1010 mal gefunden,
von Peters Funktion 994 mal,
und von popovs Funktion 1010 mal.

Da solltest du noch mal nachschauen.

Gruß,
Mathias.

< ---------------- >

Nachtrag:

Ich habe das gleiche noch mal mit der "readme.txt" von Delphi5 probiert (57.332 Bytes). Die Ergebnisse lassen sich anhand der geposteten Funktionen ja nachvollziehen:
Zitat:
Der Buchstabe e wurde von meiner Funktion 6887 mal gefunden,
von Peters Funktion 6466 mal,
und von popovs Funktion 6887 mal.

Die Ticks (ermittelt mit "GetTickCount"):
ausblenden Quelltext
1:
2:
3:
6638878 : 6638879  // meine Funktion
6638879 : 6640359  // Peters Funktion
6640359 : 6640364  // popovs Funktion

Bei einem zweiten Durchlauf waren z.B. die Tickwerte von popovs Funktion besser (aber die würde ich hier natürlich nicht präsentieren. :wink:).
Bei Peters Funktion musste ich (wg. der Rekursion) ein bisschen mit einer Bool-Variablen tricksen, sonst wäre der Startwert bei jedem Aufruf der Funktion neu gesetzt worden. Und das hätte das Ergebnis wohl ... na, sagen wir mal: leicht verfälscht. :roll:

Mein Fazit wäre, dass meine und popovs Funktion auch bei größeren Dateien recht flott ist, während Peters Ansatz dann doch langsam an Boden verliert.

Wer SELFHTML8 hat, findet im Ordner "/dhtml/modelle/anzeige" die Datei "woerterbuch.txt" mit einer Größe von 62.517k. Das TMemo lädt diese Datei zwar nicht mehr vollständig, zeigt aber die Tickunterschiede noch besser auf. Damit wird wohl auch meine eben gemachte Behauptung über Peters Funktion gestützt.
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 24.10.02 09:51 
Ich nehme alles zurück, Peter. :oops:
MathiasSimmack hat folgendes geschrieben:
Da solltest du noch mal nachschauen.

Da sollte wohl besser ich nachschauen, denn deine Funktion sucht ja das Zeichen ohne Konvertierung via "UpCase". Übergibt man die entsprechend geänderten Funktionsparameter, stimmt das Ergebnis natürlich auch bei dir überein.

:idea: