[英]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.