C ++程序检查标签有效性

时间:2012-09-27 02:57:12

标签: c++ debugging tokenize

我是C ++的初学者,并试图让检查工作正常。但它几乎每次测试都会恢复正常。在这种情况下,它只能假设返回true:

<red> Red blank <dim> I'm now dim and red. </dim> </red>

但是现在这个也是如此:

<red> Blah I'm red.<dim> Im dim now </red> </dim>

或者这个:

 <red> blah <im dim now

所以我想知道我的代码中是否有一些东西会被忽略。

bool is_well_formed(ifstream& ifs, string& error_msg) {

string fname,line;
Token tok;
Lexer lexer;
tags.insert("blue");
tags.insert("red");
tags.insert("cyan");
tags.insert("white");
tags.insert("yellow");
tags.insert("magenta");
tags.insert("dim");
tags.insert("underline");
tags.insert("bold");

stack<string> tagstack;
while (getline(ifs, fname)) { 
    // tries to open the file whose name is in string fname

    if (ifs.fail()) {
        cerr << "ERROR: Failed to open file " << fname << endl;
        ifs.clear();
    } else {
        while (getline(ifs, line)) {
            lexer.set_input(line);
            while (lexer.has_more_token()) {
                tok = lexer.next_token();
                string tmpTok = tok.value;
                switch (tok.type) {
                case TAG:

                    // If it has /, remove / from tmpTok
                if (tok.value[0] == '/') {
                    // If it's a closing t
                        tmpTok = tmpTok.substr(1,tmpTok.length()-1);
                    }
                    if(tags.find(tmpTok) == tags.end()) {
                    // Check whether the encountered tag is valid
                    error_return("Tag " + tmpTok + " is invalid!");
                    return false;
                     } else {
                     // Valid Tag encountered

                     tagstack.push(tmpTok);
                     // Check if the tags are formed properly
                            if (tmpTok.find('/')) {
                             // Remove / from tmpTok
                            string closingTag =  tmpTok;
                                string openingTag = tagstack.top();
                                tagstack.pop();
                    if(closingTag.compare(openingTag) != 0) {
                        error_return(closingTag+"doesn't match" +openingTag);
                        return false;
                      } //else 
                                  //  return true; // if the file is well formed
                 }/**else{
                    tagstack.push(tmpTok);
                 }*/
                     }// else end    

                    break;
               case IDENT:
                   // cout << "IDENT: " << tok.value << endl;
                    break; 
                case ERRTOK:
                    error_return("Syntax error on this line\n");
                    return false;
                    //cout << "Syntax error on this line\n";
                    break;
                case ENDTOK:
                    break;
                }
            }
        }
    }
}
return true; // if the file is well-formed
 }

1 个答案:

答案 0 :(得分:1)

对于这个简单的事情(这一定很简单,因为这根本不可能解析现实世界中谁知道你会得到什么样的XML)一些事情可能会有所不同,但你的直接问题很直接:

stack<string> tagstack声明移出每行循环之外,或者更好地移动到整个处理循环之外。现在,只要将标签推入堆栈并退出声明它的else{}块的范围,它就会立即停止。

您的状态机可以使用一些工作来提高可靠性,但这是另一个问题,首先修复标记堆栈的范围。

你需要在调试器下运行它,你应该习惯这一点,因为我所知道的每个专业的C / C ++工程师都将其生产生活的一半花在一个上面。它伴随着业务。话虽如此,关于总是回归真实,我会将这些问题反馈给您,而不是在这里回答,而是再次调查调试器

  1. 如果词法分析器永远不会返回令牌类型的TAG会怎样?
  2. 如果词法分析器返回TAG类型的标记会发生什么,但它永远不会以'/'开头?
  3. 如果词法分析器返回TAG的令牌类型,并以'/'开头,会怎样,但是你继续砍掉'/'?
  4. 在代码中的某个位置,您似乎正在检查令牌的第一个字符为'/',而不是两行之后您似乎试图抛出开头和结尾元素标记'&lt;'和'&gt;'。具体做法是:

    if (tok.value[0] == '/') {
       // If it's a closing t
       tmpTok = tmpTok.substr(1,tmpTok.length()-1);
    }
    

    这两行代码与结束标记不一致。首先,检查前导'/',表示&lt;&gt;已被剥离,下一行你继续剥离字符串的前导和尾部字符,就好像它 两个&lt;&gt;还在。但是,如果他们不存在(并且它们不能存在,否则你的'/'检查将是假的。你现在看到了吗?你正在切掉'/'。那重要吗?好吧。进一步查看代码,我们发现:

    if (tmpTok.find('/')) {
       // Remove / from tmpTok
       string closingTag =  tmpTok;
       string openingTag = tagstack.top();
       tagstack.pop();
       if(closingTag.compare(openingTag) != 0) {
          error_return(closingTag+"doesn't match" +openingTag);
          return false;
       } //else
    }
    

    “/”检查中的任何代码都将执行,因为你只是将其剪掉了。因此,你会在令牌认为他们全部之后通过你的整个文件添加令牌进入令牌,然后用完线,并且presto,返回true。实际上如果文件末端的tagstack上有任何LEFT,则必须存在不平衡,因此出现错误。将那个条件检查作为整体评估的一部分,我保证你会开始看到错误的过滤。

    现在让您进入调试器。我设法找到所有这些只是仔细阅读代码。想象一下,在调试器中逐行运行时你会看到的东西,你可以实时看到这些变化。