Autozastępowanie

Adam Boduch

Pewnie myślałeś kiedyś jak to by było fajnie napisać
program, który złe wyrazy zastępował by dobrymi. Np. zastąpić
wyraz "sie" na "się". Program będzie się opierał
na dwóch plikach tekstowych, które zawierać będą słowa złe - do
zastąpienia, a w drugim pliku będą się znajdywać pliki, które zastąpią
złe wyrazy.

Wszystko będzie się opierać na module "WordFrm"
i na klasie wątkowej:

 TFind = class(TThread)
  private
    FFindText : String;
    FGoodText : String;
    FBadWord : TStrings;
    FGoodWord : TStrings;
  protected
    procedure Execute; override;
    procedure GiveAnswer; 
  public
    constructor Create; 
    destructor Destroy; override;
  end;

Podstawową konstrukcją są dwie zmienne - "FBadWord"
i "FGoodWord". Obie te zmienne są typu "TStrings",
które zawierają listę złych i dobrych plików. Lista ta ładowana
jest z plików tekstowych. W sekcji "protected" znajduje się
procedura "GiveAnswer", która wyświetla rezultat na formie,
a konkretnie na komponencie RichEdit.

Główny wątek to następujący kod:

procedure TFind.Execute;
var
  TF : TextFile;
  BadWord, GoodWord : String;
  Count : Integer; // ilosc slow, ktore znajduja sie w pliku

{  Laduje wyrazy z plikow }
  procedure LoadFile;
  begin
    if not FileExists(WORDS) or not FileExists(GOOD) then
      raise ENoFile.Create(Concat('Brak pliku: ', WORDS, ' lub: ', GOOD)) else

    AssignFile(TF, WORDS);
    Reset(TF);  // otworz plik

    while not Eof(TF) do
    begin
      Readln(TF, BadWord);
      FBadWord.Add(BadWord); // wczytaj zawartosc do zmiennej
    end;
    CloseFile(TF);    // zamknij plik

    AssignFile(TF, GOOD);  // otworz plik drugi
    Reset(TF);

    while not Eof(TF) do
    begin
      Readln(TF, GoodWord);
      FGoodWord.Add(GoodWord); // wczytaj zawartosc do zmiennej
    end;

    CloseFile(TF);
  end;

begin
  FreeOnTerminate := True; // zkoncz watek przy zakonczeniu procrury
  LoadFile;  // wywolaj procedure
{
  tutaj nastepuje sprawdzenie wsystkich wyrazow znajdujacych sie w pliku
  tekstowym i porowanie ich z tym co znajduje sie w zawartosci RichEdir'a.
}

  Count := 0; // wyzeruj licznik...

  repeat // petelka
{
   Do zmiennych zostaje przypisana wartosc z innych zmiennych typu TStrings.
   Wyraz, ktory zostaje przypisany okreslany jest przez licznik - Count.
}
    FFindText := FBadWord.Strings[Count];
    FGoodText := FGoodWord.Strings[Count];

    (GiveAnswer); // wywolaj procedure

    Inc(Count); // zwieksz licznik o jeden

  until Count > FBadWord.Count;
end;

Jak widzisz jedna procedura - LoadFile zawarta jest w drugiej - w wątku. Procedura ta powoduje ładowanie treści pliku tekstowego do
zmiennych.

Następnie zmienna "Count" zostaje zerowana i wykonywana
zostaje pętelka mająca na celu pobranie za każdym razem wyrazu ze
zmiennej i wykonywanie procedury "GiveAnswer", która ma za
zadanie szukane słowo ( złe słowo ) zastąpić dobrym. Oto ta
procedura:

procedure TFind.GiveAnswer;
var
  SelPos : Integer;
begin
{ Procedura zastepuje wyraz do zastapienia nowym }
  with MainForm.RichEdit do
  begin
    SelPos := Pos(FFindText, Lines.Text); // znajdz szukany wyraz
    if SelPos > 0 then
    begin
      SelStart := SelPos -1;
      SelLength := Length(FFindText); 
      SelText := FGoodText;  //... i zastap nowym
    end else Exit; // jezeli nic nie znajdziesz - anuluj...
  end;
