每次迭代while循环后,C ++ std :: stack清空

时间:2018-02-24 07:10:19

标签: c++ while-loop stack

我试图编写一个用于解析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; }
}

1 个答案:

答案 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, '<');