我试图编写一个用于解析XML的XML标记的函数,如下所示:
<Employee>
<salary>40000</salary> <name>John Doe</name> <id>1234</id>
<address>2230 W. Treeline Dr.</address>
<city>Tucson</city>
<state>Arizona</state>
<country>USA</country>
<phone>520-742-2448</phone>
</Employee> <Employee>
<salary>60000</salary> <name>Jane Doe</name> <id>4321</id> </Employee>
<Employee>
<salary>140000</salary>
<state>Michigan</state>
<name>Jack Dough</name>
<id>12345</id>
<city>Dearborn</city>
<country>USA</country>
<phone>303-427-0153</phone>
<address>24437 Princeton</address>
</Employee>
我使用std::stack
来跟踪标记。遇到开始标记(例如<Employee>
)时,标记名称(Employee
)的字符串表示被压入堆栈,并且假设XML编写正确,遇到匹配的结束标记(例如</Employee>
)导致标签名称从堆栈中弹出。但是,我遇到了一个问题,即字符串被压入堆栈,因此堆栈的大小为1.当到达while循环的主体并且第二次执行主体时,堆栈被清空。我不能为我的生活弄清楚我做错了什么。为什么我的堆栈&#34;重置&#34;每次while
循环重复?
static void fromXML(std::istream& in_stream) {
std::stack<std::string> tags;
std::string temp;
std::string tagName;
std::getline(in_stream, temp);
std::istringstream ss(temp);
bool building_employee = true;
int _id;
std::string _name;
std::string _address = "";
std::string _city = "";
std::string _state = "";
std::string _country = "";
std::string _phone = "";
double _salary = 0.0;
while(building_employee && std::getline(ss, temp, '<')) {
std::cout << "Size: " << tags.size() << std::endl; // Prints "0"
std::getline(ss, tagName, '>');
ss.ignore(256, '<');
if (tagName == "") { }
else if ( !tags.empty() && tagName == "/" + tags.top() ) {
std::cout << "Popping " << tags.top() << std::endl;
tags.pop();
}
else if ((tags.empty() && tagName == "Employee") || (!tags.empty() && tagName != "Employee")) {
std::cout << "Pushing " << tagName << std::endl;
tags.push(tagName);
}
else {
std::cerr << "Problem with XML." << std::endl;
}
if (tagName == "/Employee") { building_employee = false; }
else if (tagName == "id") { _id = std::stoi(temp); }
else if (tagName == "name") { _name = temp; }
if (!building_employee) { std::cout << "Employee end." << std::endl; }
if(in_stream.eof()) {
std::cout << "Error: End of file reached without closing <" << temp << ">" << std::endl;
}
std::cout << "Size: " << tags.size() << std::endl; // Prints "1" after pushing one string onto the stack
}
if (temp == "/Employee") { std::cout << "Employee object succesfully created" << std::endl; }
}
答案 0 :(得分:1)
让我对其他人保持礼貌,为他们做Minimal, Complete, and Verifiable example。
#include <iostream>
#include <sstream>
#include <limits>
#include <stack>
static void fromXML(std::istream& in_stream) {
std::stack<std::string> tags;
std::string temp;
std::string tagName;
std::getline(in_stream, temp);
std::istringstream ss(temp);
bool building_employee = true;
int _id;
std::string _name;
std::string _address = "";
std::string _city = "";
std::string _state = "";
std::string _country = "";
std::string _phone = "";
double _salary = 0.0;
while(building_employee && std::getline(ss, temp, '<')) {
std::cout << "Size 1: " << tags.size() << std::endl; // Prints "0"
std::getline(ss, tagName, '>');
ss.ignore(256, '<');
if (tagName == "") { }
else if ( !tags.empty() && tagName == "/" + tags.top() ) {
std::cout << "Popping " << tags.top() << std::endl;
tags.pop();
}
else if ((tags.empty() && tagName == "Employee") || (!tags.empty() && tagName != "Employee")) {
std::cout << "Pushing " << tagName << std::endl;
tags.push(tagName);
}
else {
std::cerr << "Problem with XML." << std::endl;
}
if (tagName == "/Employee") { building_employee = false; }
else if (tagName == "id") { _id = std::stoi(temp); }
else if (tagName == "name") { _name = temp; }
if (!building_employee) { std::cout << "Employee end." << std::endl; }
if(in_stream.eof()) {
std::cout << "Error: End of file reached without closing <" << temp << ">" << std::endl;
}
std::cout << "Size 2: " << tags.size() << std::endl; // Prints "1" after pushing one string onto the stack
}
if (temp == "/Employee") { std::cout << "Employee object succesfully created" << std::endl; }
}
int main()
{
std::istringstream input(
"<Employee>\n"
" <salary>40000</salary> <name>John Doe</name><id>1234</id>\n"
" <address>2230 W. Treeline Dr.</address>\n"
" <city>Tucson</city>\n"
" <state>Arizona</state>\n"
" <country>USA</country>\n"
" <phone>520-742-2448</phone>\n"
"</Employee> <Employee>\n"
" <salary>60000</salary> <name>Jane Doe</name> <id>4321</id> </Employee>\n"
"<Employee>\n"
" <salary>140000</salary>\n"
" <state>Michigan</state>\n"
" <name>Jack Dough</name>\n"
" <id>12345</id\n"
" <city>Dearborn</city>\n"
" <country>USA</country>\n"
" <phone>303-427-0153</phone>\n"
" <address>24437 Princeton</address>\n"
"</Employee>)\n");
fromXML(input);
}
为什么每次while循环重复时我的堆栈都会“重置”?
堆栈不会重置,循环不会迭代。关注@JiveDadson建议并使用调试器。
问题的关键在于两行
std::getline(in_stream, temp);
std::istringstream ss(temp);
你在那里读了一行,你的循环只在这一行上运行。因为它是唯一的一行,所以循环的主体只执行一次。删除这些行并将代码中ss
的所有相应匹配项更改为in_stream
。
while(building_employee && std::getline(in_stream, temp, '<')) {
// ...
std::getline(in_stream, tagName, '>');
in_stream.ignore(256, '<');