0

下面是我为RichTextBox派生类编写的三个方法,它是一个语法高亮。Richtextbox 的当前行有一个共享副本,lcpy_strLine全部大写。这些方法的作用是;

  • ColorInsideTwoChars将两个指定字符之间的字符着色为指定颜色。前任。ColorInsideTwoChar("(", ")", Color.Green)将为当前行中的所有括号集将两个括号之间的所有字符着色为绿色

  • ColorTilNoNumFromChar颜色,从指定字符开始,所有为数字的字符,例如。ColorTilNoNumFromChar("G", Color.Red)遇到 G 后会将所有数字着色为红色(包括 G)

  • 如果指定字符后面没有字母,则ColorCharIfNotFollowedByLetter为指定字符着色。前任。ColorCharIfNotFollowedByLetter("x", Color.Orange)会将所有 X 后面没有字母的橙色着色

我的问题是,是否有更快的方法来执行这些方法。它们看起来很丑,我认为这些方法肯定有更简单、更美观的方法。有什么建议么?我问是因为这些方法在几千行文件的每一行上运行并且非常慢。我需要加快他们的速度。我可以尝试以不同的方式重写它们中的每一个,或者我可以让一些聪明人尝试引导我朝着正确的方向前进。

    private void ColorInsideTwoChars(String car1, String car2, Color clr)
    {
        int indx1 = 0;
        int indx2 = 0;
        while ((indx1 = lcpy_strLine.IndexOf(car1, indx1)) != -1
                && (indx2 = lcpy_strLine.IndexOf(car2, indx2)) != -1
                && indx1 < indx2)
        {
            SelectionStart = m_nLineStart + indx1;
            SelectionLength = (indx2 - indx1) + 1;
            SelectionColor = clr;
            indx1 = ++indx2;
        }
    }
    private void ColorTilNoNumFromChar(String car, Color clr)
    {
        int indx1 = 0;
        while ((indx1 = lcpy_strLine.IndexOf(car, indx1)) != -1)
        {
            int j = 0;
            for (j = indx1 + 1; j < m_nLineLength; j++)
            {
                if (!Char.IsDigit(lcpy_strLine[j]))
                    break;
            }
            SelectionStart = m_nLineStart + indx1;
            SelectionLength = j - indx1;
            SelectionColor = clr;
            indx1 = j;
        }
    }
    private void ColorCharIfNotFollowedByLetter(String car, Color clr)
    {
        int indx1 = 0;
        while ((indx1 = lcpy_strLine.IndexOf(car, indx1)) != -1 &&
            indx1 + 1 < m_nLineLength)
        {
            SelectionStart = m_nLineStart + indx1;
            SelectionLength = 1;
            if (!Char.IsLetter(lcpy_strLine[lcpy_strLine.IndexOf(car) + 1]))
                SelectionColor = clr;
            else
                SelectionColor = Color.Black;
            ++indx1;
        }
    }
4

2 回答 2

0

至于ColorInsideTwoChar(),请注意,即使它们是嵌套的,您也会对括号之间的内容进行着色,从而导致执行更多次。如果括号(或一般的这些字符)没有正确匹配怎么办?也许找到开头的字符,然后计算它关闭字符并为两者之间的所有内容着色?然后从你有关闭字符的位置开始搜索,并寻找下一个打开的字符。另外,我只会在换行时调用它,不知道你的想法是什么;)也许只在 RichBox 的可见部分首先,然后在背景中为其余部分着色?

for (j = indx1 + 1; j < m_nLineLength; j++)
        {
            if (!Char.IsDigit(lcpy_strLine[j]))
                break;
        }

我会换

while (Char.IsDigit(lcpy_strLine[++j])) ;

虽然它可能或多或少相同......

但我认为你应该等待一些更专业的答案,可能有一些更优雅的方式来做到这一点。

另外,也许在方法的开头找到所有出现的想要的字符,并将它们放入一个数组中,会比一次又一次地查找它们更快吗?

对于更大的文件块,这样做也可能比单行更快......

于 2012-08-21T12:38:32.067 回答
0

1]ColorInsideTwoChars ColorInsideTwoChars将两个指定字符之间的字符指定颜色。前任。ColorInsideTwoChar("(", ")", Color.Green)将为当前行中的所有括号集将两个括号之间的所有字符着色为绿色

这个函数的坏处是IndexOf函数。如果不是更糟,您的表现将是 O(n^2)。你基本上应该做的是:

只读取一次,并将大括号的所有位置存储到一个新列表中。像这样:

var leftList = new List<int>();
var rightList = new List<int>();
for(var i = 0; i < str.Length; i++)
{
   if(str[i] == car1) leftList.Add(i);
   if(str[i] == car2) rightList.Add(i);
}

if(leftList.Length != rightList.Length) { /*possible error or no?!*/ }
//now start going like this:
int index1 = leftList.Length - 1;
int index2 = 0;
while(index1 >= 0 && index2 < rightList.Length)
{
  //do your coloring here.
  index1--;
  index2++;
}

这将比你现在的要快得多。虽然你会交易一点记忆,但没关系。我建议您将这些列表作为类的变量而不是方法。还要确保默认情况下它们通常足够大,因此不会发生分配。在下一次迭代中,使用Clear().

2]ColorTilNoNumFromChar颜色,从指定字符开始,所有字符为数字,例如。ColorTilNoNumFromChar("G", Color.Red)遇到 G 后会将所有数字着色为红色(包括 G)

我不会这样写,但更长的是:

for(var i = 0; i < str.Length; i++)
{
   if(str[i] == "G")
   {
      int selectionStart = i + 1;
      int selectionLength = -1;
      for(var k = i + 1; k < str.Length; k++)
      {
         if(IsDigit(str[i]))
         {
            if(selectionLength == -1) selectionLength = 0;
            selectionLength++;
         } else break;
      }
      //look if selectionLength is not -1
      i = k;//advance.
   }
}

从你的最后一个开始,你也有IndexOf可能被淘汰,从而产生更多的性能。

而且,如果您分别运行这些方法(每个方法),那么它就是一个诺诺。你应该一次做所有事情(会更难,但要快得多)。

于 2012-08-21T12:53:03.887 回答