繁体   English   中英

将文本文件中的数据存储到 C++ 以便编辑的最佳方法是什么

[英]What is the best way to store data from text file into C++ in order to Edit

我正在构建一个联系人管理系统,其中有控制台 C++ 应用程序,我想将联系人存储在这样的地址文本文件中。

1
John Doe
134 main st.
south bend, IN. 38744
574-444-5554

我希望能够将多个联系人存储到文件中,然后将文件读入 memory,但不确定是否应该存储到数组、向量或其他一些数据结构中。

我需要/希望能够添加、编辑、按姓氏、ID(1 等)搜索

目前,当我将数据放入文本文件时,我可以打开并读出它,但它没有存储在任何有组织的数据结构中。

我如何阅读文件的示例:

    string myText;
    // Read from the text file
    ifstream MyReadFile("address.txt");
    // Use a while loop together with the getline() function to read the file line by line
    while (getline(MyReadFile, myText)) {
        // Output the text from the file
        cout << myText << "\n";
    }
    // Close the file
    MyReadFile.close();

C++ 是一种面向 object 的语言。 它可以帮助您将现实世界的问题抽象为对象,这些对象由数据和方法组成,对这些数据进行操作。

因此,第一个想法可能是将“联系人”翻译成 object。这样的 object(或类)将具有属于一起的属性或数据成员,然后组成“联系人”

示例:您可以像这样定义 class 联系人:

#include <string>

struct Contact {
    int ID{};
    std::string name{};
    std::string street{};
    std::string city{};
    std::string phone{};
};

这样,构成联系人的所有属性都集中在 object 中,可以轻松处理。

如果你需要这样一个联系人的实例,你可以简单地写Contact c并且你可以轻松地访问所有数据,例如c.name

这让生活已经很简单了。

下一个。 方法。 你可以或你想用一个联系人做什么。 您目前唯一的要求是,从 stream 读取数据或将数据写入 stream。C++ 也会在这里帮助您。 您已经了解 iostream 设施,并且您可以例如使用插入器运算符<<写入任何 stream。stream 是std::cout还是任何文件 stream 甚至是std::ostringstream都没有关系。 它会一直有效。

很好,但是如何将这样的功能添加到您的“联系人”object? 这可以通过为您的 object 覆盖运算符<<>>来完成。class 现在看起来像这样:

#include <iostream>
#include <string>
#include <iomanip>

struct Contact {
    int ID{};
    std::string name{};
    std::string street{};
    std::string city{};
    std::string phone{};

    friend std::istream& operator >> (std::istream& is, Contact& c) {
        is >> c.ID;
        std::getline(is >> std::ws, c.name);
        std::getline(is, c.street);
        std::getline(is, c.city);
        std::getline(is, c.phone);
        return is;
    }
    friend std::ostream& operator << (std::ostream& os, const Contact& c) {
        return os << c.ID << '\n' << c.name << '\n' << c.street << '\n'
            << c.city << '\n' << c.phone << '\n';
    }
};

现在你需要考虑更多的抽象。 您不仅希望拥有一个联系人实例,而且希望拥有多个联系人实例。 并且您想使用这些数据,例如搜索、添加、排序或其他任何操作。

这当然不能用上面的 object 原样完成。 我们需要存储它的一个或多个对象。

为此,绝对标准的方法是使用std::vector std::vector可以容纳 0..many 其他对象,非常适合您的要求。 您可以简单地编写std::vector<Contact> contacts; 并且您立即可以拥有许多“联系人”实例。

但是在 C++ 中,您将 go 领先一步。 因为您想对这么多“联系人”进行操作,所以您也可以将其封装在一个新的、不同的 object 中。让我们称之为“数据库”。 在这里您将添加所有与“联系人”一起使用的功能。 因此,数据是一个std::vector<Contact>并且方法将对该数据进行操作。 让我们从输入和 output 开始。

下一个源代码:

#include <iostream>
#include <vector>
#include <string>
#include <iomanip>

struct Contact {
    int ID{};
    std::string name{};
    std::string street{};
    std::string city{};
    std::string phone{};

    friend std::istream& operator >> (std::istream& is, Contact& c) {
        is >> c.ID;
        std::getline(is >> std::ws, c.name);
        std::getline(is, c.street);
        std::getline(is, c.city);
        std::getline(is, c.phone);
        return is;
    }
    friend std::ostream& operator << (std::ostream& os, const Contact& c) {
        return os << c.ID << '\n' << c.name << '\n' << c.street << '\n'
            << c.city << '\n' << c.phone << '\n';
    }
};

struct Database {

    std::vector<Contact> data{};

    friend std::istream& operator >> (std::istream& is, Database& d) {
        d.data.clear();
        Contact tmp;
        while (is >> tmp)
            d.data.push_back(tmp);
        return is;
    }
    friend std::ostream& operator << (std::ostream& os, const Database& d) {
        for (const Contact& c : d.data)
            os << c;
        return os;
    }
};

这在现在已经很强大了。 如果你有一个Database d ,你可以使用简单的语句 output 将完整的数据库发送到控制台: std::cout << d; . 这将显示std::cout上的所有数据。 所有功能都封装在类中。 这是一个很大的优势。 想象一下,你在“联系人”class 中进行了修改。“外部”世界不会受到影响并继续工作,无需任何修改。

现在让我们 go 来一个完整的例子。 为此,我想提醒您,我们的 class 现在可以与任何类型的 stream 一起使用。因此,我将把一些测试数据放在std::istringstream而不是文件中。 让我们来看看:

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <iomanip>

struct Contact {
    int ID{};
    std::string name{};
    std::string street{};
    std::string city{};
    std::string phone{};

    friend std::istream& operator >> (std::istream& is, Contact& c) {
        is >> c.ID;
        std::getline(is >> std::ws, c.name);
        std::getline(is, c.street);
        std::getline(is, c.city);
        std::getline(is, c.phone);
        return is;
    }
    friend std::ostream& operator << (std::ostream& os, const Contact& c) {
        return os << c.ID << '\n' << c.name << '\n' << c.street << '\n'
            << c.city << '\n' << c.phone << '\n';
    }
};

struct Database {

    std::vector<Contact> data{};

    friend std::istream& operator >> (std::istream& is, Database& d) {
        d.data.clear();
        Contact tmp;
        while (is >> tmp)
            d.data.push_back(tmp);
        return is;
    }
    friend std::ostream& operator << (std::ostream& os, const Database& d) {
        for (const Contact& c : d.data)
            os << c;
        return os;
    }
};

std::istringstream in{ R"(1
John Doe
134 main st.
south bend, IN. 38744
574-444-5554
2
Jane Doe
2 second  st.
north , IN. 5678
543-123-456
3
x y
z  st.
city
phone)" };

int main() {
    Database d{};

    in >> d;
    std::cout << d;
}

当然,您现在需要向“数据库”class 添加更多功能。无论您需要什么。

而如果你想重组“联系人”class。也没有问题。 它将继续工作。

我希望这个例子给了你一些关于如何做事情的想法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM