Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Wörter zählen (https://www.delphipraxis.net/191872-woerter-zaehlen.html)

Lisa.99 27. Feb 2017 06:55

Wörter zählen
 
Hallo Zusammen!

Ich wollte mein Programm Wörter zählen lassen. Nur leider weiß ich nicht, wie ich das anstellen soll.
Ganz grob gedacht, muss er ja nach jedem Leerzeichen die Gesamtzahl mit 1 addieren, aber wie sieht das im Quelltext aus?

Danke schon mal für die Hilfe :)

MrSpock 27. Feb 2017 07:29

AW: Wörter zählen
 
Welche Idee hast du denn schon dazu entwickelt?

Lisa.99 27. Feb 2017 08:20

AW: Wörter zählen
 
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var i, woerter : integer;
    text : string;
begin
woerter:= 1;
 for i := 0 to length (text) do
  begin
    inc(woerter);
    continue;
  end;
  Edit3.Text:= inttostr(woerter);
end;
Das habe ich und für wenige Wörter funktioniert das!

MrSpock 27. Feb 2017 09:38

AW: Wörter zählen
 
Du hast ja auch noch eine zusätzliche, richtige Idee oben gezeigt. Du musst die Wortgrenzen finden. Das sind in der Regel Leerzeichen. Können aber auch Sonderzeichen wie CR / LF (Zeilenvorschub) oder Tab (Tabulator) sein. Ob du auch Kommata oder Semikolon oder Punkt als Trennzeichen akzeptieren willst, wenn ihnen kein Leerzeichen folgt, musst du dir auch noch überlegen.

Dann kannst du eine Prozedur schreiben, die diese Sonderzeichen findet. das wäre einmal der nächste Schritt.

Slipstream 27. Feb 2017 11:17

AW: Wörter zählen
 
Zitat:

Zitat von Lisa.99 (Beitrag 1362747)
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var i, woerter : integer;
    text : string;
begin
woerter:= 1;
 for i := 0 to length (text) do
  begin
    inc(woerter);
    continue;
  end;
  Edit3.Text:= inttostr(woerter);
end;
Das habe ich und für wenige Wörter funktioniert das!

Length(Text) gibt die Anzahl der Buchstaben und Zeichen zurück. Die Zählung bei Strings beginnt nicht bei 0, sondern bei 1: Text[1] bezeichnet das erste Zeichen des Strings Text. In deiner Prozedure iterierst du durch die Zeichen und erhöhst bei jedem Durchlauf die Zählvariable woerter. Danach gibt deine Procedure die Anzahl der Zeichen aus, nicht die Anzahl der Wörter.

Ich würde so vorgehen: zuerst einmal legst du fest, welche Zeichen als Worttrenner gelten sollen. Das macht man am besten mit einem Set:

Delphi-Quellcode:
  private { Private-Deklarationen }
    Trenner = set of (' ', '?', ',', '.', ';', '!'); // ... und was dir sonst noch einfällt
Dann entwickelst du eine Function, die das gewünschte Ergebnis zurückliefert:

Delphi-Quellcode:
function Form1.GetWordCount(AText : String) : Integer; // "Text" sollte man nicht als Variable verwenden
var
  i,
  Zaehler,
  Laenge : Integer;

begin
  Zaehler := 0;
  i := 1;
  Laenge := Length(AText);
  while i <= Laenge do
  begin
    if AText[i] in Trenner then // ein Trennzeichen wurde gefunden
    begin
      if (i < Laenge) and (AText[i] = ' ') then // wenn i nicht das letzte Zeichen ist, wird das nächste auf Space geprüft
         inc(Zaehler);
      if i = Laenge then // wenn i das letzte Zeichen ist, wird nicht das nächste auf Space geprüft
         inc(Zaehler);
    end;

    inc(i); // nicht vergessen, den Index des Strings zu erhöhen
  end;

  Result := Zaehler;
end;
Den Beispielcode hab ich nicht getestet, sondern einfach im Foreneditor getippt. Der Code ist natürlich nicht perfekt, zB reagiert er nicht darauf, wenn am Ende des Strings gar kein Trennzeichen mehr steht.

Lisa.99 27. Feb 2017 16:04

AW: Wörter zählen
 
Danke für die Hilfe!
Ich schaue, was ich daraus machen kann :-D

himitsu 27. Feb 2017 21:32

