从文本文件读取以显示给多个联系人

时间:2019-02-20 08:24:41

标签: c++

我必须读取一个名为“ address.xml”的文件,其中包含:

<?xml version="1.0"?>
<address_book>
    <contact>
        <name>George Clooney</name>
        <street>1042 El Camino Real</street>
        <city>Beverly Hills</city>
        <state>CA</state>
        <zip>90214</zip>
       </contact>

等等,具有多个联系人。只需要显示Palmdale城市的人。我已经定义了联系人的每个元素,但是当我尝试在Palmdale中显示联系人时,它仅列出一个联系人(文本文档中的最后一个)。我需要使用循环来显示所有这些内容吗?

void test2() {
    ifstream fin;
    string row, name, street, city, state, zip;
    int start, end;
    fin.open("address.xml");
    if (fin.fail()) {
        cout << "There was an error opening the file...";
        exit(1);
    }

while (getline(fin, row)) {

    if ((start = row.find("<name>")) != string::npos) {
        start = row.find(">");
        end = row.find("</name>");
        name = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<street>")) != string::npos) {
        start = row.find(">");
        end = row.find("</street>");
        street = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<city>")) != string::npos) {
        start = row.find(">");
        end = row.find("</city>");
        city = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<state>")) != string::npos) {
        start = row.find(">");
        end = row.find("</state>");
        state = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<zip>")) != string::npos) {
        start = row.find(">");
        end = row.find("</zip>");
        zip = row.substr(start + 1, end - start - 1);
    }
}

if (city == "Palmdale") {
    cout << name << endl << street << endl
        << city << endl << state << endl << zip << endl;
}
fin.close();
}

感谢所有可以指出正确方向的人

2 个答案:

答案 0 :(得分:2)

您的if (city == "Palmdale") {...}不在任何循环中,因此在处理完所有数据之后,它将仅运行一次。相反,您应该在每次获取所有数据时运行它。例如,如果您确定自己的模式将完全保持这种方式,则可以假设您在读取<zip>元素时记录是完整的。或者更好的是,当<contact>元素关闭时。试试这个:

while (getline(fin, row)) {

    if ((start = row.find("<name>")) != string::npos) {
        start = row.find(">");
        end = row.find("</name>");
        name = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<street>")) != string::npos) {
        start = row.find(">");
        end = row.find("</street>");
        street = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<city>")) != string::npos) {
        start = row.find(">");
        end = row.find("</city>");
        city = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<state>")) != string::npos) {
        start = row.find(">");
        end = row.find("</state>");
        state = row.substr(start + 1, end - start - 1);
    }
    if ((start = row.find("<zip>")) != string::npos) {
        start = row.find(">");
        end = row.find("</zip>");
        zip = row.substr(start + 1, end - start - 1);
    }
    if ((row.find("</contact>")) != string::npos) {
        if (city == "Palmdale") {
            cout << name << endl << street << endl
            << city << endl << state << endl << zip << endl;
        }
    }
}


fin.close();
}

如果它变得比这更复杂,我真的建议您使用XML库。实际上,如果您需要重做,我已经使用了一个。


例如,这就是使用tinyxml的样子(您所要做的就是将tinyxml2.htinyxml2.cpp添加到项目中):

#include <iostream>
#include <string>
#include "tinyxml2.h"
#include "tinyxml2.cpp"

int main() {
    tinyxml2::XMLDocument doc;
    doc.LoadFile("address.xml");
    tinyxml2::XMLElement* book = doc.FirstChildElement("address_book");

    for (tinyxml2::XMLElement* contact = book->FirstChildElement("contact");
        contact != NULL; contact = contact->NextSiblingElement())
    {
        std::string name = contact->FirstChildElement("name")->GetText();
        std::string street = contact->FirstChildElement("street")->GetText();
        std::string city = contact->FirstChildElement("city")->GetText();
        std::string state = contact->FirstChildElement("state")->GetText();
        std::string zip = contact->FirstChildElement("zip")->GetText();

        if (city == "Palmdale") {
            std::cout << name << std::endl << street << std::endl
                << city << std::endl << state << std::endl << zip << std::endl;
        }
    }
}

注意:我不隶属于tinyxml,但过去曾使用过它。

答案 1 :(得分:1)

  1. if (city == "Palmdale") {...}仅适用于最后一条记录。您需要在循环内打印。
  2. 您最好使用XML解析器库,因为对于合法的XML,您的程序可能会失败。
    • 它不会丢弃前导和尾随空格
    • 假设开始标签,值和结束标签之间没有换行符。
    • 它是指没有上下文的线,而不是contact节点,例如,如果从一个元素中省略城市,它将使用前一个元素的城市。