You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于栈实现的HTML标签校验器异常问题排查与修复求助

HTML标签校验器问题排查与修复

问题根源

示例1(合法代码误判为异常)

代码将hr标记为自闭合标签,处理<hr>时不会将其压入栈中,但后续遇到</hr>闭合标签时,栈为空,触发"标签不匹配"错误。

示例2(非法代码误判为合法)

同样因为hr被标记为自闭合标签,处理<hr>时不压栈,最终栈为空,被判定为合法,但实际<hr>未闭合,属于非法代码。

修复方案

根据你的需求提供两种修复方式:

方式1:所有标签必须显式闭合

如果要求所有标签(包括hr、br等)都需要手动闭合,只需修改isSelfClosingTag函数,取消自闭合标签的判断:

int isSelfClosingTag(const char* tag) {
    // 所有标签均需显式闭合,无自闭合标签
    return 0;
}

修复后效果:

  • 输入<hr></hr>:<hr>压入栈,</hr>匹配弹出,最终栈空,输出Correct!
  • 输入<hr>:<hr>压入栈,最终栈不为空,输出Error <hr>

方式2:仅自闭合写法的标签无需闭合

如果遵循HTML标准,仅允许<hr/>这类自闭合写法的标签无需闭合,修改isSelfClosingTag函数,通过标签结尾的/判断自闭合:

int isSelfClosingTag(const char* tag) {
    int len = strlen(tag);
    // 检查标签是否以/结尾(自闭合写法)
    if (len > 0 && tag[len-1] == '/') {
        // 可选:限制仅指定标签可使用自闭合写法
        char* tagName = strdup(tag);
        tagName[len-1] = '\0'; // 移除末尾的/
        static const char* allowedTags[] = {"hr", "br", "img", "input", "meta", "link"};
        for (int i = 0; i < sizeof(allowedTags)/sizeof(allowedTags[0]); i++) {
            if (strcmp(tagName, allowedTags[i]) == 0) {
                free(tagName);
                return 1;
            }
        }
        free(tagName);
    }
    return 0;
}

修复后效果:

  • 输入<hr></hr>:<hr>压入栈,</hr>匹配弹出,输出Correct!
  • 输入<hr>:<hr>压入栈,最终栈不为空,输出Error <hr>
  • 输入<hr/>:判定为自闭合标签,不压栈,输出Correct!

修复后的完整代码(方式1示例)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STACK_SIZE 100

typedef struct {
    char* items[MAX_STACK_SIZE];
    int top;
} Stack;

void initStack(Stack* s) {
    s->top = -1;
}

int isStackEmpty(Stack* s) {
    return s->top == -1;
}

int isStackFull(Stack* s) {
    return s->top == MAX_STACK_SIZE - 1;
}

void push(Stack* s, const char* item) {
    if (isStackFull(s)) {
        fprintf(stderr, "Stack overflow\n");
        exit(EXIT_FAILURE);
    }
    s->items[++s->top] = strdup(item);
}

char* pop(Stack* s) {
    if (isStackEmpty(s)) {
        return NULL;
    }
    return s->items[s->top--];
}

char* peek(Stack* s) {
    if (isStackEmpty(s)) {
        return NULL;
    }
    return s->items[s->top];
}

void freeStack(Stack* s) {
    while (!isStackEmpty(s)) {
        free(pop(s));
    }
}

int isSelfClosingTag(const char* tag) {
    // 所有标签均需显式闭合,无自闭合标签
    return 0;
}

void checkHTML(const char* html) {
    Stack stack;
    initStack(&stack);

    const char* p = html;
    while (*p != '\0') {
        if (*p == '<') {
            const char* tagStart = p + 1;
            const char* tagEnd = strchr(tagStart, '>');
            if (tagEnd == NULL) {
                printf("Error: Invalid tag format\n");
                freeStack(&stack);
                return;
            }

            int tagLength = tagEnd - tagStart;
            char* tag = (char*)malloc(tagLength + 1);
            strncpy(tag, tagStart, tagLength);
            tag[tagLength] = '\0';

            if (tag[0] == '/') {
                // 处理闭合标签
                if (isStackEmpty(&stack)) {
                    printf("Error <%s>\n", tag);
                    free(tag);
                    freeStack(&stack);
                    return;
                }
                char* openTag = pop(&stack);
                if (strcmp(openTag, tag + 1) != 0) {
                    printf("Error <%s>\n", tag);
                    free(openTag);
                    free(tag);
                    freeStack(&stack);
                    return;
                }
                free(openTag);
            } else {
                // 处理开启标签
                if (!isSelfClosingTag(tag)) {
                    push(&stack, tag);
                }
            }

            free(tag);
            p = tagEnd;
        } else {
            p++;
        }
    }

    // 检查栈中是否有未闭合标签
    if (isStackEmpty(&stack)) {
        printf("Correct!\n");
    } else {
        printf("Error <%s>\n", peek(&stack));
    }
    freeStack(&stack);
}

int main() {
    char html[1000];

    printf("Enter HTML code (end with an empty line):\n");
    fgets(html, sizeof(html), stdin);
    html[strcspn(html, "\n")] = '\0'; // 移除换行符

    checkHTML(html);

    return 0;
}

内容的提问来源于stack exchange,提问作者Nothin Karwy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:14:54