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.