以下是我为RichTextBox
派生类编写的三种方法,它是一种语法高亮显示。所有大写字母的richtextbox的当前行都有一个共享副本lcpy_strLine
。这些方法的作用是什么;
ColorInsideTwoChars 为指定颜色指定两个指定字符之间的字符。防爆。对于当前行中的所有括号组,ColorInsideTwoChar("(", ")", Color.Green)
会为两个括号绿色之间的所有字符着色
ColorTilNoNumFromChar 颜色,来自指定字符,所有字符都是数字,例如。遇到G后,ColorTilNoNumFromChar("G", Color.Red)
将为所有数字着色,红色(包括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;
}
}
答案 0 :(得分:0)
对于ColorInsideTwoChar()
,请注意,即使它们是嵌套的,您也会对括号中的内容进行着色,从而使其更多一次。如果括号(或一般的这些字符)不匹配怎么办?也许找到开头的字符,然后把它关闭char并将颜色之间的所有内容染色?然后从你关闭char的位置开始搜索,并寻找下一个开放的一个..而且,我只会在换行时调用它,不知道你的想法是什么;)并且可能只在RichBox的可见部分开始,然后在后台为其余颜色着色?
for (j = indx1 + 1; j < m_nLineLength; j++)
{
if (!Char.IsDigit(lcpy_strLine[j]))
break;
}
我会换掉
while (Char.IsDigit(lcpy_strLine[++j])) ;
虽然它可能或多或少相同......
但我认为你应该等待一些更专业的答案,这可能是一些更优雅的方法。
另外,也许,在方法开头找到所有想要的字符,并将它们放入数组中,会比一次又一次地查找它们更快?
对于较大的文件块,这可能比单行更快......
答案 1 :(得分: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
颜色,来自指定字符,所有字符都是数字,例如。遇到G后,ColorTilNoNumFromChar("G", Color.Red)
将为所有数字着色,红色(包括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
可以被淘汰,从而产生更多的表现。
如果你分别运行这些方法(每个方法),那么它就是nono。你应该立刻做所有事情(会更难,但要快得多)。