You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用C++栈检查HTML标签平衡时遇字符常量报错,求解决办法

解决HTML标签平衡检查的字符常量问题

你遇到的“字符常量中字符过多”错误非常典型——核心原因是你把多字符的HTML标签(比如<head>)当成了单个char来处理,而char类型只能存一个字符,'<head>'这种写法在C++里是非法的多字符常量,自然会报错。

要解决这个问题,你需要从“处理单个字符”切换到“处理字符串”,下面是具体的修正思路和代码示例:

核心修正点

  • 放弃char[]作为输入,改用std::string来存储HTML内容,它天生支持多字符的文本处理。
  • 把栈的类型从stack<char>改成stack<std::string>,用来存储完整的HTML标签名(比如"head""title"),这样才能正确匹配开始标签和结束标签。
  • 新增标签解析逻辑:遍历字符串时,识别<>包裹的标签内容,提取出真正的标签名(还要区分开始标签和结束标签)。

修改后的完整代码

#include <iostream>
#include <stack>
#include <string>
#include <algorithm>

bool isBalancedHTML(const std::string& html) {
    std::stack<std::string> tagStack;
    size_t currentPos = 0;
    const size_t htmlLength = html.length();

    while (currentPos < htmlLength) {
        // 找到标签的起始标记 '<'
        if (html[currentPos] == '<') {
            currentPos++; // 跳过 '<'
            
            // 检查是否是结束标签(以 '/' 开头)
            bool isClosingTag = (html[currentPos] == '/');
            if (isClosingTag) {
                currentPos++; // 跳过 '/'
            }

            // 提取标签名:从当前位置到 '>' 之前的内容
            size_t tagStart = currentPos;
            while (currentPos < htmlLength && html[currentPos] != '>') {
                currentPos++;
            }
            std::string rawTag = html.substr(tagStart, currentPos - tagStart);
            currentPos++; // 跳过 '>'

            // 处理带属性的标签:只取第一个空格前的部分作为标签名
            size_t spacePos = rawTag.find(' ');
            std::string tagName = (spacePos != std::string::npos) ? rawTag.substr(0, spacePos) : rawTag;
            
            // 去除标签名前后的空白(避免格式问题)
            tagName.erase(tagName.begin(), std::find_if(tagName.begin(), tagName.end(), [](int ch) {
                return !std::isspace(ch);
            }));
            tagName.erase(std::find_if(tagName.rbegin(), tagName.rend(), [](int ch) {
                return !std::isspace(ch);
            }).base(), tagName.end());

            if (isClosingTag) {
                // 结束标签:检查栈顶是否匹配
                if (tagStack.empty() || tagStack.top() != tagName) {
                    return false;
                }
                tagStack.pop();
            } else {
                // 开始标签:跳过自闭合标签(比如 <img/>、<br/>)
                if (!tagName.empty() && tagName.back() != '/') {
                    tagStack.push(tagName);
                }
            }
        } else {
            // 非标签内容,直接跳过
            currentPos++;
        }
    }

    // 所有标签处理完后,栈为空说明完全匹配
    return tagStack.empty();
}

// 测试用例
int main() {
    // 平衡的HTML
    std::string balancedHTML = "<html><head><title>My Page</title></head><body><div class=\"content\"><p>Hello World</p></div></body></html>";
    // 不平衡的HTML(少了一个</div>)
    std::string unbalancedHTML = "<html><head><title>My Page</title></head><body><div class=\"content\"><p>Hello World</p></body></html>";

    std::cout << "Balanced HTML check: " << (isBalancedHTML(balancedHTML) ? "Pass" : "Fail") << std::endl;
    std::cout << "Unbalanced HTML check: " << (isBalancedHTML(unbalancedHTML) ? "Pass" : "Fail") << std::endl;

    return 0;
}

额外说明

  • 代码里处理了带属性的标签(比如<div class="test">),会自动提取出div作为标签名。
  • 支持忽略自闭合标签,这类标签不需要入栈,因为它们没有对应的结束标签。
  • 实际生产环境中,HTML标签的规则更复杂(比如注释、CDATA块、特殊字符转义等),如果需要更严谨的检查,可能需要结合正则表达式或者专门的HTML解析库,但上面的代码已经能覆盖大部分基础场景。

内容的提问来源于stack exchange,提问作者R. Ren

火山引擎 最新活动