65.9K
CodeProject 正在变化。 阅读更多。
Home

EDX 拼写检查器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (14投票s)

2006 年 7 月 9 日

CPOL

15分钟阅读

viewsIcon

82684

downloadIcon

1885

为您的程序添加拼写检查单词和进行拼写猜测的功能。

引言

此包为您提供了拼写检查单词的功能,以及在遇到拼写错误的单词时,可以建议用户可能想要输入的正确单词(拼写猜测)的功能。它还支持用户个人的辅助词典。提供了一个美式英语词汇表,并提供了在其他语言中创建词汇数据库的说明。如果您想将此拼写检查器代码移植到其他操作系统,也提供了指南。该代码已有多年历史,已被证明非常快速稳定。我将这个拼写检查器称为 EDX。

EDXSPELL.DLL

edxspell.dll 包含以下四个例程

edx$dic_lookup_word 检查单词的拼写。您提供一个单词,它将返回一个值,指示该单词是否拼写正确。它首先通过检查 EDX 词汇数据库(即“词典”),然后检查用户的个人 Aux1 词典来实现。如果找到该单词,则返回 EDX__WORDFOUND。如果找不到该单词,则返回 EDX__WORDNOTFOUND
edx$spell_guess 猜测用户想输入的单词。如果 edx$spell_guess 返回 EDX__WORDNOTFOUND,您就可以通过反复调用 edx$spell_guess 来获取用户可能想输入的单词。每次调用 edx$spell_guess 都会返回一个与传递给 edx$dic_lookup_word 的拼写错误的单词相似的、拼写正确的单词。您可以继续调用 edx$spell_guess,直到 edx$spell_guess 返回 EDX__WORDNOTFOUND,表示没有更多建议。
edx$add_persdic 将单词添加到用户的个人辅助词典。用户的个人辅助词典是一个纯文本文件,每行一个单词。用户也可以使用普通文本编辑器编辑此文件来添加或删除单词。
edx$dll_version (返回 edxspell.dll 的版本号。如果已加载 EDX 词典和用户的个人辅助词典,还会返回有关它们的信息。)

edx$dic_lookup_word

edx$dic_lookup_word

您将一个单词传递给 edx$dic_lookup_word,它将返回一个值,指示该单词是否拼写正确。

int edx$dic_lookup_word(char *spellwordptr,
                        char *errbuf,
                        int errbuflen,
                        char *Dic_File_Name,
                        char *Aux1_File_Name);

char *spellwordptr

您要检查拼写的单词(指向 ASCIIZ 字符串的指针)。此字符串应仅包含单词。任何前导或尾随空格都不会被自动去除。您需要自己去除任何前导或尾随空格。单词的大小写(大写或小写)无关紧要。(edx$dic_lookup_word 会在词汇数据库中查找之前,将其复制为小写。)

char *errbuf

int errbuflen

您提供一个错误缓冲区,用于写入错误消息。提供一个指向缓冲区的指针,并提供缓冲区的长度。一种您会收到错误消息的情况是,如果 EDX 词汇数据库文件(即“词典”)找不到。在这种情况下,返回 errbuf 中的错误消息将类似于

"Error opening C:\Program Files\Multi-Edit 2006\EDXDIC.DIC
 Error is: 2: The system cannot find the file specified."

您需要自行将错误消息显示给用户。

char *Dic_File_Name

包含词汇数据库文件名(ASCIIZ 字符串)。这通常是完整路径/文件名,例如 Dic_File_Name = 'C:\Program Files\Multi-Edit 2006\EDXDIC.DIC'。如果您只指定 "EDXDIC.DIC",则会搜索当前目录。如果找不到文件,edx$dic_lookup_word 将返回 EDX__ERROR,并将错误消息放入 errbuf

如果您愿意,可以将 EDXDIC.DIC 重命名为其他名称(例如 EDX_DICTIONARY.DAT)。只需在此处指定新名称即可。

