SpellCheck mt Text String
K im li chính t là mt thách thc thú v v k thut lp trình. Nó đòi hi s tính
toán v thiết kế và v cách viết code.
Như ta thường dùng công c SpellCheck trong các chương trình thông dng như
Word, Excell .v.v.. nó hot động coi êm ái, d dàng, nhưng tht ra nó không đơn gin
đâu. Chính Microsoft đã tng license k thut SpellCheck t mt công ty khác đ
chuyên lo công vic ny cho Microsoft.
đây ta th bàn bc và thiết kế mt phương tin SpellCheck nho nh để có th dùng
trong chính các programs cây nhà, lá vườn ca mình.
Program SpellCheck bng VB6
Thông thường User có mt Text String mà h va mi đánh vào.
H s Click mt Menu Command hay mt nút SpellCheck. Lp tc mt SpellCheck
Dialog s hin ra ging như sau:
Program có sn mt t đin ( Dictionary) ca tt c nhng ch đúng chính t. Khi
SpellCheck, nó s kim tng ch mt trong Text String xem ch y có mt trong t
đin không. Nếu có thì nó s lướt qua đến mt ch khác.
Khi gp mt ch chưa có trong t đin, program s highlight ch y trong TextBox và
display nhng ch trong t đin có spelling tương đối gn ging ch y nht. Program
s đợi, và User có 3 options:
Skip ch y: Bo program đừng quan tâm đến ch y và tiếp tc
x lý ch kế tiếp.
Add ch y vào t đin: Ðây là cách cho t đin hc thêm ch
mi.
Change ch y: Thay thế ch y trong Text String bng hoc là
mt ch nm trong danh sách các ch đã được đề ngh (thường
thường các ch ny ch trt mt character so vi ch ta đang x
lý, có l vì ch ta đang x lý b đánh vn trt) hoc mt ch mi
hoàn toàn mà User mi đánh cái TextBox nm phía trên.
Sau khi User đã chn mt trong 3 options k trên, program s tiếp tc (continue) cho
đến khi đến cui Text String.
Kết cc, ta s có mt Text String đã đuc SpellChecked (sa li chính t) và mt
Dictionary đuc cho thêm mt s ch mi để dùng trong dp ti.
Thiết kế
Trước hết là cách chuyn TextString t Form chánh ca ta qua Form SpellCheck để
nó SpellCheck và khi x lý xong nó return Modified TextString li cho TextBox trong
Form chánh.
Kế đó là nghĩ cách cha các Words trong Dictionary. Cha cách nào để ta làm các
vic sau đây cách hiu năng nht:
Tìm mt ch cho nhanh.
Display các ch tương t nhanh.
Thêm mt ch d dàng và nhanh.
Cách cha Dictionary ít tn ch nht là dùng mt Tree Structure, để tùy theo vic
chn đi dc theo các nhánh nào ca cây ta có nhng ch khác nhau. Cách ny cho ta
thy rõ ràng nht s liên h ca spelling các ch tương t nhau. Mi khi ta thêm mt
ch mi vào trong Dictionary có th là thêm mt nhánh vào Tree. Khi Tree Structure
có sn trong b nh thì làm vic tin lm, nhưng nếu mun lúc cha xung file, và đọc
lên t File cho nhanh thì hơi rc ri.
Có th cách ny tính toán nhanh hơn và ít tn b nh hơn trong ngôn ng lp trình
khác nhưng trong VB6 nó không hn efficient. Du sau đi na, lp trình navigating (đi,
li đây đó) trong Tree Structure cn nhiu Recursive Subs ( nhng Subs gi chính
nó) và không thích hp cho các tay non trong ngh lp trình.
Trong bài ny, chúng ta ch dùng nhng đồ ngh và tiu xo có sn trong mình, đó là
Text File, ListBox và Function InStr.
Dictionary ca chúng ta s gm có 26 hàng Text, mi hàng cha tt c nhng ch bt
đầu cùng mt Alphabet. Tc là hàng th nht cha nhng ch bt đầu bng leter "a"
và hàng cui cha nhng ch bt đầu bng leter "z".
Khi bt đầu ta create sn mt Dictionary File tên words.txt vi content như sau:
are
big
cut
down
entire
fall
go
hall
ink
job
Kid
large
main
narrow
old
partition
quarter
regular
small
to ten the than that thing terrible those thin
unregister
vehicle
who
x
yellow
zone
Chc bn đã để ý, mt khi đã load content ca Dictionary vào ListBox lstWords
(Listbox ny có Property Visible bng False, tc là nó vô hình, User không thy nó), ta
có th tìm đến đúng hàng ca mi alphabet rt d dàng và nhanh. Hãy xem Function
NOTFound dùng để xem mt ch có hin din trong Dictionary như dưới đây:
Function NOTFound(ByVal Word) As Boolean
' See if the given word exists in the dictionary.
' if NOT then display all similar words in the suggested Listbox.
Dim LIndex, Item
' Work out the Index of the Alphabet line in the ListBox lstWords.
' The first line is for "a", the last line is for "z"
LIndex = Asc(UCase(Left(Word, 1))) - Asc("A")
' Prefix and Append the String with spaces.
Item = " " & UCase(lstWords.List(LIndex)) & " "
lstWords.ListIndex = LIndex
' We'll try to locate the Word having a blank space at either end,
' i.e. looking for the pattern of a whole word that is the same as given
word
Word = " " & UCase(Word) & " "
If InStr(Item, Word) = 0 Then
NOTFound = True
' Display similar words
DisplaySuggestedWords Trim(Word), lstWords.List(LIndex)
Else
NOTFound = False
End If
End Function
Ðể khi ln ln Uppercase hay LowerCase ta luôn luôn convert text ra Uppercase
trước khi so sánh. Ðể Search nguyên mt ch (whole word) ta cn phi gn mt blank
space vào phía đầu và phía đuôi ca mt ch, tc là để tìm ch "big" ta phi tìm ch "
big ", nếu không nó ln qua ch "bigger".
Mun thêm mt ch mi vào Dictionary, ta ch cn ráp nó vào cui hàng ch cùng
starting alphabet. Ðể ngc khúc mt hàng ra nhiu ch d dàng ta dùng Class
clsString.
Làm sao ta tìm ra các ch trong Dictionary tương t vi mt ch. Ta định nghĩa hai ch
tương t là khi chúng ch khác nhau mt hai letters thôi, tc là chuyn xãy ra khi có li
chính t.
Ðể so sánh kiu ny ta ln lượt ly tng letter trong mt ch để xem nó có mt trong
ch kia không. Nếu có thì ta rút letter đó ra khi ch kia và ghi nhn có thêm mt letter
ging.
Thí d ta có mt ch dài 6 characters. Ta s ch so sánh nó vi nhng ch trong
dictionaty dài t 4(=6-2) đến 8(=6+2) characters. Mi khi so sánh ta lưu ý ch ngn
hơn, gi d nó dài 5 characters. Như thế nếu hai ch có ít nht 3(=5-2) characters
ging nhau thì là tương t.
Listing ca Function SimilarWords như sau:
Function SimilarWords(ByVal Word, ByVal ILen, ByVal TWord, ByVal Tlen) As
Boolean
' Two words are considered Similar if the shorter word has at least (its
length minus 2)
' characters that are found in the other word.
' In other words, the two words differ only a couple characters at the
most.
Dim L1, L2, W1, W2
Dim i, MatchCount, Pos
' Identify the shorter Word and its length
If ILen > Tlen Then
L1 = ILen
L2 = Tlen
W1 = UCase(Word)
W2 = UCase(TWord)
Else
L1 = Tlen
L2 = ILen
W1 = UCase(TWord)
W2 = UCase(Word)
End If
MatchCount = 0
' Iterate through each character of the shorter word, i.e. W2
For i = 1 To L2
' Locate a character of W2 in W1
Pos = InStr(W1, Mid(W2, i, 1))
If Pos > 0 Then
' Increment the number of same characters
MatchCount = MatchCount + 1
' Temporary remove the matched character from W1
W1 = Left(W1, Pos - 1) & Mid(W1, Pos + 1)
End If
Next
If MatchCount >= (L2 - 2) Then
SimilarWords = True
Else
SimilarWords = False
End If
End Function
Khi lit kê các ch tương t trong ListBox lstSuggested, ta cho các ch gn ging
nht lên đầu. Nhng ch gn ging là nhng ch ch khác có 1 hay 2 letters vi ch ta
đang x lý. Trong program ta dùng ba SORTED Listboxes TList(1), TList(2) và TList(3)
để cha các ch có cùng chiu dài hay dài/ngn hơn 1,2 characters (so vi ch ta
đang x lý) để cha các ch tương t tm thi. Sau đó ta copy chúng vào
lstSuggested.