Jak pewnie kilka osób zauważyło piszę edytor textu. Chciałbym dodać do niego opcję sprawdzania pisowni ( nie korzystając z żadnego gotowego komponentu!) Chodzi o to, żeby słownik znajdował się w pliku textowym, a po wpisaniu textu do RE i postawieniu spacji lub entera program sprawdzałby, czy wyraz znajduje sie w słowniku. Jeżeli nie to podkreślałby go na czerwono :)
Da się coś takiego zrobić ?? I oczywiście jak :D [hurra]
Pewnie że się da.... trzeba tylko:
-
Znaleźć słownik polski w pliku tekstowym - gdzieś taki widziałem - koło 10 mb...
-
Napisać procedurę sprawdzającą z plikiem
-
Włączyć program :)
Oczywiście samo załadowanie słownika zajmie jakieś 10 sekund... jeśli w ogole sie wszystko nie zawiesi... że nie wspomne o sprawdzaniu - każde sprawdzenie zajmie kilka sekund... czyli ... LIPA
Jak się tak do tego podejdzie, to rzeczywiście lipa.
Proponuję wpisać w wyszukiwarce Uniwersalna Struktura Słownikowa. Już Vogel pisał jak to zrobić.
Słownik jest gotowy pod adresem http://www.kurnik.pl/slownik/growy/ - po rozpakowaniu około 30Mb. Jak będziesz go wgrywał za pomocą ReadBuffer, to u mnie zajmuje to jakieś 5.5 sekundy, to oczywiście zależy od szybkości sprzętu, ja mam Celerona 366. Jest oczywiście taki makament, że sprawdzanie będzie trwało w nieskończoność, bo musisz zastosować pętlę, która będzie porównywała każdy wyraz ze słownika z ostatnim wyrazem z Memo. I w tym właśnie miejscu trzeba wymyśleć coś innego, bo taka operacja zajmuje około 30-40 sekund... A jak ci się uda to jeszcze musisz pobrać pozycję (w pixelach) błędnie napisanego wyrazu w Memo i narysować na tym Memo linię pod tym wyrazem. Powodzenia.
//DOPISANE
Z ciekawości wpisałem sobie tą "uniwersalną strukturę słownikową", wyświetliło mi tylko jedną stronę. Przejrzałem z grubsza, ale się przestraszyłem wzorów, jakie tam widziałem...
//DOPISANE2
link : http://www.orca2.mila.edu.pl/~astajniak/indexalg.htm
Ta wyszukiwarka jest dobijająca :(
Moglby ktos podac link?
[dopisane]
a moze by tak stworzyc nowy watek. Uzytkownik wpisywalby tekst, a w tym czasie probram sobie go porownuje
słownik mam już od jakiegoś czasu :)
Domyślałem się, że sprawdzanie będzie sporo czasu trwało :) No ale trudno. A może jest jakas inna możliwość zrobienia czegos takiego ??
Tak żeby szybko chodziło i ostatecznie sprawdzanie odbywało się po nacisnieciu przycisku sprawdz pisownie. Oczywiście wolałbym, żeby to się mogło odbywac podczas wprowadzania textu, ale jak sie nie da to trudno :)
NIech ktos podpowie, jak to zrobic, zeby działało szybko i nie zawieszało kompa ;P
szybciej wyszukac na pewno sie da, trzeba tylko znalezc dobry ku temu algorytm. Jesli w slowniku masz zapisane slowa wg. alfabetu i zalozmy kazde slowo jest w nowym wierszu to mozna podzielic slownik na 31 grup (chyba tyle jest liter w alfabecie polskim ;-) ) Program wiedzialby wtedy gdzie szukac np. chce sprawdzic czy istnieje słowo 'gitara' program Od razu wie ze trzeba zaczac (i skanczyc) szukac w grupie w ktorej slowa zaczynaja sie na litere 'g'... mozna dac kilka petli i sprawdzac po literce...
http://www.kurnik.pl/literaki/konkurs/
program "Lit", jest to program ze źródłem w delphi do gry w literaki. Po ułożeniu wyrazy sprawdza czy jestw słowniku, a robi to naprawdę szybko, lecze nie wiem jak, bo nie studiowałem źródła.
Pochwalony! Mam pomysł, nie należy on do najlepszych, ale jakoś trza to zrobić (wszystko jest możliwe) :P. Możesz na początku programu dać tabliczkę "ładowanie", podczas której do zmiennej jakiejś typu TStringList zostanie załadowany plik tekstowy (niestety nie należy to do dobrych rozwiązań, gdyż jest to w SPACJA końcu 30MB...). Podczas wciśnięcia przycisku ENTER lub SPACE (dla polskojęzycznych: WEJDŹ, lub PRZERWA :P ) można porozdzielać zdanie na słowa, a następnie sprawdzić poleceniem IndexOf (klasy TStringList, przy CaseSensive (dokładnie nie pamiętam, jakoś tak, teraz Delphi nie mam to nie powiem dokładnie :P) na True) czy takie słowo istnieje, jeżeli istnieje to odczepić się od tego i kolejne sprawdzać (oczywiście tylko z lini!! (przy większym obszarze to mogłoby dłużej trwać)). Jeżeli nie istnieje takie słowo w słowniku to podkreślić :P. Niestety, nie jestem pewny tego rozwiązania, gdyż nie mam Delphi, nie mam tego jak przetestować. To może się i tak zacinać przez polecenie IndexOf (może ono jakoś nieładnie sprawdzać TStringList), co doprowadzi do spowolnień. Jeżeli sposób nie zadziała, to sorki (chciałem mieć dobry uczynek na duszy P:P ).
Nie wiem czy to coś da bo nie próbowałem ale spróbuj tak. Zamiast szukać całego wyrazu najpierws poszukaj pierwszej litery tego wyrazu. Potem od miejsca gdzie znalazłeś tę pierwszą literę szukaj dwóch pierwszych liter szukanego wyrazu itd.
A mógłby ktos napisać taką przykładową procedurę, szukającą w pliku textowym wyraz wpisany w RE ?? I w jakim miejscu programu (noChange ?? RE)?? jestem dosyć początkujący i nie znam jeszcze wielu poleceń delphi :D [cya]
Wiesz, przykład to chyba każdy może dać. Na przykład tworzysz sobie TStringList, wgrywasz do niego słownik, a potem sprawdzasz :
if TStringList.ItemIndex('slowo') <> -1 then JestWSlowniku := true
else JestWSlowniku := false;
Tylko jak u mnie jak próbowałem wgrać słownikk ten 30Mb to się komputer zawiesił po jakimś czasie, długim zresztą. Może ktoś ma pomysł, jak to szybko przerzucić do TStringLista zawartość pliku?
Załamujecie mnie:
http://4programmers.net/Forum/viewtopic.html?id=29951
Post Vogel'a
Dzięki. Ale tak przy okazji jeszcze jedna mała prośba. I proszę, nie śmiejcie się :) Ja naprawdę jetem początkujący i nie opanowałem jeszcze obsługi tablic :( Jeżeli ktoś mógłby mi napisać, jak powinna wyglądać ta tablica z wczytanymi z pliku wartościami, w którym miejscu kodu ją wstawić itp to bardzo proszę o pomoc!!!
Może załóżmy, że w pliku znajduje się kilka wyrazów i chcę je wczytać do tablicy slowa_w_slowniku. Następnie wywołać procedurę w poprzednim poscie (tą co szuka wyrazu w tablicy). Prosiłbym o napisanie przykładowego kodu tej tablicy i info, w której części programu mam ją umieścić (domyślam się, że w onCreate formy głównej, ale nie jestem pewny :()
Kurcze, Google nie znalazło zbyt wiele na temat Uniwersalnej Struktury Słownikowej. Jedną stronę angielskojęzyczną z gotowym źródłem, ale w C, a drugą polską, ale tylko z ogólnym zarysem tego problemu (jakieś źródła są w Pascalu, ale ja nie wiem, co tam w nich jest... http://www.orca2.mila.edu.pl/~astajniak/drzewa.htm). Gdyby ktoś mógł wyjaśnić ten problem w Artach lub skierować do jakiegoś URL, gdzie to jest jakoś lepiej wyjaśnione i gdzie są jakieś przykłady, to byłbym wdzięczny.
Co tu jest do rozumienia? Fragment (niedokończonego) notatnika wykorzystujący USS.
type
PNode = ^TNode;
TNode = record
Last: Boolean; //Czy ostatnia litera słowa?
Letters: array ['A'..'Z'] of PNode; //Poszczególne litery
end;
type TDictionary = class
FRoot: PNode; //Korzeń drzewa liter
FStrings: TStrings; //Lista, na którą są wypisywane pasujące słowa
FWord: string; //Aktualne słowo, do którego szukamy dopasowań
private
procedure Find(Word: string); //Wyszukuje pasujące słowa
public
constructor Create;
destructor Destroy; override;
procedure Add(Word: string); //Dodaje wyraz do słownika
procedure Delete(Word: string); //Usuwa wyraz ze słownika
procedure Clear; //Czyści słownik
property Word: string read FWord write Find;
property List: TStrings read FStrings write FStrings default nil;
end;
var
Form1: TForm1;
Slownik: TDictionary = nil;
implementation
{$R *.dfm}
constructor TDictionary.Create;
(* Tworzy słownik i inicjuje zmienne *)
begin
inherited Create;
FStrings := nil;
FWord := '';
end;
destructor TDictionary.Destroy;
(* Usuwa zawartość słownika i niszczy słownik *)
begin
Clear;
inherited Destroy;
end;
procedure TDictionary.Clear;
(* Czyści słownik *)
procedure Empty(var Node: PNode);
var
i: Char;
begin
if Node = nil then
Exit;
for i := 'A' to 'Z' do
Empty(Node^.Letters[i]);
Dispose(Node);
Node := nil;
end;
begin
Empty(FRoot);
end;
procedure TDictionary.Delete(Word: string);
(* Usuwa słowo *)
function Remove(Node: PNode; Word: string; i: Integer): Boolean;
var
j: Char;
begin
if Node = nil then
begin
Result := True;
Exit;
end;
if Remove(Node^.Letters[Word[i]], Word, i+1) then
begin
Dispose(Node^.Letters[Word[i]]);
Node^.Letters[Word[i]] := nil;
end;
for j := 'A' to 'Z' do
if Node^.Letters[j] <> nil then
begin
Result := False;
Exit;
end;
if (not Node^.Last) or (i = Length(Word)+1) then
Result := True
else
Result := False;
end;
begin
Remove(FRoot, UpperCase(Word), 1);
end;
procedure TDictionary.Add(Word: string);
(* Dopisuje słowo do słownika *)
procedure Write(var Node: PNode; Word: string; i: Integer);
begin
if Node <> nil then
begin
if (i > Length(Word))or not(Word[i] in ['A'..'Z']) then
Node^.Last := True
else
Write(Node^.Letters[Word[i]], Word, i+1);
end
else
begin
New(Node);
Node^.Last := False;
FillChar(Node^.Letters, SizeOf(Node^.Letters), 0);
Write(Node, Word, i);
end;
end;
begin
if Word <> '' then
Write(FRoot, UpperCase(Word), 1);
end;
procedure TDictionary.Find(Word: string);
(* Wyszukuje zgodne słowa *)
function Match(Node: PNode; i: Integer): PNode;
(* Wyszukuje pasujące fragmenty słowa *)
begin
if (i > Length(FWord)) or (Node = nil) then
begin
Result := Node;
Exit;
end;
if FWord[i] in ['A'..'Z'] then
Result := Match(Node^.Letters[FWord[i]], i+1)
else
Result := Node;
end;
procedure Print(Node: PNode; Word: string);
(* Dopisuje do listy pasujące słowa *)
var
i: Char;
begin
if Node = nil then
Exit;
if Node^.Last then
FStrings.Add(Word);
for i := 'A' to 'Z' do
Print(Node^.Letters[i], Word+i);
end;
begin
if not Assigned(FStrings) then
Exit;
FWord := UpperCase(Word);
FStrings.Clear;
Print(Match(FRoot, 1), FWord);
end;
Nie czepiać się, że mało komentarzy i niespójne nazewnictwo. Dopiero w trakcie powstawania to jest. Czuję, że jakiś prosty art będzie potrzebny...
Z tego co widzę, to to jest jakiś komponent, więc może zamiast arta walnąć go w kodach źródłowych i nie będzie problemu... Po pierwsze szybciej instaluje się gotowe komponenty niż pisze własne według jakichś wskazówek. A myślę, że niejednemu się to przyda jeszcze...
hmm.....
A ten słownik to jest w jakimś pliku czy gdzie ??
bo nie zauważyłem żeby było tam jakieś odwołanie do pliku ??
I może rzeczywiście skoro to jest komponent, to umieścić go w źródłach i zrobić jakiś krótki opis korzystania z niego ??
Nie wiem... u mnie to nie chce działać, wywala się na
Node <> nil
w procedurze write... Acces Violation i tak dalej.
- Nie komponent tylko obiekt.
- Jak już wspomniałem, dopiero piszę to, dlateg m. in. nie ma jeszcze zapisu na dysk i odczytu z dysku bazy danych.
- Jak z pkt. 2 wynika, jeszcze zdarzają się błędy. Nie wiem co jest nie tak w procedurze Write. U mnie działało ostatnio, ale możliwe, że coś zmieniałem i zapomniałem.
Umieszczę do w kodach źródłowych, jak tylko skończę i wyszlifuję. Na razie nie mam czasu brać się za to... Ale może jeszcze w ciągu tygodnia zdążę się za to wziąć.
Z tego co zobaczyłem to ten program szuka normalnie w wątku ? [spoko]