0

以下RichTextBoxは、シンタックス ハイライターである派生クラス用に作成した 3 つのメソッドです。lcpy_strLineすべて大文字のリッチテキストボックスの現在の行の共有コピー があります。これらのメソッドが行うことは次のとおりです。

  • ColorInsideTwoCharsは、指定された 2 つの文字の間の文字を指定された色で色付けします。元。ColorInsideTwoChar("(", ")", Color.Green)現在の行のすべての括弧のセットについて、2 つの括弧の間のすべての文字を緑色にします。

  • ColorTilNoNumFromChar色、指定された文字から、数字であるすべての文字、Ex. 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指定された 2 つの文字の間の文字を指定された色で色付けします。元。ColorInsideTwoChar("(", ")", Color.Green)現在の行のすべての括弧のセットについて、2 つの括弧の間のすべての文字を緑色にします。

この関数の悪い点はIndexOf関数です。あなたのパフォーマンスは、悪くなければ O(n^2) になります。あなたが本質的にすべきことは、次のとおりです。

行を 1 回だけ読み取り、中括弧のすべての位置を新しいリストに格納します。このような:

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.
   }
}

最後の 1 つの時点で、IndexOf排除できるものもあり、より多くのパフォーマンスが得られます。

そして、これらのメソッドを個別に (それぞれ) 実行している場合、それは nono です。すべてを一度に行う必要があります (難しくなりますが、はるかに高速になります)。

于 2012-08-21T12:53:03.887 に答える