end;

Ta procedura znajduje słowo w komponencie "RichEdit", a
następnie znalezione słowo zastąpnie dobrym.

Oto cały kod modułu:

(****************************************************************)
(*                                                              *)
(*                 Word Unit fof Change Words programme         *)
(*       Copyright (c) 2001 by Service for programmers          *)
(*            Build:  14.04.2001  -  Adam Boduch                *)
(*              HTTP://WWW.PROGRAMOWANIE.OF.PL                  *)
(*    E - mail: boduch@poland.com                               *)
(*                                                              *)
(****************************************************************)

unit WordFrm;

interface

uses
  Classes, SysUtils, Graphics;

const
{
  Stale przechowuja pliki, w ktorych znajduja sie slowa - do zmiany i
  slowa, ktore nalezy zmienic.
}
  WORDS = 'Words.txt';
  GOOD = 'Good.txt';

type
  ENoFile = class(Exception); // wyjatek wystapi gdy pliku na dysku nie bedzie

  TFind = class(TThread)
  private
    FFindText : String;
    FGoodText : String;
    FBadWord : TStrings;
    FGoodWord : TStrings;
  protected
    procedure Execute; override;
    procedure GiveAnswer; 
  public
    constructor Create; 
    destructor Destroy; override;
  end;

implementation

uses MainFrm;

constructor TFind.Create;
begin
  inherited Create(FALSE);
    FBadWord := TStringList.Create; // utworz zmienne
    FGoodWord := TStringList.Create;
end;

destructor TFind.Destroy;
begin
  FBadWord.Free;
  FGoodWord.Free;  // zwolnij zmienne

  inherited;
end;

procedure TFind.Execute;
var
  TF : TextFile;
  BadWord, GoodWord : String;
  Count : Integer; // ilosc slow, ktore znajduja sie w pliku

{  Laduje wyrazy z plikow }
  procedure LoadFile;
  begin
    if not FileExists(WORDS) or not FileExists(GOOD) then
      raise ENoFile.Create(Concat('Brak pliku: ', WORDS, ' lub: ', GOOD)) else

    AssignFile(TF, WORDS);
    Reset(TF);  // otworz plik

    while not Eof(TF) do
    begin
      Readln(TF, BadWord);
      FBadWord.Add(BadWord); // wczytaj zawartosc do zmiennej
    end;
    AssignFile(TF, GOOD);  // otworz plik drugi
    Reset(TF);

    while not Eof(TF) do
    begin
      Readln(TF, GoodWord);
      FGoodWord.Add(GoodWord); // wczytaj zawartosc do zmiennej
    end;

    CloseFile(TF);
  end;

begin
  FreeOnTerminate := True; // zkoncz watek przy zakonczeniu procrury
  LoadFile;  // wywolaj procedure
{
  tutaj nastepuje sprawdzenie wsystkich wyrazow znajdujacych sie w pliku
  tekstowym i porowanie ich z tym co znajduje sie w zawartosci RichEdir'a.
}

  Count := 0; // wyzeruj licznik...

  repeat // petelka
{
   Do zmiennych zostaje przypisana wartosc z innych zmiennych typu TStrings.
   Wyraz, ktory zostaje przypisany okreslany jest przez licznik - Count.
}
    FFindText := FBadWord.Strings[Count];
    FGoodText := FGoodWord.Strings[Count];

    (GiveAnswer); // wywolaj procedure

    Inc(Count); // zwieksz licznik o jeden

  until Count > FBadWord.Count;
end;


procedure TFind.GiveAnswer;
var
  SelPos : Integer;
begin
{ Procedura zastepuje wyraz do zastapienia nowym }
  with MainForm.RichEdit do
  begin
    SelPos := Pos(FFindText, Lines.Text); // znajdz szukany wyraz
    if SelPos > 0 then
    begin
      SelStart := SelPos -1;
      SelLength := Length(FFindText);  // zaznacz go...
      SelText := FGoodText;  //... i zastap nowym
    end else Exit; // jezeli nic nie znajdziesz - anuluj...
  end;
end;

end.

0 komentarzy