AW: Wörter zählen
 
Zitat:

Zitat von Lisa.99 (Beitrag 1362747)
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var i, woerter : integer;
    text : string;
begin
woerter:= 1;
 for i := 0 to length (text) do
  begin
    inc(woerter);
    continue;
  end;
  Edit3.Text:= inttostr(woerter);
end;
Das habe ich und für wenige Wörter funktioniert das!

Das glaub ich nicht.

Erstmal ist 0 bis Length Einer zuviel,
dann zählt das die Zeichen und keine Wörter
und zum Schluss sagt der Code immer "2", da Text leer ist.

Continue ist zwar Nutzlos, da nachfolgend nichts mehr in der Schleife folgt, aber es verursacht hier wenigstens keinen Fehler.

awk 28. Feb 2017 20:32

AW: Wörter zählen
 
Das ist eine einfache Aufgabe. Die folgenden Zeilen sollten dein Problem lösen.

Delphi-Quellcode:
function TokenCount(const cText: String): integer;
    var s: string;
        nPos: integer;
    begin
     result:=0;

     s:=trimright(cText);

     nPos:=Pos(#32,s);

     if (nPos=0) and (length(s)>0) then inc(result);

     while nPos>0 do
     begin
      inc(Result);
      System.Delete(s,1,nPos);
      s:=trimleft(trimright(s));

      nPos:=Pos(#32,s);
     end;
     
    end;
Liebe Grüße aus dem Süden

DeddyH 28. Feb 2017 22:18

AW: Wörter zählen
 
Mit TStringList, Delimiter und DelimitedText sollte das IMHO auch recht einfach zu machen sein.

himitsu 28. Feb 2017 22:48

AW: Wörter zählen
 
Zitat:

Zitat von DeddyH (Beitrag 1362928)
Mit TStringList, Delimiter und DelimitedText sollte das IMHO auch recht einfach zu machen sein.

Delphi-Quellcode:
Length(SplitString(...))

Delphi-Referenz durchsuchenSplitString

Im Prinzip braucht man nur irgendwas, das den String an den Wortgrenzen oder Trennzeichen "zerlegt" und zählt dann die Teile.
"Schneller" wird der Code, wenn man nur die Trennstellen sucht und zählt und nicht wirklich zerlegt. (unnötige Speicheroperationen)
Man kann sogar mit RegEx arbeiten, denn da gibt es nette Steuerzeichen, um "Wort"-Grenzen (Wortanfang/Wortende) zu suchen, wo dazwischen nur "Wort"-Zeichen sind, und zählt dann die Matches.

Selbt eine For-Schleife funktioniert gut, wenn man sie richtig implementiert.
z.B. alle Zeichen durchgehen, beim (ersten) "Wort"-Zeichen (Buchstaben) den Zähler erhöht und dann alle nachfolgenden "Wort"-Zeichen (Buchstaben, Bindestrich usw.) ignoriert, bis zum nächsten Nicht-Wort-Zeichen und beim nächsten Wort-Zeichen wieder zählen usw.
Bzw. ganz billig: Man zählt Alles, wo man ein Wort-Zeichen findet, wo direkt davor ein Nicht-Wort-Zeichen liegt und zählt 1 dazu, wenn das allererste Zeichen auch ein Wort-Zeichen war.

"Etwas" Aufwändiger wird es, wenn man mehrfache aufeinanderfolgende "Nicht-Wort-Zeihen" hat und die als "mehrere" Trennstellen zählt, obwohl keine Wörter dazwischen sind.
Bei der StringList kann man da z.B. mit StrictDelimiter rumspielen.

Dann kann man noch "Nicht-Wörter" ignorieren (z.B. Zahlen) und wenn man dann auch noch zusammengesetzte Wörter erkennen will wird es erst spaßig.


Es geht also einfach oder aufwändiger ... jenachdem was man als "Wörter" definiert.

t.roller 2. Mär 2017 13:17

AW: Wörter zählen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Das Beispiel TOKENCOUNT (648 Wörter) von awk und das Beispiel von hier
http://www.swissdelphicenter.com/de/showcode.php?id=806
(680 Wörter)
sind unterschiedlich zu MS WORD (660 Wörter).
Textprobe im Anhang.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtDlgs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    OpenTextFileDialog1: TOpenTextFileDialog;
    Button2: TButton;
    Label1: TLabel;
    Button3: TButton;
    SaveTextFileDialog1: TSaveTextFileDialog;
    Button4: TButton;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function Seps(As_Arg: ANSIChar): Boolean;
begin
  Seps := As_Arg in
    [#0..#$1F, ' ', '.', ',', '?', ':', ';', '(', ')', '/', '\', '-'];
end;

function WordCount(CText: ANSIstring): Longint;
var
  Ix: Word;
  Work_Count: Longint;
begin
  Work_Count := 0;
  Ix        := 1;
  while Ix <= Length(CText) do
  begin
    while (Ix <= Length(CText)) and (Seps(CText[Ix])) do
      Inc(Ix);
    if Ix <= Length(CText) then
    begin
      Inc(Work_Count);

      while (Ix <= Length(CText)) and (not Seps(CText[Ix])) do
        Inc(Ix);
    end;
  end;
  WordCount := Work_Count;
end;
//------------------------------------------------------------------------------
function TokenCount(const cText: String): integer;
    var s: string;
        nPos: integer;
    begin
     result:=0;

     s:=trimright(cText);

     nPos:=Pos(#32,s);

     if (nPos=0) and (length(s)>0) then inc(result);

     while nPos>0 do
     begin
      inc(Result);
      System.Delete(s,1,nPos);
      s:=trimleft(trimright(s));

      nPos:=Pos(#32,s);
     end;

    end;

//------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Clear;
if OpenTextFileDialog1.execute then
      Memo1.Lines.loadfromfile(OpenTextFileDialog1.FileName);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Label1.Caption:= INTTOSTR(WORDCOUNT(Memo1.Text));
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if SaveTextFileDialog1.execute then
  Memo1.Lines.SaveTofile(SaveTextFileDialog1.FileName);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
Label2.Caption:= INTTOSTR(TOKENCOUNT(Memo1.Text));
end;

procedure TForm1.FormShow(Sender: TObject);
begin
Label1.Caption:= INTTOSTR(WORDCOUNT(Memo1.Text));
end;

end.

nahpets 2. Mär 2017 15:19

AW: Wörter zählen
 
Mit dieser Routine komme ich bei oben angehängtem Text auf 612 Wörter.
Delphi-Quellcode:
function WortCount(s : String): Integer;
var
         i      : Integer;
         bInWort : Boolean;
begin
  Result := 0;
  bInWort := False;
  for i := 1 to Length(s) do begin
    case s[i] of
      // Wenn Ziffern auch als Zeichen für Wörter gelten sollen,
      // oder Zahlen als Wort zu zählen sind:
      // '0'..'9',
      // Wer weitere Zeichen berücksichtigen will, darf hier gerne erweitern:
      'A'..'Z',
      'Á','É','Í','Ó','Ú',
      'À','È','Ì','Ò','Ù',
      'Ä','Ö','Ü',
      'a'..'z',
      'á','é','í','ó','ú',
      'à','è','ì','ò','ù',
      'ä','ö','ü','ß' : if not bInWort then begin
                          Result := Result + 1;
                          bInWort := True;
                        end;
      else
        bInWort := False;
    end;
  end;
end;

var
        sl : TStringList;
begin
  sl := TStringList.Create;
  sl.LoadFromFile('c:\temp\Von 14 auf 20 Millionen.txt');
  ShowMessage(IntToStr(WortCount(sl.Text)));
  sl.Free;
end;
Text aufbröseln und "von Hand" nachzählen ergab ebenfalls 612 Wörter.

Frage: ist das ein Wort? Welt-Krebs-Bericht
Oder sind das drei Wörter?

Wird mit obiger Routine als drei gezählt.

Word zählt auch die Zahlen oder ein Datum ... als einzelne Wörter.

Wenn man's genau haben will, muss man erstmal definieren, was genau ist ;-)
Und dann wird es schnell beliebig komplex.

freimatz 3. Mär 2017 11:51

AW: Wörter zählen
 
https://de.wikipedia.org/wiki/Wort :lol:

t.roller 3. Mär 2017 16:40

AW: Wörter zählen
 
Zitat:

Zitat von nahpets (Beitrag 1363034)
Frage: ist das ein Wort? Welt-Krebs-Bericht
Oder sind das drei Wörter?

Wird mit obiger Routine als drei gezählt.

Es müsste als EIN Wort gezählt werden, weil man es auch zusammenhängend schreiben kann:
Weltkrebsbericht oder WeltKrebsBericht.

Dieses nennt man Binnenmajuskel.

Ich liebe Binnenmajuskel!
Grund: Solch ein Wort lässt sich leichter lesen.

Micropachycephalosaurus hongtuyanensis, ein Dinosaurier
MicroPachyCephaloSaurus HongtuYanensis, ein Dinosaurier
Der Gattungsname – einer der längsten aller Dinosaurier – leitet sich von den Wörtern
mikros (=„klein“),
pachys (=„dick“),
kephale (=„Kopf“) und
sauros (=„Echse“) ab und bedeutet dementsprechend „kleine Dickkopfechse“.
Hongtu = Ort, wo es rote Erde gibt, (Red soil = roter Ackerboden)
Yunnan = Provinzname.
Fundort: Wangshi, Shandong (China), ca. 80 Mill. Jahre alt.

Rollo62 3. Mär 2017 22:48

AW: Wörter zählen
 
Dankesehr für die Aufklärung.

Ich bin da auch ein großer Fan von.

Jetzt weiss ich auch endlich wie CamelCase auf Deutsch heisst :-)

Rollo

Lisa.99 6. Mär 2017 07:21

AW: Wörter zählen
 
Bei mir zählt er leider immer nur zwei Wörter, egal wie viele es sind und finde dabei den Fehler auch nicht

procedure TForm1.Button2Click(Sender: TObject);
var i, woerter : integer;
text : string;
begin
woerter:= 1;
for i := 0 to length (text) do
begin
inc(woerter);
continue;
end;
Edit3.Text:= inttostr(woerter);
end;

mikhal 6. Mär 2017 07:41

AW: Wörter zählen
 
Wie oben bereits beschrieben ist deine Variable Text leer.

Du setzt den Startwert auf 1, zählst in deiner Schleife sofort 1 hoch: Ergebnis ist 2.

Wie ebenfalls bereits oben beschrieben zählst du nicht die Wörter sondern die Anzahl Zeichen. Also solltest du in deiner Schleife nur dann hochzählen, wenn ein Leerzeichen ausgewertet wird. Continue ist hier überflüssig! Sorge mit Trim noch dafür das weder am Anfang noch am Ende deines Strings Leerzeichen stehen (Trailing-Spaces). Dann kannst du die naheliegende Variante verwenden, indem du jedes Zeichen Text[i] auf Space / Leerzeichen auswertest.

Diese "naive" Variante kannst du dann wie oben bereits angezeigt, verfeinern und um die Zeichen erweitern, die ebenfalls zur Trennung von Worten führen. Beispielroutine ist ungetestet.

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var i, woerter : integer;
    text : string;
begin
  woerter:= 0;
  text := Trim('Dies ist ein kurzer Text') // Trailing-Spaces entfernen;
  for i := 1 to length (text) do
  begin
    if text[i] = ' ' then
      inc(woerter);
//    continue; // überflüssig!
  end;
  // das letzte Wort mitnehmen
  inc(woerter);
  Edit3.Text:= inttostr(woerter);
end;

Lisa.99 6. Mär 2017 07:52

AW: Wörter zählen
 
verstanden habe ich, was mein Fehler war, nur leider funktioniert es immer noch nicht, entweder er gibt mir 0 oder 1 aus.

Sherlock 6. Mär 2017 08:01

AW: Wörter zählen
 
Hast Du Dir eigentlich auch nur einen der Lösungsvorschläge angesehen?

Sherlock

Lisa.99 6. Mär 2017 08:03

AW: Wörter zählen
 
Ich habe mir alle angesehen, nur leider verstehe ich die wenigsten und möchte gerne die Lösungen nutzen, die ich auch nachvollziehen kann. Vieles haben wir nämlich in der Schule nicht gelernt.

mikhal 6. Mär 2017 08:06

AW: Wörter zählen
 
Deshalb habe ich meine Routine auf deinen Ansatz erweitert. Sie sollte einwandfrei funktionieren, auch wenn ich sie immer noch nicht getestet habe.

Grüße
Mikhal

p80286 6. Mär 2017 08:12

AW: Wörter zählen
 
Zitat:

Zitat von Lisa.99 (Beitrag 1363267)
verstanden habe ich, was mein Fehler war, nur leider funktioniert es immer noch nicht, entweder er gibt mir 0 oder 1 aus.

Dann wäre es sinnvoll Deinen Sourcecode (mit Berichtigungen) zu posten. Und wenn Du das Helmsymbol dabei nutzt, wird es auch leserlicher.

Gruß
K-H

himitsu 6. Mär 2017 09:21

AW: Wörter zählen
 
Zitat:

Zitat von Lisa.99 (Beitrag 1363263)
Bei mir zählt er leider immer nur zwei Wörter, egal wie viele es sind und finde dabei den Fehler auch nicht

procedure TForm1.Button2Click(Sender: TObject);
var i, woerter : integer;
text : string;
begin
woerter:= 1;
for i := 0 to length (text) do
begin
inc(woerter);
continue;
end;
Edit3.Text:= inttostr(woerter);
end;

Sorry, ich klinke mich ab jetzt aus jeglichen Themen aus.

Zitat:

Das habe ich und für wenige Wörter funktioniert das!
Erst behauptest du das funktioniert.
Ich hatte bereits in Antwort #7 gezeigt, dass ich es nicht wirklich glauben kann, hab dort bereits die Gründe/Fehler genannt
und jetzt heißt es, dass es doch nicht funktioniert?

Es wäre gut, wenn du dir Antworten vielleicht auch durchliest.

p80286 6. Mär 2017 09:31

AW: Wörter zählen
 
Der letzte Vorschlag von mikhal ist die einfachste Lösung und sollte ein erstes Ergebnis bringen.
Un falls da etwas unklar ist: fragen.
(aber bitte konkret)

Gruß
K-H

Lisa.99 6. Mär 2017 16:22

AW: Wörter zählen
 
text := Trim('Dies ist ein kurzer Text')
Was hat das in den Klammern zu stehende zu bedeuten?
Verstanden habe ich, dass das Trim die Leerzeichen am Satzanfang und -ende verfallen lässt.

EWeiss 6. Mär 2017 16:28

AW: Wörter zählen
 
Zitat:

Zitat von Lisa.99 (Beitrag 1363349)
text := Trim('Dies ist ein kurzer Text')
Was hat das in den Klammern zu stehende zu bedeuten?
Verstanden habe ich, dass das Trim die Leerzeichen am Satzanfang und -ende verfallen lässt.

Gar nichts denn hier Trim zu verwenden bei diesen Satz ist Blödsinn.
Es wäre etwas anderes wenn er so geschrieben wäre.


Delphi-Quellcode:
text := Trim('  Dies ist ein kurzer Text');


Das Ergebnis wäre dann wie du schon sagst der gleiche Text ohne die beiden Leerzeichen am Anfang.


gruss

Luckie 6. Mär 2017 16:29

AW: Wörter zählen
 
Aber da man nicht weiß, was für ein Text übergeben wird, benutzt man zur Sicherheit trim.

EWeiss 6. Mär 2017 16:30

AW: Wörter zählen
 
Zitat:

Zitat von Luckie (Beitrag 1363351)
Aber da man nicht weiß, was für ein Text übergeben wird, benutzt man zur Sicherheit trim.

Aber nicht bei dieser Konstellation.
Wenn man den Text selber Schreibt wie hier geschehen.
Da ist doch wohl erkenntlich das hier keine Leerzeichen stehen.

Somit ist die Frage von ihr in dem Zusammenhang durchaus berechtigt da es keinen sinn macht hier Trim zu verwenden.

Zitat:

text := Trim('Dies ist ein kurzer Text') // Trailing-Spaces entfernen;
Welcher Trailing-Spaces ?

gruss

himitsu 6. Mär 2017 17:28

AW: Wörter zählen
 
Dann kann man aber auch selber Zählen und direkt die Wortanzahl hinschreiben.

Denkt euch den "Text" als Platzhalter für eine Variable.


PS: Bei einem Leerstring wird behauptet da sei ein Wort drin.
Und sind zwischen zwei Wörtern mal zwei/mehrere Leerzeichen, dann werden mehr Wörter gezählt, als da sind.

Luckie 6. Mär 2017 17:37

AW: Wörter zählen
 
Diese Sonderfälle sollten wir erst mal ausklammern. Erst mal muss sie den einfachsten Fall hinbekommen. Aber da sehe ich im Moment kein Ende hier. :cry:


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