如何使用栈来解析字符串
How to use a stack to parse a string
我有一个字符串:
String stringContent="{\*\listtable{\list{\listlevel{\leveltext}{\levelNumber}}}}"
我如何 select 像这样在每次传递中一个一个地 select 所有大括号的值:
"{\levelNumber}"
"{\leveltext}"
"{\listlevel{\leveltext}{\levelNumber}}"
"{\list{\listlevel{\leveltext}}}"
"{\*\listtable{\list{\listlevel{\leveltext}}}}"
到目前为止我已经这样做了:
public class StringExtracter {
public String stringofObject(Section parentSectionObject, String stringContent) {
Stack stack=new Stack();
String returnString = "";
char arr[] = stringContent.toCharArray();
for(int i=0;i<=arr.length;i++){
while(arr[i]!='}'){
if(arr[i]=='{'){
stringContent=stringContent.substring(i+1);
returnString=stringContent;
System.out.println(stringContent);
braces=true;
Section sectionObject=new Section(parentSectionObject,stringContent);
stack.push(arr[i]);
}
}
return returnString;
}
但问题是它没有像这样检测到正确的}
。我应该怎么做?
截至目前的输出:
\*\listtable{\list{\listlevel{\leveltext}{\fefw}}}}
\list{\listlevel{\leveltext}{\fefw}}}}
\listlevel{\leveltext}{\fefw}}}}
\leveltext}{\fefw}}}}
\fefw}}}}
我建议您不要使用 for 循环,而是创建一个名为 i 的变量并在 while 循环中增加它。您正在 while 循环中检查 "arr[i]!='}'",但由于它在 for 循环内,因此 i 永远不会增加,因此它始终检查相同的字符。
基于堆栈的解决方案(可能会更简单,但让我们先解决问题):
public class Main {
public static class Node {
public int level;
public String content = "";
public List<Node> children = new ArrayList<>();
}
public static void main(String[] args) {
String input="{\\*\\listtable{\\list{\\listlevel{\\leveltext}{\\levelNumber}}}}";
Node root = null;
Stack<Node> stack = new Stack<>();
for(char c: input.toCharArray()) {
if (c == '{') {
Node n = new Node();
n.level = stack.size() + 1;
n.content += c;
stack.push(n);
if (root == null) root = n;
} else if (c == '}') {
Node n = stack.pop();
n.content += c;
if (!stack.isEmpty()) {
stack.peek().children.add(n);
}
} else {
stack.peek().content += c;
}
}
TreeTraverser<Node> treeTraverser = new TreeTraverser<Node>() {
@Override
public Iterable<Node> children(Node root) {
return root.children;
}
};
for(Node node : treeTraverser.preOrderTraversal(root)) {
String indent = String.format("%" + node.level + "s", " ");
System.out.println(indent + node.content);
}
}
}
注意:TreeTraverser
需要Google的Guava库
输出:
{\*\listtable}
{\list}
{\listlevel}
{\leveltext}
{\levelNumber}
编辑 1:修改为在 OP
的额外输入后创建树
编辑 2:修改以正确对待兄弟姐妹
我有一个字符串:
String stringContent="{\*\listtable{\list{\listlevel{\leveltext}{\levelNumber}}}}"
我如何 select 像这样在每次传递中一个一个地 select 所有大括号的值:
"{\levelNumber}"
"{\leveltext}"
"{\listlevel{\leveltext}{\levelNumber}}"
"{\list{\listlevel{\leveltext}}}"
"{\*\listtable{\list{\listlevel{\leveltext}}}}"
到目前为止我已经这样做了:
public class StringExtracter {
public String stringofObject(Section parentSectionObject, String stringContent) {
Stack stack=new Stack();
String returnString = "";
char arr[] = stringContent.toCharArray();
for(int i=0;i<=arr.length;i++){
while(arr[i]!='}'){
if(arr[i]=='{'){
stringContent=stringContent.substring(i+1);
returnString=stringContent;
System.out.println(stringContent);
braces=true;
Section sectionObject=new Section(parentSectionObject,stringContent);
stack.push(arr[i]);
}
}
return returnString;
}
但问题是它没有像这样检测到正确的}
。我应该怎么做?
截至目前的输出:
\*\listtable{\list{\listlevel{\leveltext}{\fefw}}}}
\list{\listlevel{\leveltext}{\fefw}}}}
\listlevel{\leveltext}{\fefw}}}}
\leveltext}{\fefw}}}}
\fefw}}}}
我建议您不要使用 for 循环,而是创建一个名为 i 的变量并在 while 循环中增加它。您正在 while 循环中检查 "arr[i]!='}'",但由于它在 for 循环内,因此 i 永远不会增加,因此它始终检查相同的字符。
基于堆栈的解决方案(可能会更简单,但让我们先解决问题):
public class Main {
public static class Node {
public int level;
public String content = "";
public List<Node> children = new ArrayList<>();
}
public static void main(String[] args) {
String input="{\\*\\listtable{\\list{\\listlevel{\\leveltext}{\\levelNumber}}}}";
Node root = null;
Stack<Node> stack = new Stack<>();
for(char c: input.toCharArray()) {
if (c == '{') {
Node n = new Node();
n.level = stack.size() + 1;
n.content += c;
stack.push(n);
if (root == null) root = n;
} else if (c == '}') {
Node n = stack.pop();
n.content += c;
if (!stack.isEmpty()) {
stack.peek().children.add(n);
}
} else {
stack.peek().content += c;
}
}
TreeTraverser<Node> treeTraverser = new TreeTraverser<Node>() {
@Override
public Iterable<Node> children(Node root) {
return root.children;
}
};
for(Node node : treeTraverser.preOrderTraversal(root)) {
String indent = String.format("%" + node.level + "s", " ");
System.out.println(indent + node.content);
}
}
}
注意:TreeTraverser
需要Google的Guava库输出:
{\*\listtable}
{\list}
{\listlevel}
{\leveltext}
{\levelNumber}
编辑 1:修改为在 OP
的额外输入后创建树编辑 2:修改以正确对待兄弟姐妹