在第一次调用 edx$dic_lookup_word 时,将在内存中映射 Dic_File_Name 中指定的词汇数据库文件。一旦词汇数据库文件加载完毕,Dic_File_Name 的值将在所有后续调用中被忽略。

char *Aux1_File_Name

包含用户个人辅助词典文件名(ASCIIZ 字符串)。如果用户没有个人辅助词典文件,您可以使用空字符串。这通常是完整路径/文件名,例如 Aux1_File_Name = 'C:\Program Files\Multi-Edit 2006\EDXAUX1.TXT'。如果您只指定 "EDXAUX1.TXT",则会搜索当前目录。如果指定了文件但找不到,则会创建该文件。

用户的个人辅助词典文件是一个纯文本文件,每行一个单词。用户可以使用普通文本编辑器编辑此文件来添加或删除单词。您也可以使用 edx$add_persdic 函数将单词添加到此文件。

在第一次调用 edx$dic_lookup_word 时,将在内存中加载 Aux1_File_Name 中指定的用户的个人辅助词典(除非传递了 NULL 字符串,在这种情况下将跳过此步骤)。一旦用户个人辅助词典加载完毕,Aux1_File_Name 的值将在所有后续调用中被忽略。

返回值

将以下三个定义添加到您的代码中

#define EDX__WORDFOUND 1
#define EDX__WORDNOTFOUND 2
#define EDX__ERROR 4

这三个是可能返回值。请注意,EDX 之后有两个下划线字符。如果返回值是 EDX__ERROR,则 errbuf 将包含有关错误的更多信息。您需要自行将此错误消息显示给用户。

讨论

在第一次调用 edx$dic_lookup_word 时,将打开并映射由 Dic_File_Name 指定的主词典,如果 Aux1_File_Name 不是 null 字符串(""),则会简要打开该文件并将其读入内存。然后,将在主词典和用户的个人辅助词典中搜索 spellwordptr 中的单词以进行拼写检查。如果找到该单词,则返回 EDX__WORDFOUND。如果未找到该单词,则返回 EDX__WORDNOTFOUND

注释

  • 拼写检查零长度字符串将返回 EDX__WORDFOUND
  • 词典不能存储超过 31 个字符的单词。
  • 您需要自行去除要拼写检查的单词前导和尾随空格,然后再将其传递给 edx$dic_lookup_word
  • 如果需要,您可以通过拼写检查零长度字符串来初始化拼写检查器,将 EDX 词典文件 Dic_File_Name 和可选的用户个人词典文件 Aux1_File_Name 的名称传递给 edx$dic_lookup_word。然后,您可以在所有后续调用 edx$dic_lookup_word 时使用 NULL 字符串作为这两个参数,因为在所有后续调用中将忽略这两个参数。

edx$spell_guess

edx$spell_guess

每次调用 edx$dic_lookup_word 都会设置拼写猜测。传递给 edx$dic_lookup_word 的单词会被保存,并初始化拼写猜测。如果该单词拼写错误,您就可以通过反复调用 edx$spell_guess 来获取用户可能想输入的建议单词。(即使单词拼写正确,您也可以进行这些调用,但我不知道为什么有人会费事。)每次调用 edx$spell_guess 都会从主 EDX 词典或用户的个人辅助词典中返回一个与传递给 edx$dic_lookup_word 的拼写错误的单词相似的、拼写正确的单词。您可以继续调用 edx$spell_guess,直到 edx$spell_guess 返回 EDX__WORDNOTFOUND,表示没有更多建议。

int edx$spell_guess(char *guessword, char *errbuf, int errbuflen);

char *guessword

指向您提供的用于接收猜测单词的缓冲区的指针。该缓冲区应足够大,可以容纳一个 31 个字符的单词(不要忘记末尾的 NULL 字节,所以需要 32 个字节)。

char *errbuf

int errbuflen

