Autor |
Beitrag |
Hennar
      
Beiträge: 19
|
Verfasst: 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:
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; text:=memo1.Text;
For i:=1 to length(text) do begin if text[i]=char(65) then 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
      
Beiträge: 1054
Erhaltene Danke: 78
Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
|
Verfasst: Do 16.09.10 19:28
_________________ Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Do 16.09.10 19:36
Mal so als Idee, damit man sich die Rechnerei spart.
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;
for c := low(AnsiChar) to high(AnsiChar) do anz[c] := 0;
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
      
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: Do 16.09.10 19:37
Hallo,
schreibe doch das Ganze mit einem Array:
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..91] of longint; 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; For i:=1 to length(Memo1.text) do begin j := Ord(UpperCase(Memo1.text[i])); if j in [65..91] then inc(Anzahl[j]); end;
for i:=65 to 91 do begin SGTabelle.Cells[1,i-64]:=IntToStr(Anzahl[i]) end;
end |
das sollte funktionieren,
Gruß
Gunther
|
|
Hennar 
      
Beiträge: 19
|
Verfasst: 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 :
Delphi-Quelltext 1:
| j := Ord(UpperCase(Memo1.text[i])); |
Weiß jemand warum ?
|
|
Tranx
      
Beiträge: 648
Erhaltene Danke: 85
WIN 2000, WIN XP
D5 Prof
|
Verfasst: 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 
      
Beiträge: 19
|
Verfasst: 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
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: 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:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| if text[i]=char(65) then anzahl := StrToIntDef(SGTabelle.Cells[1,1],0); anzahl := anzahl + 1; SGTabelle.Cells[1,1] := inttostr(anzahl); end;
if text[i]=char(65) then anzahl := StrToIntDef(SGTabelle.Cells[1,2],0); 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
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| Buchstabe := text[i]; Buchstabe := Upcase(Buchstabe); Buchstabe_Ordnungszahl := Ord(Buchstabe); Index_Im_StringGrid := Buchstabe_Ordnungszahl - 64; If Index_Im_StringGrid in [1..26] Then 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 
      
Beiträge: 19
|
Verfasst: Do 16.09.10 22:21
Erst einmal vielen Dank, der Support hier ist echt Super
@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
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: 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 
      
Beiträge: 19
|
Verfasst: Do 16.09.10 22:33
Ok, das mit dem String stimmt, ein Blick auf die Uhr erklärt vielleicht einiges
Und Upcase hab ich jetzt auch verstanden, sehr nützlich.
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
      
Beiträge: 1054
Erhaltene Danke: 78
Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
|
Verfasst: 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 
      
Beiträge: 19
|
Verfasst: Do 16.09.10 23:48
Achso ok,
ich dachte es gibt da noch ein unterschied zu "nicht deklariert", danke 
|
|
Hennar 
      
Beiträge: 19
|
Verfasst: 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 : 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;
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; 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..26] Then Begin anzahl := StrToIntDef(SGTabelle.Cells[1,Index_Im_StringGrid],0); anzahl := anzahl + 1; SGTabelle.Cells[1,Index_Im_StringGrid] := inttostr(anzahl); end; end; |
|
|
Tilo
      
Beiträge: 1098
Erhaltene Danke: 13
Win7 geg. WInXP oder sogar Win98
Rad2007
|
Verfasst: Fr 17.09.10 10:22
Hallo Hennar,
guck Dir deinen Code doch mal genauer an,
Du iterierst nicht durch das Memo.
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;
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; 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..26] Then Begin 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 
      
Beiträge: 19
|
Verfasst: 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
      
Beiträge: 155
Erhaltene Danke: 6
Win XP
Delphi 7.0 Personal
|
Verfasst: 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 
      
Beiträge: 19
|
Verfasst: 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 
      
Beiträge: 19
|
Verfasst: So 19.09.10 14:13
Kann mir keiner das mit der For-schleife erklären,
wie ich die wo schreiben muss ?
|
|
Tilman
      
Beiträge: 1405
Erhaltene Danke: 51
Win 7, Android
Turbo Delphi, Eclipse
|
Verfasst: 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
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;
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 Buchstabe := text[n]; Buchstabe := Upcase(Buchstabe); Buchstabe_Ordnungszahl := Ord(Buchstabe); Index_Im_StringGrid := Buchstabe_Ordnungszahl - 64; If Index_Im_StringGrid in [1..26] Then Begin anzahl := StrToIntDef(SGTabelle.Cells[1,Index_Im_StringGrid],0); anzahl := anzahl + 1; SGTabelle.Cells[1,Index_Im_StringGrid] := inttostr(anzahl); end; end; 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)
|
|
|