文本比对-中文看打测试程序设计中的“对、错、漏、多”

默认分类 | 2021-05-26 20:34:33 | 阅读 107 次 | 评论(0)
     第一部分  鉴别
    因为程序在“打字时段”,对打字的“进度”和“对错”等都没有“实时监测”,所以,在15分钟后,需通过“样张文本”和“打字文本”的比对来进行批改。
    批改的最起码的要求,就是在2个文本中,每个字都须定性为“正确”或“不正确”(样张中的“不正确”,意思是指“没有被正确地打出来”,下同)。“正确”的3个原则是:1.(两个文本中的正确字)一一对应。 2.不能颠倒顺序。3.选“给分最多”的方案。
例1:样张是“他叫英白罗”,打字是“他叫罗英白”。正确(给分)字是4个:“他叫英白”。“罗”不给分,正是为了满足这3个原则。
    这样一来,就必须注意:为了符合第1、2原则,两个文本中已经“定性”的字符,不可以再参与比对。(其左边的字,也不可再参与比对。)
    文本比对的基本操作,其实是单个文字(字符)的比对,而这种比对,只能判断两个字“是否相同”(并非正确与不正确,见“罗”字)。怎样才能批改出“正确”与“不正确”,甚至“对、错、漏、多”呢?我觉得,按怎样的规则来取出比对的“字”(出字顺序),是关键。
    我的方法是:把“录入文本”中的每一字(zn2) ,按从先到后(就是从左到右)的顺序,拿出来与样张中的字(zn1)比对。必须等到zn2定性后,才可以取出下一个来。
    那么,zn1是按什么顺序来取出的呢?
    zn1 是样张里“还没有定性的、最左面的字”。或者说,zn1左面的字都是已经定性了的字;zn1及其的右面都是还没有定性的字。
    比对的语句,在不同的编程语言里会不同,但意思都是:如果 zh1 与 zn2 相同,那么怎样怎样;否则怎样怎样。    (不同的编程语言中,“从字串中取出字符”的方法各不相同,在VB里有现成的函数。)
    zn1与zn2比对时,会有以下几种情况:
    如果zn1与zn2相同,那么,2个都是正确字。这种情况是大多数,除非打得“一塌糊涂”。我称之为“第一种情况”,我会在插图中zh2的下面用①标出来。
    如果zn1与zn2不相同,那么,接着把zn2与“zn1右面的字”顺序、逐个地进行比对,这过程中,又有2种情况,一种是:直至样张结束,都没遇到与zn2相同的字,这时,zn2肯定是不正确的字,而zn1不能肯定。我用②来标志。这种情况是少数。典型的例子就是“全中文的样张却打了一个拼音或英文字母”。
★而比较复杂的是,在zn1右面(移过了若干个字,我用K来计数)找到了与zn2相同的字我称为“第3种情况”(比如例1“罗”,还有例3、例4) 。
那么,例3中的“到”(和例4中的“旅”)是否是正确的字呢,依据“正确字”的第3个原则,这还需进一步的“计算”,在这里由于比较简单,可以知道“到”、“旅”是正确字(样张里的字我标为z3),我用“③1”标志这个结果。而在“例1”中,“罗”却不是正确字。我用“③2”标志这个结果。“③2”与②的效果★完全一样。
注意★:如果是“第3种情况”,就必须要进一步计算究竟是③1还是③2,这正是程序中的难点。关键是要遵循第3个原则:“给分最多”。在我以前的博文中,有比较详细的叙述,由于这涉及到“最长公共子序列”、“动态规划”、“递归函数”等等问题,这里不再赘述。
★这里特别要指出的是,根据原则2.不能颠倒顺序。 ,例3样张中的“带孙子”就定性为“不正确”了,我用K来记录其字数,例3中K=3,例4中K=4。
如果经过进一步的计算,找到的字并不是zn2的对应字(例1中的“罗”),那么就把这个字【当作是“与zn2不同的字”】(不能称为z3),继续往样张的后面找,找到,就再计算……。如果直到样张的最后都不能得到③1的结论,那么zn2就定性为“不正确”,zn1不能肯定,就跟②一样,我标志为③2。
    至此,我们可以归纳一下“正确字”、“不正确字”的“来历”:
    “正确字”----------①、③1。 
    “不正确字”----:
    打字文本那里“不正确字”--------由②、③2情况产生,连续的不正确字数可以通过一个一个累加而得到(我用Tmp来表示,见流程图)。
    这些字(Tmp)有2个转变,在例1、例2中转为“多(蓝色)”;在例4中转为“错2(红色)”;
    样张那里“不正确字”--------由③1情况产生,每次连续的部分用K记录,见“第3种情况”的例3的说明。
    这些字(K)也有2个转变,在例3中转为“漏(绿色)”;在例4中转为“错1(红色)”。
    那么,“不正确字”又是怎么转变为“多、漏、错”的呢?我们借助于彩色图 例1-例4,可以得出规律来: 
    多----见图例1: 遇到①时, Tmp>0。(Tmp>0,K=0)(纯多)。看流程图中的“差异结束a”。
    漏----见图例3: 遇到③1时,Tmp=0。 (Tmp=0,K>0) (纯漏)。看流程图中的“差异结束b”。
    错----见图例4: 遇到③1时,Tmp>0。 (Tmp>0,K>0) (又多又漏。把“鳌”错打成“鳖”,也可以说“漏了‘鳌’”、“多了‘鳖’”)。也可以看流程图中的“差异结束b”。
    我们也可以梳理一下两个文本的“出字顺序”:(用n1、n2来表示zn1和zn2的位置)
