Autor Beitrag
Hennar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 16.09.10 19:17 
Hallo Zusammen,
Wir sollen ein Programm schreiben, das in einem MemoText alle Buchstaben zählt und diese dann in eine vorher erstellte Tabelle einträgt. Beispiel:
MemoText: Hallo Welt
Tabelle :
Buchstabe Häufigekit
A = 1
L = 3
usw.

Für das a hb ich das wie folgt gelöst:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm1.BBuchstabenstatistikClick(Sender: TObject);
var i, n, anzahl :integer;
    text:string;


begin
   SGTabelle.Cells[0,0]:='Buchstabe';
   SGTabelle.Cells[1,0]:='Häufigkeit';
   For i:=0 to 26 do begin
      SGTabelle.Cells[0,i+1]:=char(i+65);
   end;
  //  Buchstaben zählen (erstmal nur "a"
  text:=memo1.Text;

  For i:=1 to length(text) do begin
        if text[i]=char(65then
        anzahl:=anzahl+1;
        SGTabelle.Cells[1,1]:=inttostr(anzahl);
  end;

end


Nur wollte ich vermeiden 26 bzw. 52 (Groß und Kleinschreibung) If-ABfragen zu schreiben.
Nur weiß ich leider nicht wie ich das lösen könnte, da ja auch noch der Eintrag in den richtigen
Punkt der Tabelle erfolgen muss.
Schonmal vielen Dank im Voraus,
Gruß Hennar
platzwart
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1054
Erhaltene Danke: 78

Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
BeitragVerfasst: Do 16.09.10 19:28 
Ein Array für die Häufigkeit der Buchstaben:

ausblenden Delphi-Quelltext
1:
2:
var
 count: array[0..25of Integer;


Das Zählen geht in einer Schleife:
ausblenden Delphi-Quelltext
1:
2:
For i:=1 to Length(text) do
 Inc(count[Ord(text[i])-65]);

_________________
Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 16.09.10 19:36 
Mal so als Idee, damit man sich die Rechnerei spart.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var anz: Array[AnsiChar] of Integer;
    i: integer;
    s: AnsiString;
    c: AnsiChar;

    // Array Nullen
    for c := low(AnsiChar) to high(AnsiChar) do
        anz[c] := 0;

    // Buchstaben zählen
    for i := 1 to length(s) do
        inc(anz[s[i]]);


Dann musst du nur nach das Array anz im Grid anzeigen lassen. :)

_________________
We are, we were and will not be.
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Do 16.09.10 19:37 
Hallo,
schreibe doch das Ganze mit einem Array:

ausblenden Delphi-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:
procedure TForm1.BBuchstabenstatistikClick(Sender: TObject);
var 
  i, j : integer;
  Anzahl : Array[65..91of longint;  // longint wegen möglicherweise sehr großer Texte

begin
   SGTabelle.Cells[0,0]:='Buchstabe';
   SGTabelle.Cells[1,0]:='Häufigkeit';
   For i:=0 to 26 do begin
      SGTabelle.Cells[0,i+1]:=char(i+65);
   end;
  
  for i:=65 to 91 do 
    Anzahl[i]:=0// Leeren des Arrays

  For i:=1 to length(Memo1.text) do 
  begin
    j := Ord(UpperCase(Memo1.text[i]));
    if j in [65..91then 
      inc(Anzahl[j]);
  end;

// Ausgabe

  for i:=65 to 91 do 
  begin
     SGTabelle.Cells[1,i-64]:=IntToStr(Anzahl[i])
  end;

end


das sollte funktionieren,

Gruß

Gunther
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 16.09.10 20:05 
Hallo Gunther und die anderen vielen Dank schonmal, haben in Informatik nur noch nie mit Arrays gearbeitet, aber ich werd mich mal einlesen.
Beim Compilieren gibt er nur leider folgende Fehlermeldung aus :
[Pascal Fehler] Unit1.pas(59): E2008 Inkompatible Typen
Das ist die Zeile :
ausblenden Delphi-Quelltext
1:
j := Ord(UpperCase(Memo1.text[i]));					

Weiß jemand warum ?
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Do 16.09.10 20:10 
Mag sein, dass der Text, selbst indiziert, nicht als char interpretiert wird, schreibe dann das nach Konvertierung, wie Du es geschrieben hattest:

s := Uppercase(Memo1.Text);

und ...


j := Ord(s[i]);
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 16.09.10 20:25 
Verzeiht mir meine Unwissenheit. Vielleicht steh ich auch gerade nur auf'm Schlauch,
aber wo muss ich die beiden Sachen genau einfügen ?

Und bei s := Uppercase(Memo1.Text);
kommt immer die Fehlermeldung:
[Pascal Fehler] Unit1.pas(59): E2003 Undefinierter Bezeichner: 's'
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Do 16.09.10 21:53 
Die Sache mit den Arrays ist zwar richtig, aber vielleicht ein wenig viel auf einmal.
Versuchen wir es hiermit:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
// Auf 'A' prüfen
if text[i]=char(65then
  anzahl := StrToIntDef(SGTabelle.Cells[1,1],0); // Steht nix drin => 0 liefern, sonst die Anzahl
  anzahl := anzahl + 1;
  SGTabelle.Cells[1,1] := inttostr(anzahl);
end;

// Auf 'B' prüfen
if text[i]=char(65then
  anzahl := StrToIntDef(SGTabelle.Cells[1,2],0); // Steht nix drin => 0 liefern, sonst die Anzahl
  anzahl := anzahl + 1;
  SGTabelle.Cells[1,2] := inttostr(anzahl);
end;

Die beiden Blöcke sind ja fast identisch. Entweder schreiben wir uns eine eigene Prozedur, die zu einem beliebigen Buchstaben im Grid eins dazuaddiert oder wir machen das direkt im Code.

Also:
Wenn der Buchstabe die Ordnungszahl 65 hat, dann ändern wir die Zelle #1
Wenn der Buchstabe die Ordnungszahl 66 hat, dann ändern wir die Zelle #2
...
Merkste wat?
Wenn der Buchstabe die Ordnungszahl N hat, dann ändern wir die Zelle #(N-64)

Nächster Versuch
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Buchstabe := text[i]; // 'Buchstabe' musst Du deklarieren. Als... welcher Datentyp?
Buchstabe := Upcase(Buchstabe);
Buchstabe_Ordnungszahl := Ord(Buchstabe);  // Auch deklarieren... Als?
Index_Im_StringGrid := Buchstabe_Ordnungszahl - 64// Auch deklarieren... Als?
If Index_Im_StringGrid in [1..26Then Begin
  anzahl := StrToIntDef(SGTabelle.Cells[1,Index_Im_StringGrid],0); 
  anzahl := anzahl + 1;
  SGTabelle.Cells[1,Index_Im_StringGrid] := inttostr(anzahl);
end;

_________________
Na denn, dann. Bis dann, denn.
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 16.09.10 22:21 
Erst einmal vielen Dank, der Support hier ist echt Super :D
@alzaimar:
Bin halt noch totaler Anfänger, aber ich hoffe ich habs dank dir verstanden :)
Müsste ich also Buchstabe als String
Buchstabe_Ordnungszahl als Integer
Buchstabe_Im_Stringgrid als Integer
deklarieren ?
Noch eine andere Frage, was bedeutedt das Upcase ?

Gruß Hennar
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Do 16.09.10 22:29 
Ist ein Buchstabe denn eine Zeichenkette (=String) oder doch nur ein einzelnes Zeichen?
Das 'Upcase' ist eine in Delphi eingebaute Funktion, die ein Zeichen in einen Großbuchstaben umwandelt.
Du hast ja vielleicht auch Kleinbuchstaben im Text. Die Abfrage, ob dieser Index 'in [1..26]' ist, prüft eigentlich, ob da ein Buchstabe oder ein Zeichen (z.B. ein Punkt, Komma, Leerzeichen usw.) steht.

Der Rest von Dir ist richtig.

Wichtig ist, das Du es verstehst.

_________________
Na denn, dann. Bis dann, denn.
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 16.09.10 22:33 
Ok, das mit dem String stimmt, ein Blick auf die Uhr erklärt vielleicht einiges :roll: :lol:
Und Upcase hab ich jetzt auch verstanden, sehr nützlich. :D
Dann hab ich soweit ich das jetzt überlicken kann, alles verstanden.
Ist halt nur schwer so ein Programm zu schreiben (ist das aller erste),
wenn einem vorher nichtmal gesagt wird das es etwas wie ein array gibt, aber naja, schule halt.
Falls ich noch weitere Probleme hab werd ich mich melden.
Vielen Dank :)
Hennar

Tante Edit sagte mit gerade:
[Pascal Fehler] Unit1.pas(64): E2003 Undefinierter Bezeichner: 'Index_Im_StringGrid'

Versteh gerade nicht wo er da ein Problem hat ?
platzwart
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1054
Erhaltene Danke: 78

Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
BeitragVerfasst: Do 16.09.10 23:29 
Undefinierter Bezeichner bedeutet immer, dass du vergessen hast, eine Variable zu deklarieren. Welche das ist, steht hinter dem Doppelpunkt der Fehlermeldung ;)

_________________
Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 16.09.10 23:48 
Achso ok,
ich dachte es gibt da noch ein unterschied zu "nicht deklariert", danke ;)
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Fr 17.09.10 07:21 
Hab Index_Im_SringGrid auch nochmal deklariert.
Programm startet jetzt auch. Allerdings zählt es nur die kleinen "a"'s und nicht die großen und auch keine anderen Buchstaben.
Und wie ich gerade merke zählt es aucvh nur bis 1, egal ob in der zeile noch 4 kleine a's sind.
Desweiteren zählt es diese auch nur, wenn im Feld noch Memo1 steht.
Das ist der aktuelle Code :
ausblenden Delphi-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:
procedure TForm1.BBuchstabenstatistikClick(Sender: TObject);
var i:integer;
    Buchstabe:char;
    text:string;
    Buchstabe_Ordnungszahl:integer;
    Buchstabe_Im_StringGrid:integer;
    anzahl:integer;
    Index_Im_StringGrid:integer;

    // Tabelle anlegen :

begin
   SGTabelle.Cells[0,0]:='Buchstabe';
   SGTabelle.Cells[1,0]:='Häufigkeit';
   For i:=0 to 26 do begin
      SGTabelle.Cells[0,i+1]:=char(i+65);
   end;
  //  Buchstaben Zählen
   text:=memo1.Text;
   Buchstabe := text[i]; 
   Buchstabe := Upcase(Buchstabe);
   Buchstabe_Ordnungszahl := Ord(Buchstabe);  
   Index_Im_StringGrid := Buchstabe_Ordnungszahl - 64
     If Index_Im_StringGrid in [1..26Then Begin
        anzahl := StrToIntDef(SGTabelle.Cells[1,Index_Im_StringGrid],0);
        anzahl := anzahl + 1;
        SGTabelle.Cells[1,Index_Im_StringGrid] := inttostr(anzahl);
     end;
end;
Tilo
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 1098
Erhaltene Danke: 13

Win7 geg. WInXP oder sogar Win98
Rad2007
BeitragVerfasst: Fr 17.09.10 10:22 
Hallo Hennar,

guck Dir deinen Code doch mal genauer an,
Du iterierst nicht durch das Memo.

ausblenden volle Höhe Delphi-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:
procedure TForm1.BBuchstabenstatistikClick(Sender: TObject);
var i:integer;
    Buchstabe:char;
    text:string;
    Buchstabe_Ordnungszahl:integer;
    Buchstabe_Im_StringGrid:integer;
    anzahl:integer;
    Index_Im_StringGrid:integer;

    // Tabelle anlegen :

begin
   SGTabelle.Cells[0,0]:='Buchstabe';
   SGTabelle.Cells[1,0]:='Häufigkeit';
   //Ausgabe der Buchstaben Liste
   For i:=0 to 26 do begin
      SGTabelle.Cells[0,i+1]:=char(i+65);
   end;
   // i hat hier (vermutlich) den wert 26 oder 27
  //  Buchstaben Zählen
   text:=memo1.Text;
   // in Text steht der gesamte Memoinhalt
   Buchstabe := text[i]; 
   // in Buchstabe steht nun der i. Buchstabe
   Buchstabe := Upcase(Buchstabe);
   Buchstabe_Ordnungszahl := Ord(Buchstabe);  
   Index_Im_StringGrid := Buchstabe_Ordnungszahl - 64
     If Index_Im_StringGrid in [1..26Then Begin
     //falls index des i. Buchstaben >=1 && <=26 dann erhöhe Anzahl
        anzahl := StrToIntDef(SGTabelle.Cells[1,Index_Im_StringGrid],0);
        anzahl := anzahl + 1;
        SGTabelle.Cells[1,Index_Im_StringGrid] := inttostr(anzahl);
     end;
end;


Du must zwischen text:=memo1.Text und Buchstabe:=text[i] noch einen Schleifenkopf einbauen der i von 1 bis Anzahl der Zeichen im Text durchiteriert.
Der Schleifenkörper geht dann von Buchstabe:=Test[i] bis Procedure Ende.

Der Code ist aber langsam, da Du für jeden einzelne Buchstabenposition im Text die Ausgabe aktualisierst. Wenn Du nicht im Threads arbeitest sieht der Anwender das aber nicht. Der Code wird effektiver wenn Du die Verarbeitung von der Ausgabe trennst.
Der BeispielCode von Gausi zum Beispiel ermittelt nur das Vorkommen der Buchstaben. Dadurch spart er sich das ständige Umformen mit StrToIntDef und inttostr.
Wenn der Text 10 Mio Zeichen hat führst Du diese Tranformationen 10 Mio mal aus. Bei Gausi's Code muss die Umwandlung maximal 256 mal durchgeführt werden, Jenachdem für welche (und damit wieviele) Buchstaben die Information gewünscht ist. Jeder Vergleich (hier: if Index_Im_StringGrid in [1..26] Then) und jede Umformung kostet (wenn heute im Privatbereich kaum spürbar) Rechenzeit. Im Vergleich dazu ist ein inc(Array[index]) (im Allgemeinen) um einiges schneller.
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Fr 17.09.10 21:13 
Zitat:
Der Code ist aber langsam

Ich würd ihn trotzdem erstmal versuchen, kann ihn danach ja noch verbessern.
Leider muss ich schon wieder sagen, dass ich gerade nicht weiß wie ich das mit dem
durchiterieren machen soll.
For schleife wahrscheinlich ?! Aber wie muss ich die schreiben ?
Georg08
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 155
Erhaltene Danke: 6

Win XP
Delphi 7.0 Personal
BeitragVerfasst: Fr 17.09.10 22:17 
Ich hab den Thread hier grade entdeckt...
Ich hab vor ein paar Monaten mal was geschreiben. Habs in den Anhang gelegt. Es zählt die Buchstaben und schreibt sie in ein TListView...
Einloggen, um Attachments anzusehen!
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Fr 17.09.10 23:04 
Bin ich also nicht der einzige der das macht.
Nur würd ich lieber bei meinem Code bleiben damit ich es verstehe,
aber vielen Dank, habs mir eben mal angeguckt und gewisse paraleln sind doch da ;)
Hennar Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: So 19.09.10 14:13 
Kann mir keiner das mit der For-schleife erklären,
wie ich die wo schreiben muss ?
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: So 19.09.10 15:39 
Du musst das Memo durchgehen, so in etwa:
P.S. habe ausserdem eine Zeile eingefügt, die alle Zahlen im Stringgrid erstmal auf "0" setzt

ausblenden volle Höhe Delphi-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:
procedure TForm1.BBuchstabenstatistikClick(Sender: TObject);
var i,n:integer;
    Buchstabe:char;
    text:string;
    Buchstabe_Ordnungszahl:integer;
    Buchstabe_Im_StringGrid:integer;
    anzahl:integer;
    Index_Im_StringGrid:integer;

    // Tabelle anlegen :

begin
   SGTabelle.Cells[0,0]:='Buchstabe';
   SGTabelle.Cells[1,0]:='Häufigkeit';
   For i:=0 to 26 do begin
      SGTabelle.Cells[0,i+1]:=char(i+65);
      SGTabelle.Cells[1,i+1] := '0';
   end;
   text:=memo1.Text;
   for n := 1 to length(text) do
   begin
     //  Buchstaben Zählen
     Buchstabe := text[n];
     Buchstabe := Upcase(Buchstabe);
     Buchstabe_Ordnungszahl := Ord(Buchstabe);
     Index_Im_StringGrid := Buchstabe_Ordnungszahl - 64;
       If Index_Im_StringGrid in [1..26Then Begin
          anzahl := StrToIntDef(SGTabelle.Cells[1,Index_Im_StringGrid],0);
          anzahl := anzahl + 1;
          SGTabelle.Cells[1,Index_Im_StringGrid] := inttostr(anzahl);
       end// if
   end;  // for n

end;


P.S. am besten früh angeöhnen: hinter jedes end; schreiben, wozu es gehört, das erleichtert die Arbeit ungemein :)

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)