检查 HTML 标签是否平衡

3

我已经尝试了两天让我的程序运行起来,这是一项作业任务,我认为我的算法应该是正确的,使用堆栈检查标签是否平衡。如果有人知道代码哪里出了问题,我将不胜感激。现在它看起来像这样:

public class HtmlParser {

    private Stack<String> tagstack; // stack to collect only "<" characters.

    public HtmlParser() {
        tagstack = new Stack<String>(); 
    }

    private void processClosedTag(Scanner in) {
        tagstack.pop();
        in.next();
    }

    private void processOpenTag(Scanner in) {  
        tagstack.push(in.next()); // "<"
    }

    public boolean isCorrectlyNested(Scanner in) {
        boolean isBalanced = false;
        while(in.hasNext()) {
            if(in.hasNext("<")) 
                processOpenTag(in); //and recurse until "/>"
            else if(in.hasNext(">")) 
                processClosedTag(in);
        }
        if(tagstack.isEmpty())
            isBalanced = true;
        return isBalanced;

    }//isCorrectlyNested

}//class

当我使用扫描器对象“in”并调用此类中的方法时,在控制台中不会发生任何事情,它只读取我写的内容,但然后什么也不会发生,它甚至不会返回我写的语句,例如:

if(parser.isCorrectlyNested(input))
  System.out.println("Correctly Nested!"); 
else
  System.out.println("Need to nest properly");

当然,这是在主方法中使用HtmlParser实例“parser”的情况。

哦,我看到我忘记发布问题了,哈哈。当我使用扫描器对象“in”并调用此类中的方法时,在控制台中什么也不会发生,它只读取我写的内容,但然后什么也不会发生,它甚至不会返回我编写的语句,例如:if(parser.isCorrectlyNested(input))System.out.println(“正确嵌套!”); 否则System.out.println(“需要正确嵌套”); 当然,这是在我使用HtmlParser实例“parser”的主要方法中。 - patriques
如果你说控制台没有输出任何内容,那么要么代码没有被执行到,要么就是抛出了异常并且被静默捕获了... - SJuan76
完整的主方法如下所示:public class HtmlMain { public static void main(String[] args) { HtmlParser parser = new HtmlParser(); System.out.println("输入要解析的html字符串:"); Scanner input = new Scanner(System.in); if(parser.isCorrectlyNested(input)) System.out.println("正确嵌套!"); else System.out.println("需要正确嵌套"); } } - patriques
1
请编辑您的答案,以便以可读形式发布您的代码。 - SJuan76
4个回答

3

如果下一个字符既不是小于号也不是大于号,那么您实际上没有移动扫描器的位置。考虑一下,如果下一个字符是某种字母数字字符串。由于while循环永远无法超过它所寻找的字符串,因此您的方法永远不会返回,导致输出也永远不会被执行。


是的,这确实是其中一个问题,谢谢你,但它仍然无法运行。 - patriques
1
“不运行”是什么意思?编译错误、执行错误还是行为错误? - doogle

0

如前所述,您不会为除<或>之外的其他字符移动扫描器。另一个问题是您没有结束条件(您可能希望在第一行后退出)。第三个问题是,一旦遇到比已经打开的更多的关闭字符,您将收到一个空堆栈异常...


0
作为对您算法的一般观察,它将允许一个语句<html>,它没有与</html>匹配的闭合标签。这是有意行为吗?看起来不像。
无论如何,正如@odie之前所述,如果不是尖括号,您的循环将无法移动到任何内容。但是缺陷比那更深 - 将您的堆栈算法考虑如下:
  • 如果我看到一个HTML标记,则应将其推送到堆栈上。

  • 如果我看到一个关闭的HTML标记,并且它与当前位于堆栈顶部的标记匹配,则应弹出[堆栈的第一个元素]。

这是词法分析的原则;您正在寻找匹配的令牌。您不能依赖尖括号为您提供上下文。

好的,我的意图只是为了平衡“<”标签并检查它们是否平衡,而不是检查它们的语法含义是否正确。但感谢您的观察。无论如何,我已经用下面的代码解决了这个问题。 - patriques

0

只是想发布解决方案。这样那些参与问题的人可以看到最终结果,谢谢。

公共类 HtmlParser {

private Stack<Character> tagstack; // stack to collect only "<" characters.

public HtmlParser() {
    tagstack = new Stack<Character>();
}

public boolean isCorrectlyNested(String str) {
    boolean isBalanced = false;
    String s = str.trim();
    for(int i = 0; i < s.length(); i++) {
        if(str.charAt(i) == '<') 
            tagstack.push('<');
        if(str.charAt(i) == '>') {
            if (tagstack.isEmpty()) 
                return isBalanced;
            else 
                tagstack.pop();
            }
        }

    if(tagstack.isEmpty())
        isBalanced = true;
    return isBalanced;

}//isCorrectlyNested 

}


运行此代码后,我注意到它仍然不符合HTML规范的平衡性。您的算法平衡了字符串"<html>"(这是不应该的),以及字符串"<html><p></a></html>"(这也是不应该的)。 - Makoto
意图只是为了平衡“<”标签并检查它们是否平衡,而不是检查它们的语法含义是否正确。但感谢您的观察。 - patriques

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接