Entwickler-Ecke

Sonstiges (Delphi) - Zählen wie oft Wort in einem Satz vorkommt (Quelltext?)


SiH - Do 24.05.07 15:23
Titel: Zählen wie oft Wort in einem Satz vorkommt (Quelltext?)
Hallo!
Ich habe ein Problem. Im Rahmen des Informatikunterrichtes sollen wir einen solchen Quelltext schreiben (s. Topic-Titel).
Bsp.:
Eingabe1: Hallo Hallo Hallo
Eingabe2: Hallo

Ausgabe: Das wort 'Eingabe 2' kommt 'xmal' in 'Eingabe 1' vor.
x in diesem Falle also 3.

Ich habe es schon mit allen mir bekannten Dingen probiert: If-Verzweigung, For-/While/Repeat/-Schleife, Pos(a,b), komme aber einfach nicht auf die Lösung. Ich habs lediglich geschafft, dass das Programm mir sagt, das wort ist einmal enthalten (eingabe 1 = eingabe2).
Ich denke nicht, dass die Lösung allzu schwer sein wird, mir fällt aber wie gesagt nichts mehr ein. Könnte mir jemand vielleicht einen solchen Quelltext schreiben? Mit Kommentaren/Erklärungen wäre das natürlich super! :)
MfG SiH


Moderiert von user profile iconGausi: Topic aus VisualCLX (Component Library for Cross Platform) verschoben am Do 24.05.2007 um 16:28


Narses - Do 24.05.07 15:42
Titel: Re: Zählen wie oft Wort in einem Satz vorkommt (Quelltext?)
Moin und :welcome: im Forum!

user profile iconSiH hat folgendes geschrieben:
Ich habe es schon mit allen mir bekannten Dingen probiert: If-Verzweigung, For-/While/Repeat/-Schleife, Pos(a,b), komme aber einfach nicht auf die Lösung. Ich habs lediglich geschafft, dass das Programm mir sagt, das wort ist einmal enthalten (eingabe 1 = eingabe2).

Zeig uns doch mal deine bisherige Lösung, dann sehen wir mal, was man machen kann, damit es läuft. ;)

cu
Narses


Jann1k - Do 24.05.07 16:20

also mir fallen spontan zwei möglichkeiten ein:

entweder trennst du die einzelnen wörter voneinander, sodass du einzelne strings erhälts, dann vergleichst du jeden dieser strings mit der eingabe und zählst wie oft der vergleich stimmt.

oder du bastelst die ne for schleife von anfang bis ende des eingegeben string1(-länge von eingabe2) und vergleichst dann immer die nächsten buchstaben mit deinem wort.


ub60 - Do 24.05.07 16:29

Hier einige kleine Denkanstöße:

Bye!
ub60


Gausi - Do 24.05.07 16:34

Schau mal in der Hilfe nach der Funktion PosEx. Das ist wie Pos, nur mit einem Startwert. Ich kenne die Funktion nicht genau, daher Syntaxfehler selber rausfinden ;-)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Anzahl:=0;
Startpos:=1;
NetxPos := PosEx(String1, String2, StartPos);
while NextPos<>0 do//oder was immer PosEx liefert, wenn nix gefunden wird
begin
  inc(Anzahl);
  NextPos := PosEx(String1, String2, NextPos + 1);
  // oder
  NextPos := PosEx(String1, String2, NextPos + length(String2));
end;

Welche Variante du wählst, hängt davon ab, ob du bei abababab und abab als Anzahl 2 oder 3 haben willst ;-)


SiH - Do 24.05.07 17:10

Danke für:
- das Willkommen
- Eure Hilfe

@JannK
Ich weiß nicht, wie ich einen String in mehrere Teilstrings unterteilen kann. Hört sich sicherlich logisch an.

@ub:
Deine Idee ist scheinbar auch meine! Doch warum, bzw. WAS mit der Delete-Funktion löschen?

@Gausi:

Delphi 4 kennt kein PosEx ;) (hätte ich vll. vorher sagen sollen)

Also mal meine Idee:
Mit dieser Pos-Funktion schauen, ob das wort von eingabe2 in eingabe1 enthalten ist. Wenn ja, dann nen zähler +1 setzen und später ausgeben.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
var a, s, i:integer;
begin
w:=ed_e_eingabe1.text; // global schon Variablentyp deklariert
w2:=ed_e_eingabe2.text; // global schon Variablentyp deklariert
i:=1;
s:=0;
begin
for i:=1 to length(w) do
begin
a:=Pos(w2,w);
if a>0 then
s:=s+1
end;
end;
ed_a_ausgabe.text:='Das Wort '+'"'+w2+'"'+' ist '+inttostr(s)+' mal enthalten.';

Das haut einfach nicht hin! :( Mit ner while-Schleife hab ich sogar ne Endlosschleife hinbekommen ^^
Das Problem muss irgendwie bei diesem Pos liegen. Pos(w2,w1) schaut ja nur nach dem ersten buchstaben von w2 oder?

Moderiert von user profile iconGausi: Quote- durch Delphi-Tags ersetzt


Gausi - Do 24.05.07 17:36

Hmm...dann ohne PosEx. Überlappungen von SubStrings werden mitgezählt, d.h. "abab" ist zweimal in "ababab" enthalten. Kann man auch schneller machen, aber Boyer-Moore möchte ich jetzt nciht mal eben für diesen Zweck umbauen ;-)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function Count_SubStrings_Naiv(fText, fPattern: String): Integer;
var t, p, m, n: Integer;
begin
  result := 0;
  m := Length(fPattern);
  n := Length(fText);
  for t := 1 to n - m + 1 do
  begin
    p := 1;
    while (p <= m) and (fText[t + p - 1] = fPattern[p]) do
      inc(p);
    if p = m+1 then
    begin
      inc(result);
    end;
  end;
end;


Jann1k - Do 24.05.07 17:39

zum unterteilen eines strings in seine teilstrings (getrennt wird nur an " " zeichen):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
var 
 woerter: array of string;

procedure tform1.zerlegestring(s:string);
  var I:integer;
begin

  setlength(woerter,1);
  
  for I:=0 to length(s) do
  begin
    if s[I]<>'' then 
      woerter[high(woerter)]:=woerter[high(woerter)]+s[I]
    else
      setlength(woerter,high(woerter)+2);
  end;
end;


Narses - Do 24.05.07 17:49

Moin!

Alternative (ohne überlappende Teilstrings): ;)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure TForm1.Button1Click(Sender: TObject);
  var
    i,j,Anzahl: Integer;
begin
  Anzahl := 0// Vorgabewert
  if (Edit1.Text <> ''then // durchsuchter String leer? nein, dann weiter
    if (Edit2.Text <> ''then begin // Suchen nach leeren Teilstrings sinnlos
      i := 1// Start mit erstem Zeichen im zu durchsuchenden String
      j := 1// Start mit erstem Zeichen im Teilstring
      while (i <= Length(Edit1.Text)) do begin // bis zum Ende des durchsuchten Strings
        if (Edit1.Text[i] = Edit2.Text[j]) then begin // passt das aktuelle Zeichen?
          Inc(j); // dann mit dem nächsten Zeichen des Teilstrings vergleichen
          if (j > Length(Edit2.Text)) then begin // Teilstring zuende? ja, dann
            Inc(Anzahl); // haben wir eine Fundstelle! :)
            j := 1// und wieder vorne anfangen im Teilstring
          end;
        end;
        Inc(i); // nächstes Zeichen im durchsuchten String
      end;
    end;
  ShowMessage(IntToStr(Anzahl));
end;

cu
Narses