拼写检查器,但语法由您决定






4.97/5 (11投票s)
集成了Hunspell功能的文本框类
更好的拼写
当我看到这篇发表不久的文章 《适用于 .NET 的 C# 和 VB 示例的拼写检查、连字符和同义词库 - 第 1 部分:单线程》 时,我很高兴地发现有一个 DLL 可以实现我多年来一直在努力做的事情。在本文中,我将介绍一个 textbox
对象,它结合了该文章中介绍的一些功能,并介绍我一直在开发的、类似于 Hunspell 产品的一些其他项目,包括一个帮助英语读者解读拉丁语的工具。
首先,神奇的文本框
我将引导您阅读上述文章,以更清晰地解释 Hunspell 在您的程序中是如何使用的,但我想描述这个 textbox
类通过使用而获得的一些很棒的功能。实例化 textbox
就像实例化任何其他动态生成的对象一样。
classTextBoxSpellChecker txtBox = new classTextBoxSpellChecker();
然后,将其添加到您的窗体中,如下所示:
public formRhymes()
{
InitializeComponent();
Controls.Add(txtBox);
我相信大多数程序员对此都很熟悉,所以这没什么难的。它有两个功能,尽管两者都是英文的,但下载您想要的语言文件并更改类中的变量名称都取决于您。
const string en_us_DicFilename = "en_us.dic";
const string en_us_AffFilename = "en_us.aff";
const string th_en_us_idx = "th_en_us_new.idx";
const string the_en_us_dat = "th_en_us_new.dat";
再次强调,有关这些文件的 URL 和查找信息,请参阅上述文章。请注意,这些文件必须存在于您计划使用此 textbox
和 Hunspell 工具的项目的工作目录中。
此 textbox
具有两个主要功能,可以开启或关闭:
bool bolShowSpellChecker = true;
bool bolShowThesaurus = true;
public bool spellChecker
{
get { return bolShowSpellChecker; }
set { bolShowSpellChecker = value; }
}
public bool thesaurus
{
get { return bolShowThesaurus; }
set { bolShowThesaurus = value; }
}
当同义词库开启且 bolShowThesaurus
变量设置为 true
时,textbox
将识别拼写正确的单词,并自动生成光标附近单词的同义词列表,显示在用户当前键入的位置上的 listbox
中。如果用户单击此 listbox
,则先前键入的单词将被所选的同义词替换。一旦用户开始键入另一个单词,即使没有进行选择,此 listbox
也会消失。
当拼写检查器开启时,同一个列表框会出现在光标附近,并显示一个用户可能想要输入的备选拼写列表。用户可以通过区分同义词列表框和拼写检查器列表框的红色/绿色背景色来区分它们:红色表示拼写检查器发出了单词可能拼写错误的警报,绿色表示同义词库,如果您想改进语法。
以上就是关于这部分的全部内容。
... 在本文的其余部分,我将讨论一些不如 Hunspell 强大的搜索树,但实现起来很有趣。所以,如果您只是在寻找一个内置拼写检查器的 textbox
:它就在这里。
我的拉丁语项目
我这几年一直在自学拉丁语,使用 Wheelock's Latin 教材,虽然我仍然不是很好,但我已经大有进步,这得益于我编写的一个程序,它可以对拉丁语名词、形容词和动词进行变格和变位。我花了大约三个月的时间将拉丁语/英语词典输入到一个单独的数据库程序中。词典数据库本身并不是什么了不起的工程奇迹,只是三个月枯燥乏味的打字过程。它完全由文本文件组成。每个文本文件按顺序输入字段,例如“filename
”(一个冗余且无用的字段,导致了更多问题而非解决)、“heading
”、“alt-heading
”、“links
”和“main text
”。文件的“heading
”字段包含拉丁语单词,例如“amo
, -are
”,表示“爱
”的意思,而“main text
”包含该单词的定义。很简单。文件之间的关联是通过“links
”字段实现的,该字段包含与当前文件相关联且指向的文件列表。使用 RecordViewer
,将显示每个文件的内容,并包含通过“links
”字段指向的文件标题,用户可以单击并跳转,显示所选文件。
数据库文件-文本文件网络
因此,在我建立完这个数据库之后,我必须使用搜索算法来组织这些文件。拉丁语词典中有 24,000 个文件,其中并非所有都是拉丁语单词条目,因为有许多文件是我称之为标题文件,使得整个文件网络更容易导航;这些文本文件网络的大小使得发布该项目变得昂贵,而且尽管导航方便,但查找任何条目的困难使得使用该项目(就像使用任何其他词典一样)速度太慢,不值得花时间。所以我需要一个搜索引擎来使这变得更容易。
很简单:以随机顺序对数据库中的每个文件进行采样,解析每个文件的文本内容,并将每个单词插入到二叉树中,使用这些单词作为搜索键向下遍历树。当您发现单词已插入到树中时,使用前端插入指向该特定单词的链接列表,该列表包含网络中包含此特定拼写的文件的文件名。
我真的不想在这里过多地阐述拼写树,但既然我提到了它,而且它是一个非常简单的制作搜索引擎的方法,我认为每个人都应该知道如何制作一个,即使他们已经在使用 SQL 或任何其他数据库软件开发工具包,我会在我闲暇时多谈谈。
二叉树和链表
二叉树从一个根节点开始。每个节点都有指向左子节点和右子节点的指针。最初,这些指针设置为“null
”。每个节点还包含一个称为“搜索键”的内容,用于向下遍历树。要找到您要查找的节点,您从根节点开始,将您的搜索单词与该节点的搜索键进行比较。如果比较结果是“大于”(按字母顺序,对于字母搜索键),则向下移动到“右子节点”,反之,如果“小于”,则向左移动,或者如果两者都不是,则表示您已经到达。您可以向右走以获取更大的,或向左走以获取更小的,或者随便哪种方式都可以,随您喜欢。请记住,对于二叉树:您必须**一致**。
对于搜索引擎,您还需要在每个节点中添加另一条信息:一个指向链表的指针。链表也是非常有用的工具,如果您从未见过它们,那么我将不得不告诉您一些关于它们的事情。链表类似于二叉树,但您可以将其视为没有分支的藤蔓。它有一个头部和一个尾部,每个节点都必须有一个“next
”指针指向另一个节点,即使该指针设置为“null
”。您指向第一个,它指向下一个,下一个指向再下一个,依此类推,直到您到达最后一个指向“null
”的节点。有许多变体,如双向链表,它还有一个“previous
”指针,列表中的这些项彼此指向。或者,循环链表实际上不会结束,因为最后一个节点指向第一个节点,它会不断循环。
搜索引擎
回到搜索引擎并将这个想法放在一边:搜索树中的每个节点都有一个指向自己链表的指针。您向下遍历树直到找到您要查找的单词,检索指向该单词的链表的指针,然后沿着链表移动,读取文件网络中包含您要查找的单词的所有文件名。这有无限多的应用。
好的,现在我们(实际上是“我”)有一个拉丁语词典和一个快速查找内容的方法。有了两个独立的文件集,用于标题搜索和完整搜索,可以查找仅出现在单词标题中的单词(就像您使用普通的桌面词典一样)或查找包含在单词定义中的单词的完整搜索。
但这并不能进行变位和变格。
您可能难以置信我花了多少精力才让它正常工作。首先,我自己也是拉丁语新手,所以我实际上并不太懂拉丁语,在学习语言的过程中,我一直在为我的项目添加新功能,以便在学习每个章节时进行变位和变格,两年后最终的成果是一团糟。但整个过程中最困难的部分并不是让它实际执行变格,因为那实际上是容易的部分。不,最困难的部分是教会项目识别它正在查看的是哪种类型的单词。因此,在这两年的学习和向我的拉丁语知识拼布中添加新补丁的过程中,我一直在不断地尝试错误,以找出如何编写代码来始终如一地解析读者当前正在查看的单词类型。因此,当我重写项目并将其从 Visual Basic 2005 转换为 C# 2008 时,我使用旧的 VB 项目将整个数据库,整个拉丁语/英语词典,复制到第二个目录,并在每个文件中包含我知道它们的单词类型,因为我再也不想经历两年多的时间,在我已经让它工作起来之后,仍然不知道它是否正常工作。
您是否感到厌烦?我该怎么用拉丁语说?non gaudes?我不知道……
拉丁语查找表
完成之后,实际上编写代码来变格不同类型的单词就相当容易了。而且,这次我清楚自己要做什么,所以我对 C# 版本进行了更好的组织,并且非常满意。
这并不是全部。一旦我完成了对所有不同类型单词的变格和变位,我就想要一个拉丁语查找表,这样我就可以弄清楚一个单词是什么,无论它是如何拼写的。您看,拉丁语是一种有趣的语言。假设我在翻译的文本中找到了单词“sustulim”,我不认识它或不记得它的意思。我可能会尝试在我的桌面词典中查找“sustulimus”,但在“sustollo”和“susum”之间找不到任何内容,这对我没有帮助,因为它在“t”下列出了“tollo, tollere, sustuli, sublatum”。您看,“sustulimus”是动词“tollo, -ere”的第一人称复数完成主动语态的直陈式,正如您在词典标题中清楚看到的(好吧,如果您对拉丁语一无所知,您就不知道我在说什么;这其实是我的观点:如果您不知道,您永远找不到)。
我需要从这里开始做的是,遍历词典中的每个单词条目,生成所有可能的拼写,并将它们以类似于我为搜索引擎描述的方式插入到查找表中,同时记录生成该特定拼写的手段。
这就是我所做的。
在此图像中,您可以看到我的 LatinExercises
项目,它使用了这个 class_Latin_C#.dll。在实际操作中,这是我最喜欢的 Latin_LUT
。要调出这些窗口,我首先将光标放在句子“Filium nautae Romani in agris videmus”(我们看到田野里的水手的儿子)中的单词“nautae”上,然后按键盘上的 F3 键。首先出现的窗口是我的 LUT-Results 窗口,它列出了该单词条目“nauta, -ae”的特定拼写可以达到的四种不同方式。该名词是阳性,有两个单数形式(属格和与格)和两个复数形式(主格和呼格)。因为它们都是同一个单词的不同拼写方式,所以在其中任何一个上再次按 F3 都会弹出右侧的窗口,显示完整的变格以及一个包含单词定义的选项卡。从 LUT-Results 窗口按 F1 会弹出您看到的最后一个窗口,该窗口显示单词的定义(您可以看到底部的链接已下划线,用户可以沿此导航)以及两个组合框,它们将生成名词和形容词的变格,或动词的几十种变位。
有树,也有子树
我在这里包含了 LUT 的搜索树用户定义类型以及链表的 UDT,因为它们有点特殊。
public struct udtLUTRecord_Bin
{
// main
public int deaccentLeft;
public int deaccentRight;
public string strDeaccentWord;
// sub
public int left;
public int right;
public string strWord;
public int LL;
public bool flag;
}
public struct udtLUTRecord_LL
{
public string filename;
public int next;
public classLatin_C.classLatin_C.enuTypeSolutions typeSolution;
public classLatin_C.classLatin_C.enuCase case_;
public classLatin_C.classLatin_C.enuPerson person;
public classLatin_C.classLatin_C.enuNumber number;
}
拉丁语使用短元音和长元音。初级拉丁语读本教科书使用“长音符号”来区分它们,长音符号是覆盖长字符的横线。由于任何给定单词的许多形式可能存在几种带长音符号的变体,而一种长音符号拼写与另一种拼写之间的差异可能会完全改变短语,因此将这些有序排列很重要。所以 LUT 的二叉树搜索首先使用“去重音”的单词(去除长音符号的单词),直到找到正确的拼写。然后,在这一点上,二叉树的每个节点都关联着另一个子树,这个“子树”保存长音符号(使用带重音的元音字符描述),并搜索该特定的长音符号配置。在 LUT-Results 表单上显示结果时,该子树按顺序遍历,子树的每个节点都有自己的解决方案列表,这些解决方案被显示在屏幕上。
我认为我已经关于这个项目说得够多了;因为它对我自己以外的人几乎没有用处,所以我一直不愿意写一篇关于它的文章(尤其是因为我无法提供代码或数据库,因为我不知道我输入的词典的版权,而且 LUT 文件本身解压后有 1GB 大小),但这样一来,您就得到了一个 textbox
,如果您一直失眠,这应该会有所帮助。
法语?
当这个项目效果很好时,我又在法语和英语中做了同样的事情。对我来说,法语比拉丁语容易得多,因为我实际上会说这门语言,并且发现 Bescherelle 是我能找到的最好的法语烹饪书。所以,除了代词动词和被动语态之外,我的法语词典(完全是法语,1600 页长!)已经变成了一个法语 LUT。有一个法国女孩,我觉得她可能会有兴趣看看那个。我做了英语版的(是的,我有很多空闲时间),现在我将这三个放在一个单独的项目中,使用剪贴板来接收命令,当我使用我的电脑在任何应用程序或互联网上写作时。
剪贴板命令
现在,如果我用键盘上的 CTRL-C 组合键突出显示并“复制”单词“enabledictionary”,那么任何复制到剪贴板的内容都将成为我要求此应用程序查找的单词。就像我说:给我这个单词的定义。但我所做的只是将其复制到剪贴板。这会稍微减慢我的系统速度,因为它每秒都会测试剪贴板,但我写的东西很多,而且我可以随时选择“killdictionary”。我的三个 LUT 都在里面,而且我有多种词典可供选择,考虑到我喜欢写作,它已成为一个我经常使用的强大工具。
我的最新打字项目是一个押韵词典,但我不会打扰您了。
历史
- 2009年11月24日:初始版本