您提供一个错误缓冲区,用于写入错误消息。提供一个指向缓冲区的指针,并提供缓冲区的长度。(我建议错误缓冲区大小约为 400 个字符。)我所知道的唯一一种会收到错误消息的情况是,EDX 词汇数据库文件(即“词典”)位于远程计算机上,并且与该远程计算机的网络连接丢失。在这种情况下,返回 errbuf 中的错误消息将是

"EDXspell.dll encountered
error EXCEPTION_IN_PAGE_ERROR. This error can 
occur if the EDX dictionary file is on a
remote computer and the network connection 
to that remote computer is lost."

您需要自行将错误消息显示给用户。(您不必显示它。您可以将此错误视为 EDX__WORDNOTFOUND 返回,然后停止拼写猜测。在这种情况下,您可以指定 errbuflen = 0 并且不接收错误消息,因为您不会显示它。)通常,EDX 词典文件与程序在同一台计算机上,这不成问题。

返回值
EDX__WORDFOUND     - guessword is filled with another guess word.
EDX__WORDNOTFOUND  - all out of guesses.
EDX__ERROR         - EXCEPTION_IN_PAGE_ERROR (see above).

以下是 edx$spell_guess 进行拼写猜测的大致流程

  1. 反转(测试字符转置)
  2. 元音(测试使用了错误的元音)
  3. 减去字符(测试单词中多余的字符)
  4. 加上字符(测试单词中缺少字符)
  5. 辅音(测试使用了错误的字符)
  6. 放弃(放弃)

代码会注意不要猜测同一个单词两次。

edx$add_persdic

edx$add_persdic

将单词添加到用户的辅助个人词典。用户的个人辅助词典是一个纯文本文件,每行一个单词。用户也可以使用普通文本编辑器编辑此文件。

char *newword

您想添加到用户个人辅助词典的单词(指向 ASCIIZ 字符串的指针)。在添加到文件之前,会去除前导和尾随空格并将单词转换为小写。生成的单词长度不能超过 31 个字符。

char *errbuf

int errbuflen

您提供一个错误缓冲区,用于写入错误消息。提供一个指向缓冲区的指针,并提供缓冲区的长度。您需要自行将错误消息显示给用户。(我建议错误缓冲区大小约为 400 个字符。)

返回值
  • EDX__WORDFOUND - 成功将单词添加到用户的个人词典。
  • EDX__ERROR - 添加单词到用户的个人词典时出错。错误文本在 errbuf 中。

edx$dll_version

edx$dll_version

返回一个包含信息的长字符串。字符串可能看起来像

EDX Spelling Checker file edxspell.dll version 7.2 November 26, 2006.
EDX dictionary file is version 5 (Extended ANSI character compatible)
There are no extended ANSI characters in the dictionary.
Extended ANSI Guessing is: OFF.
User's personal auxiliary dictionary file is: EDXMYAUX1DIC.TXT

char *buf

int buflen

您提供一个缓冲区,用于写入版本消息字符串。提供一个指向缓冲区的指针,并提供缓冲区的长度。(我建议缓冲区大小约为 550 个字符。)

运行演示

尝试演示

  1. 下载 演示
  2. 阅读 "0Readme EDX Spellchecker Demo.txt" 文件。

使用代码

如果您正在拼写检查缓冲区,那么您将编写的代码的大致轮廓将是

  1. 解析出下一个单词。
  2. 调用 edx$dic_lookup_word 来拼写检查该单词。
  3. 如果 edx$dic_lookup_word 返回 EDX__WORDNOTFOUND,则声明该单词拼写错误,并通过反复调用 edx$spell_guess 来向用户提供建议,直到 edx$spell_guess 返回 EDX__WORDNOTFOUND(表示没有更多猜测单词)。

这是一个拼写检查 testword 的伪代码示例

status = edx$dic_lookup_word(testword,errbuf,errbuflen,edxdic);