对于打字文本,我们已经说过了:定性一个,取出下一个,都是 n2+1。(看流程图)
而对于样张,要看3种情况:(看流程图)
① ----zn1、zn2 都正确,下一个字是:   n1+1;、n2+1
②或③2----zn2“不正确”,n2+1。        (zn1不能肯定,不取出下一个字: n1不动,不做 n1+1 ) 
③1----zn2、z3正确,zn1和它到z3之前共有K个字都不正确。下一个字是: n1+K+1 ,n2+1。(漏打、打错,正是由此而查出来)
   要是你能把例1-4中的字,放到流程图里走一遍的话,你就会对此主题有更好的理解。而且对于我第二部分中的“左右正误对照”,阅读起来会更容易一些。
      第二部分  应用
   我们先看一下程序批改后的界面。一是“错、漏、多”字符标上了不同的颜色,二是★“左右正误对照”的那个“下拉列表”。当选择某一项时,会自动找到相应的字并选中。
   标色和选中都需要2个数据:1.发生差异的起始位置(QD长整型),2.不正确字串的长,就是前面提到的Tmp、K(CD整型)。由于不同的文本(样、录)和不同的错误点,这2个数据都不同,所以2个都是二维的数组。
   第一维的值只有0和1,分别表示“样张”和“打字”。由于错误的次数不能预先确定,所以采用“动态数组”,并将“错误次数mn”放在最后一维(第2维)。
   QD()  和  CD()   (中文“起点”和“长度”的拼音首字母)
  1.起点(QD):请看流程图中的“差异开始”位置,就是“zn1 与 zn2 不同,而且之前‘Tmp=0’ ”,(由‘对’转‘错’)的时候。
        If zn1 <> zn2 Then  
            If Tmp = 0 Then
                mn = mn + 1'    增加(mn)发生差错的次数
                ReDim Preserve QD(1, mn)'  起点,保留数据的重定义,增加上限
                ReDim Preserve CD(1, mn)'  长度,……
                QD(0, mn) = n1'  记录在样张的起点n1
                QD(1, mn) = n2'  记录在打字的起点n2
            End If
        End If
   2.差异长度(CD):(Tmp、K)请看流程图中的“差异结束a、b”。
   在a:        If  Tmp > 0 Then
                      CD(0, mn) = 0'  0记录在样张的错误长度。  这个地方只有“多”的错误。
                      CD(1, mn) = Tmp'  1记录在打字的错误长度
                      ComErr.AddItem "No." & Right("0" & Trim(Str(mn)), 2) & "  多" & Tmp ' & " 字"
                   '上面这句是在下拉列表ComErr中添加项:   “No.0X  多  X  字”
                      Tmp = 0
                  End If
         ★左右2个文本文字的关联,就是“错误序号 mn”,下拉列表其实就是选某个序号。

   在b: 前面说过,错---(Tmp>0 而且 K>0)。漏---(Tmp=0  而且  K>0)

  VB 代码:              CD(0, mn) = K ' 样张

                             If   Tmp > 0 Then' 错
                                  CD(1, mn) = Tmp  '录入
                    ComErr.AddItem "No." & Right("0" & Trim(Str(mn)), 2) & " 错" & K & "--" & Tmp ' & " 字"
                                 Tmp = 0
                                 K = 0
                            Else'  漏,Tmp=0
                                CD(1, mn) = 0  '录入
                    ComErr.AddItem "No." & Right("0" & Trim(Str(mn)), 2) & "  漏" & K '& " 字"
                            End If '

    ★通过上面的 1.和 2.,就把数据储存到2个数组 QD()、CD() 以及 下拉控件中保存起来了。

只要在下拉列表中选择某一项(mn),就可以完成这个“错误点”的左右两边的选中、对照了。

    至于在不正确的字符上标志颜色,就比较容易了。用循环的方式。循环次数就是最大错误数。这里不再赘述了。
     不好意思,博文中插入了一些 VB 代码。即使是自己写的代码,时间久了,都会忘记初衷。不熟悉VB的更会“云里雾里”。

流程图.png (上传于2021-05-26 21:19:15)
流程图.png

例1-例4.png (上传于2021-05-26 20:34:33)
例1-例4.png

 

批改后.png (上传于2021-05-26 20:34:33)
批改后.png

文章评论,共0条
游客请输入验证码
浏览59339次
文章分类