7

簡単な RTF テキストの解析を行う予定です。Iss を修正する必要があります。次の文字列を指定します。

{aaaaaaa\}aaaa\{aaaaa{bbbbbbbb{ccccc\{cccc}bbb{eeeee}{{gggg}ffff}bbbbbb}aaaaa}

どこ:

\ means ignore next character
{ means expand
} means collapse up to parent

文字列のどの時点でも、閉じたタグ内の文字を除いて、状態は前の文字の影響を受ける可能性があります。たとえば、{gggg} は ffff には影響しませんが、aaaaaaa}aaa.. は影響bbbb, ccc, eee, ggg, fffします。

これから、上記を意味のあるブロックだけに分割できます

A1 = aaaaaaa\}aaaa\{aaaaa
B1 = bbbbbbbb
C = ccccc\{cccc
B2 = bbb
E = eeeee
G = gggg
F = ffff
B3 = bbbbbb
A2 = aaaaa

収量:

{A1{B1{C}B2{E}{{G}F}B3}A2}

X > Y を使用した依存関係を説明するには、Y が X に依存することを意味します (X では Y の意味が変わる可能性があるため)。

A1
A1 > B1
A1 > B1 > C
A1 > B1 > B2
A1 > B1 > B2 > E
A1 > B1 > B2 > G
A1 > B1 > B2 > F
A1 > B1 > B2 > B3
A1 > B1 > B2 > A2
A1 > A2

したがって、値とサブ値の順序付きリストを持つことができるノードがあるとします。値ツリーは次のようになります。

A1
- B1
- - C
- - B2
- - - E
- - - G
- - - F
- - - B3
- A2

次に、任意のノードに影響を与える文字を取得するには、各親を再帰的にステップ アップします。

私が行き詰まっているのは、文字列をノードクラスに解析しようとすることです:

public class myNode
{
    public myNode Parent;
    public string Value;
    public List<myNode> subNodes;
}

文字列を 1 文字ずつ読み取ると、\I が 2 ずつインクリメントされます。a に遭遇する{と、前のテキスト セクションをノード値として保存し、子にステップ インし、a に遭遇する}と、ステップ ダウンします。

Gしかし、特にandについては、ロジックを台無しにし続けていA2ます。紙の上で行うのは簡単ですが、ステップダウンの実際のロジックを実行しようとすると、めちゃくちゃになります。

この構造を作成するためのより簡単な方法はありますか? (または、私が使用すべきより良い構造があります)。文字列をツリーに変換できるライブラリが必要だと思いますが、見つからないようです。

4

1 に答える 1

5

状態が現在のノードである「ステート マシン」アプローチと、エスケープ フラグを使用します。

string rtf = @"{aaaaaaa\}aaaa\{aaaaa{bbbbbbbb{ccccc\{cccc}bbb{eeeee}{{gggg}ffff}bbbbbb}aaaaa}";

Node root = new Node { Parent = null, Value = "root", SubNodes = new List<Node>() };
Node node = root;
bool escape = false;
foreach (char c in rtf) {
  if (escape) {
    node.Value += c;
    escape = false;
  } else {
    switch (c) {
      case '{':
        node = new Node { Parent = node, Value = String.Empty, SubNodes = new List<Node>() };
        node.Parent.SubNodes.Add(node);
        break;
      case '}':
        node = new Node { Parent = node.Parent.Parent, Value = String.Empty, SubNodes = new List<Node>() };
        if (node.Parent != null) node.Parent.SubNodes.Add(node);
        break;
      case '\\':
        escape = true;
        break;
      default:
        node.Value += c;
        break;
    }
  }
}

PrintNode(root, String.Empty);

Node クラス (名前を少し変更しただけ):

public class Node {
  public Node Parent;
  public string Value;
  public List<Node> SubNodes;
}

表示用:

private static void PrintNode(Node node, string level) {
  if (node.Value.Length > 0) Console.WriteLine(level + node.Value);
  foreach (Node n in node.SubNodes) {
    PrintNode(n, level + "  ");
  }
}

出力:

root
  aaaaaaa}aaaa{aaaaa
    bbbbbbbb
      ccccc{cccc
    bbb
      eeeee
        gggg
      ffff
    bbbbbb
  aaaaa

G ノードは E ノードの子ではなく、値が空のノードの子であることに注意してください。

もちろん、エラー処理も追加する必要があります。

于 2012-05-04T09:42:28.740 に答える