switch( status )
{
   EDX__WORDFOUND:
      //Good. Word is correctly spelled.
      break;
   EDX__WORDNOTFOUND:
      //Word misspelled. Let's spell guess.
      while (EDX__WORDFOUND == (guess_status =
             edx$spell_guess(ResultBuf, errbuf, errbuflen)))
      {
         //ResultBuf contains a guess word.
         <Display guess word to user.>
      }
      //When we drop out here
      //guess_status is either EDX__WORDNOTFOUND
      //indicating no more guesses
      //or EDX__ERROR (which is very unlikely)
      if (guess_status == EDX__WORDNOTFOUND)
      {
         //No more guesses.
      }
      else if (guess_status == EDX__ERROR)
      {
         <Bad. Display error message and stop spell checking.>
      }
      break;
   EDX__ERROR:
     <Bad. Display error message and stop spell checking.>
     break;
}

一个简单的有效示例,请参阅 "CallEdxSpell Source" 文件夹中的 "CallEdxSpell.cpp" 文件,该文件来自 源文件下载

将拼写检查器添加到程序中的注意事项

解析出下一个单词

您需要为 edx$dic_lookup_word 提供单词,所以如果您要拼写检查缓冲区,则必须编写一些代码来解析出下一个要拼写检查的单词。有关一些建议,请参阅 源文件下载 "Documentation" 文件夹中的 "Parsing off words.txt" 文件。

用户的个人辅助词典

该代码现在支持可选的用户个人辅助词典(也称为“用户 Aux1 词典”或“用户 Aux1 词汇数据库”)。这是一个纯文本文件,每行一个单词。文件内容在第一次调用 edx$dic_lookup_word 时加载。加载时会去除前导和尾随空格,并将单词转换为小写。生成的单词长度不能超过 31 个字符。如果 edx$dic_lookup_word 在加载用户个人辅助词典时发现长度超过 31 个字符的单词,则会返回错误消息。

在拼写检查单词和进行拼写猜测时,都会检查用户个人辅助词典中的单词。

跟踪拼写更正

进一步的增强功能是跟踪所做的拼写更正。如果用户拼写错误了一个单词,并从您的猜测单词列表中选择了一个拼写正确的单词,那么您可以保存该更正。如果您再次遇到同一个拼写错误的单词,可以提供相同的更改。(EDX 拼写检查器不会为您完成此操作。)

性能速度

这个拼写检查器已被证明速度很快。EDX 拼写检查器速度快的秘诀是将页面错误降至最低。EDX 词汇数据库文件的设计反映了这一目标,通过将内存读取保持在彼此靠近的位置。有关词汇数据库文件布局以及如何优化它的更多信息,请参阅 源文件下载 中的 "Lexical Database File Layout.txt" 文件。有关页面错误是什么以及为什么对程序执行速度有深刻理解至关重要,请参阅 源文件下载 "Documentation" 文件夹中的 "PAGE_FAULTS_AND_ARRAY_ADDRESSING.TXT" 文件。

加载词汇数据库文件

速度的另一个秘诀是将词汇数据库文件(“词典”)映射到虚拟内存,而不是读取它。可以通过先分配足够的内存来容纳文件,然后将整个文件读入已分配的内存来加载词典。由于数据库的体积庞大,这会非常慢。此外,用户的页面文件配额限制了用户可以分配的总内存量,而容纳数据库文件所需的内存量相当可观。

为此,我们使用系统服务调用 Microsoft Windows 操作系统提供的函数 CreateFileMappingMapViewOfFile 来加载词典文件。CreateFileMappingMapViewOfFile 完成了分配内存然后将文件读入内存的相同结果,但它们从不从系统分配内存,也从不读取文件。相反,它们将进程区域扩展到文件 EDXDIC.DIC(“词典”,即词汇数据库文件)的大小,从而立即提供新的虚拟内存,然后声明物理文件 EDXDIC.DIC 本身是该内存段的只读分页文件。初始化现在已完成,几乎没有工作。

现在,当程序尝试读取该内存范围中的字典部分时,如果该页面不在内存中,则会发生页面错误,并且该页面会自动读入内存。由于我们没有为此使用系统分页文件,因此用户的页面文件配额不受影响。

