###课设要求
问题描述:设计一个Database类。Database类是一个表的集合,而表又由行和列组成。例如,下面的雇员信息表包含三个记录,每个记录有四个字段(Employee、Name、Department和Boss)。
雇员 | 姓名 | 部门 | 部门经理 |
---|---|---|---|
111-11-1234 | Cruz | ACC | Warder |
213-44-5649 | Johnston | MIS | Michaels |
321-88-7895 | Tom | FIN | Bearskin |
- 基本要求:能够完成对数据库的基本操作;包括创建数据库,实现对数据库里面的表的添加,删除;以及能够完成对表结构的修改(如添加或删除字段),以及对表中的记录进行添加和删除;能够完成对使用适当的查询语言从一个或多个表中查找相关信息。
- 测试数据:可以选取高校人员(教师、学生、职工等)数据库作为测试数据
- 实现提示:
Database 类的公有接口包含如下数据成员:
- 创建一个表。
- 通过增加或删除字段修改表结构。
- 删除一个表。
- 在表中增加一个记录。
- 从表中删除记录。
- 用适当的查询语言从一个或多个表中查找信息。
选做内容:高校人员信息通常保存在文件里面,可以从文件里面读取人员信息;然后完成上面操作
大纲
包含的头文件
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <fstream>
#include <sstream>
定义记录和表
定义一个记录类表示表中的一行,表类表示数据库中的表。
class Record
{
public:
std::unordered_map<std::string, std::string> fields;
void setField(const std::string& fieldName, const std::string& value)
{
fields[fieldName] = value;
}
std::string getField(const std::string& fieldName) const
{
auto it = fields.find(fieldName);
if (it != fields.end())
{
return it->second;
} else
{
return "";
}
}
};
class Table
{
public:
std::vector<std::string> columnNames;
std::vector<Record> records;
void addColumn(const std::string& columnName)
{
columnNames.push_back(columnName);
}
void removeColumn(const std::string& columnName)
{
columnNames.erase(std::remove(columnNames.begin(), columnNames.end(), columnName), columnNames.end());
for (auto& record : records)
{
record.fields.erase(columnName);
}
}
void addRecord(const Record& record)
{
records.push_back(record);
}
void deleteRecord(int index)
{
if (index >= 0 && index < records.size())
{
records.erase(records.begin() + index);
}
}
Record* getRecord(int index)
{
if (index >= 0 && index < records.size())
{
return &records[index];
} else
{
return nullptr;
}
}
};
数据库类
定义一个Database类来管理多个表。
class Database {
private:
std::unordered_map<std::string, Table> tables;
public:
void createTable(const std::string& tableName, const std::vector<std::string>& columns)
{
Table newTable;
for (const auto& column : columns)
{
newTable.addColumn(column);
}
tables[tableName] = newTable;
}
void deleteTable(const std::string& tableName)
{
tables.erase(tableName);
}
Table* getTable(const std::string& tableName)
{
auto it = tables.find(tableName);
if (it != tables.end())
{
return &(it->second);
} else
{
return nullptr;
}
}
void addRecordToTable(const std::string& tableName, const Record& record)
{
auto table = getTable(tableName);
if (table)
{
table->addRecord(record);
}
}
void deleteRecordFromTable(const std::string& tableName, int index)
{
auto table = getTable(tableName);
if (table)
{
table->deleteRecord(index);
}
}
std::vector<Record> queryTable(const std::string& tableName, const std::string& columnName, const std::string& value)
{
std::vector<Record> results;
auto table = getTable(tableName);
if (table)
{
for (const auto& record : table->records)
{
if (record.getField(columnName) == value)
{
results.push_back(record);
}
}
}
return results;
}
void loadFromFile(const std::string& tableName, const std::string& filePath)
{
std::ifstream file(filePath);
if (!file.is_open())
{
std::cerr << "Error opening file: " << filePath << std::endl;
return;
}
std::string line;
if (std::getline(file, line))
{
std::istringstream iss(line);
std::vector<std::string> columns;
std::string column;
while (std::getline(iss, column, ','))
{
columns.push_back(column);
}
createTable(tableName, columns);
}
Table* table = getTable(tableName);
if (!table)
{
return;
}
while (std::getline(file, line))
{
std::istringstream iss(line);
std::string value;
Record record;
int colIndex = 0;
while (std::getline(iss, value, ','))
{
if (colIndex < table->columnNames.size())
{
record.setField(table->columnNames[colIndex], value);
colIndex++;
}
}
table->addRecord(record);
}
file.close();
}
};
测试代码
int main()
{
Database db;
db.loadFromFile("employee", "employee_data.txt");
db.createTable("students", {"ID", "Name", "Major"});
Record student;
student.setField("ID", "12345");
student.setField("Name", "Alice");
student.setField("Major", "Computer Science");
db.addRecordToTable("students", student);
auto results = db.queryTable("students", "Major", "Computer Science");
for (const auto& record : results)
{
std::cout << "ID: " << record.getField("ID") << ", Name: " << record.getField("Name") << std::endl;
}
db.deleteRecordFromTable("students", 0);
db.deleteTable("students");
return 0;
}
解释
- Record类:用unordered_map存储字段名和值,提供方法来设置和获取字段值。
- Table类:存储列名和记录,提供方法来添加和删除列、添加和删除记录。
- Database类:管理多个表,提供创建和删除表、添加和删除记录、查询表的方法。
- 文件读取功能:通过loadFromFile方法,从文件读取数据并创建相应的表和记录。
- 测试代码:展示如何使用Database类来完成创建表、添加记录、查询记录、删除记录和表的操作。
完整代码
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <fstream>
#include <sstream>
#include <algorithm>
class Record
{
public:
std::unordered_map<std::string, std::string> fields;
void setField(const std::string& fieldName, const std::string& value)
{
fields[fieldName] = value;
}
std::string getField(const std::string& fieldName) const
{
auto it = fields.find(fieldName);
if (it != fields.end())
{
return it->second;
} else
{
return "";
}
}
};
class Table
{
public:
std::vector<std::string> columnNames;
std::vector<Record> records;
void addColumn(const std::string& columnName)
{
columnNames.push_back(columnName);
}
void removeColumn(const std::string& columnName)
{
columnNames.erase(std::remove(columnNames.begin(), columnNames.end(), columnName), columnNames.end());
for (auto& record : records)
{
record.fields.erase(columnName);
}
}
void addRecord(const Record& record)
{
records.push_back(record);
}
void deleteRecord(int index)
{
if (index >= 0 && index < records.size())
{
records.erase(records.begin() + index);
}
}
Record* getRecord(int index)
{
if (index >= 0 && index < records.size())
{
return &records[index];
} else
{
return nullptr;
}
}
};
class Database
{
private:
std::unordered_map<std::string, Table> tables;
public:
void createTable(const std::string& tableName, const std::vector<std::string>& columns)
{
Table newTable;
for (const auto& column : columns)
{
newTable.addColumn(column);
}
tables[tableName] = newTable;
}
void deleteTable(const std::string& tableName)
{
tables.erase(tableName);
}
Table* getTable(const std::string& tableName)
{
auto it = tables.find(tableName);
if (it != tables.end())
{
return &(it->second);
} else
{
return nullptr;
}
}
void addRecordToTable(const std::string& tableName, const Record& record)
{
auto table = getTable(tableName);
if (table)
{
table->addRecord(record);
}
}
void deleteRecordFromTable(const std::string& tableName, int index)
{
auto table = getTable(tableName);
if (table)
{
table->deleteRecord(index);
}
}
std::vector<Record> queryTable(const std::string& tableName, const std::string& columnName, const std::string& value)
{
std::vector<Record> results;
auto table = getTable(tableName);
if (table)
{
for (const auto& record : table->records)
{
if (record.getField(columnName) == value)
{
results.push_back(record);
}
}
}
return results;
}
void loadFromFile(const std::string& tableName, const std::string& filePath)
{
std::ifstream file(filePath);
if (!file.is_open())
{
std::cerr << "Error opening file: " << filePath << std::endl;
return;
}
std::string line;
if (std::getline(file, line))
{
std::istringstream iss(line);
std::vector<std::string> columns;
std::string column;
while (std::getline(iss, column, ','))
{
columns.push_back(column);
}
createTable(tableName, columns);
}
Table* table = getTable(tableName);
if (!table) return;
while (std::getline(file, line))
{
std::istringstream iss(line);
std::string value;
Record record;
int colIndex = 0;
while (std::getline(iss, value, ','))
{
if (colIndex < table->columnNames.size())
{
record.setField(table->columnNames[colIndex], value);
colIndex++;
}
}
table->addRecord(record);
}
file.close();
}
};
int main()
{
Database db;
db.loadFromFile("employee", "employee_data.txt");
db.createTable("students", {"ID", "Name", "Major"});
Record student;
student.setField("ID", "12345");
student.setField("Name", "Alice");
student.setField("Major", "Computer Science");
db.addRecordToTable("students", student);
auto results = db.queryTable("students", "Major", "Computer Science");
for (const auto& record : results)
{
std::cout << "ID: " << record.getField("ID") << ", Name: " << record.getField("Name") << std::endl;
}
db.deleteRecordFromTable("students", 0);
db.deleteTable("students");
return 0;
}
测试数据文件(employee_data.txt)
你需要创建一个文件employee_data.txt
来存储雇员信息,例如:
Employee,Name,Department,Boss
111-11-1234,Cruz,ACC,Warder
213-44-5649,Johnston,MIS,Michaels
321-88-7895,Tom,FIN,Bearskin
运行步骤
- 确保C++编译器安装正确。
- 保存上述代码到一个文件,比如
源.cpp
。 - 创建测试数据文件
employee_data.txt
,并将其内容按照上述格式填写。 - 进行编译运行程序
这样,你就可以看到程序的输出,验证各项功能是否正常工作。