我是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
}
答案 0 :(得分:1)
对于这个简单的事情(这一定很简单,因为这根本不可能解析现实世界中谁知道你会得到什么样的XML)一些事情可能会有所不同,但你的直接问题很直接:
将stack<string> tagstack
声明移出每行循环之外,或者更好地移动到整个处理循环之外。现在,只要将标签推入堆栈并退出声明它的else{}
块的范围,它就会立即停止。
您的状态机可以使用一些工作来提高可靠性,但这是另一个问题,首先修复标记堆栈的范围。
你需要在调试器下运行它,你应该习惯这一点,因为我所知道的每个专业的C / C ++工程师都将其生产生活的一半花在一个上面。它伴随着业务。话虽如此,关于总是回归真实,我会将这些问题反馈给您,而不是在这里回答,而是再次调查调试器
在代码中的某个位置,您似乎正在检查令牌的第一个字符为'/',而不是两行之后您似乎试图抛出开头和结尾元素标记'&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,则必须存在不平衡,因此出现错误。将那个条件检查作为整体评估的一部分,我保证你会开始看到错误的过滤。
现在让您进入调试器。我设法找到所有这些只是仔细阅读代码。想象一下,在调试器中逐行运行时你会看到的东西,你可以实时看到这些变化。