如果对文件 EDXDIC.DIC 进行碎片整理,也有助于提高性能,因为它被用作分页文件。

提供英语词汇数据库

提供了一个美式英语词汇数据库,包含 90,000 多个单词。已尽一切努力确保所有单词都拼写正确。

其他语言

如果您愿意,也可以创建其他语言的词汇数据库。您只需要提供一个包含您想要的任何语言的所有单词的文件。唯一的限制是最大单词长度为 31 个字符,并且文件必须按字节值排序。(这是通常的排序顺序,我们关注每个字节的无符号值,而不是字节代表的字符。)以下是一些可以获取词汇表的地方的链接。

其他语言的词汇表(包含单词列表的文件)可以在 SourceForge 找到。(请参阅 SCOWL - Spelling Checker Oriented Word Lists)

请注意,上述网站上的词汇表包含许多字典中找不到的单词!(它们包含许多拼写错误的单词,或者实际上应该是连字符或两个单独的单词。我的词汇表 EDX_DICTIONARY.TXT 已经做了大量工作来确保其中的单词拼写正确。)

另一个提供各种语言词汇表的网站是:WinEdt Dictionaries

有关创建 EDX 词汇数据库文件和优化 EDX_COMMONWORDS.TXT 文件的更多信息,请参阅 源文件下载 "Build EDX Dictionary Source" 文件夹中的 "0Readme EDXBuildDictionary.txt"。

更新: 代码已更新,可处理所有 ANSI 字符 128 - 255。因此,它现在可以处理以下字符:š œ ž ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ 有关此信息的更多信息,请参阅 Documentation 文件夹中的文件 "EDX Using Extended ANSI Characters.txt" 和 "EDX lowercasing extended letters.htm"。

其他操作系统

如果您希望将此代码移植到 Microsoft Windows 以外的其他操作系统,请参阅 源文件下载 "Documentation" 文件夹中的文件 "Porting EDXspell to other operating systems.txt"。(该代码最初是为 VMS 操作系统编写的,后来修改为适用于 Microsoft Windows。)

历史

  • EDX 是我多年前在 TPU 中为 VMS 操作系统编写的一个文本编辑器,当时恐龙还在漫步。
  • 1990 年 3 月 - 我从零开始用 VAX Macro 汇编语言编写了原始拼写检查器代码。
  • 1993 年 7 月 - 由于 VAX Macro 过时,被迫将代码转换为 C 语言。
  • 2004 年 3 月 - 将 C 代码转换为适用于 Microsoft Windows,以便我可以在(Multi-Edit 文本和代码编辑器)中添加拼写检查器(请参阅 此链接)。(在 Windows XP、Windows 2000 和 Windows ME 上测试过。)
  • 2006 年 7 月 - 将代码提交给 The Code Project。我多年来一直在使用此拼写检查器代码,没有遇到任何问题。代码稳定且速度快!如果您使用此代码,请将功劳归于我,我只要求这一点。
  • 2006 年 11 月 - 添加了对扩展 ANSI 字符的支持(ASCII 值大于 127 的字符,带重音符号的字符,例如法语中的字符)。
  • 2006 年 11 月 - 添加了对用户个人辅助词典文件的支持。

词汇表

  • ASCIIZ - 以零结尾的字符字符串。C 和 C++ 编程语言中使用的字符串类型。
  • 词典 - 技术上讲,“词典”应包含单词的定义。然而,对于拼写检查器来说,通常会说“词典”,而实际上我们指的是“词汇表”或“词汇数据库文件”。
  • 词汇表 - 包含单词列表的文件。
  • “EDX 词典”也称为“EDX 词汇数据库文件”。两者都指文件 EDXDIC.DIC。(说“词典”比说“词汇数据库文件”更简洁。您也可以将 EDXDIC.DIC 文件名更改为您想要的任何名称。)
© . All rights reserved.