C# 使用规则将字符串转换为树表示形式
我要做一些简单的RTF文本解析,我需要纠正一个iss。给定以下字符串:C# 使用规则将字符串转换为树表示形式,c#,.net,algorithm,data-structures,C#,.net,Algorithm,Data Structures,我要做一些简单的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}不会影响
{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,但是aaaaaaaaaaaaaaa}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
- B1
- - C
- - B2
- - - E
- - - G
- - - F
- - - B3
- A2
然后,为了获得影响任何节点的字符,我可以递归地遍历每个父节点
我一直在尝试将字符串解析到我的节点类中:
public class myNode
{
public myNode Parent;
public string Value;
public List<myNode> subNodes;
}
公共类myNode
{
公共myNode父节点;
公共字符串值;
公共列表子节点;
}
我一个字符一个字符地读取字符串,当我遇到一个\
时,我会增加两个字符。当我遇到{
时,我将上一个文本节保存为节点值并进入子节点,当我遇到}
时,我将退出
但我一直在搞砸逻辑,尤其是对于G
和A2
。写在纸上是很简单的,但当我试着做下一步的实际逻辑时,我总是把它弄得一团糟
有没有更直接的方法来构建这个结构?(或者我是否应该使用更好的结构)。我认为应该有一些库允许将字符串转换为树,但我似乎找不到任何库。使用“状态机”方法,其中状态是当前节点,并使用转义标志:
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);
输出:
root
aaaaaaa}aaaa{aaaaa
bbbbbbbb
ccccc{cccc
bbb
eeeee
gggg
ffff
bbbbbb
aaaaa
请注意,G节点不是E节点的子节点,而是具有空值的节点的子节点
当然,您还必须添加一些错误处理。。。它应该能够解析你的结构。。。如果我是对的,你的问题可以用AST来建模,这对这个项目来说可能有点过分了。。如果是这样,您可以使用任何您喜欢的ast解析器/解析器生成器。。我相信它们生成的表有助于更快地解析。。。完全忘记了表格的名称,但问题描述很好。我冒昧地编辑了这个标题,因为它实际上不是你需要的二叉树;然后,在获取父节点的依赖节点之前,我只需向后循环通过
父.SubNodes
来获取依赖节点。由于bbb
取决于bbbbbbbb
中的值,所以我需要更改的另一件事是case'\\':
仍然需要在输出中附加``字符,因为这些经过斜杠的转义字符稍后会被解析,否则回答很好:Dyeah关于RTF规范的任何内容都不是“它通常是如何完成的”^^
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