课设要求:实现一个简单的歌曲管理系统,允许用户添加、编辑、删除、搜索和展示歌曲信息。系统将使用文本文件存储歌曲数据,以便用户可以在关闭后保持数据持久性。
PS:新手上路,还望各位大佬门们多多指教🤞🤞
1. 功能需求
1.1 数据结构
- 需要定义一个
Song
结构,包含以下属性:songNumber
(歌曲编号,整数)songName
(歌曲名称,字符串)singer
(歌手,字符串)language
(语言,字符串,可选为中文或英文)releaseDate
(发行日期,字符串)downloads
(下载量,整数)
1.2 主要功能
-
歌曲添加功能
- 用户可以输入歌曲编号、名称、歌手、语言、发行日期和下载量,系统将该歌曲信息添加到歌曲数据库中。
- 歌曲编号必须是唯一的,重复编号的添加会被拒绝。
-
歌曲编辑功能
- 用户可以通过输入歌曲编号来查找并编辑已有歌曲的信息,包括名称、歌手、语言、发行日期和下载量。
- 若歌曲编号不存在,系统需要提示用户。
-
歌曲删除功能
- 用户可以根据歌曲编号删除指定的歌曲。
- 若歌曲编号不存在,系统需要提示用户。
-
歌曲展示功能
- 系统可以显示当前所有歌曲的信息,包括编号、名称、歌手、语言、发行日期和下载量。
- 当数据库为空时,系统需要给出提示信息。
-
歌曲搜索功能
- 用户可以通过歌曲名称、编号或歌手进行搜索,系统将返回符合条件的歌曲信息。
-
歌曲计数功能
- 系统可以显示数据库中当前歌曲的总数量。
-
插入歌曲功能
- 用户可以在指定位置插入新歌曲,确保原有歌曲的编号保持正确的顺序。
- 位置的范围应在当前数据库大小内。
-
歌曲排序功能
- 系统可以根据歌曲编号对数据库中的歌曲进行升序排序。
1.3 持久化存储
- 所有的歌曲数据需要能够保存到名为
songs.txt
的文件中,程序启动时加载该文件中的数据。 - 应用程序在关闭时,会将当前的歌曲数据库保存到该文件中。
2. 用户界面需求
- 该系统应通过命令行界面与用户交互,提供清晰的文本提示。
- 用户操作应简单易懂,系统应及时给出操作结果反馈。
3. 安全与错误处理
- 系统需对子操作进行合理的错误处理,如文件打开失败、输入格式错误等。
- 对用户输入的数据进行基本的验证,以确保数据的正确性。
头文件:
1.头文件分析
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include<sstream>
#include <string>
using namespace std;
<iostream>
: 包含输入输出流的函数<vector>
: 提供动态数组的实现,vector<Song>
被用作歌曲数据库的存储。<algorithm>
:用于排序以及查找功能。本代码中,使用了sort
和find_if
。<fstream>
: 提供文件输入输出的功能,支持在文件中读取和写入。这里的ifstream
和ofstream
用于加载和保存歌曲数据。<sstream>
: 提供字符串流的支持<string>
: 提供字符串类std::string
,用于处理和存储文本数据。
2.数据结构:
struct Song
{
int songNumber;//歌曲编号
string songName;//歌曲名称
string singer;//歌手
string language;//语言
string releaseDate;//发行日期
int downloads;//下载量
};
- Song 结构体:定义了一个包含歌曲信息的数据结构,包括歌曲编号、名称、歌手、语言、发行日期和下载量。
3.主功能函数分析
1. 保存数据到文件
void saveToFile()
{ ofstream file("songs.txt"); ... }
- 检查文件是否成功打开。
- 遍历
songDatabase
向量并将每首歌曲的信息写入songs.txt
文件。 - 使用简单的空格分隔符分隔各字段。
2. 从文件加载数据
void loadFromFile()
{ ifstream file("songs.txt"); ... }
- 检查文件是否存在,若不存在则输出错误信息。
- 逐行读取数据并构建
Song
对象,使用push_back
方法添加到songDatabase
。 - 需要注意的是,如果文件格式不正确,可能会导致读取失败。
3. 添加歌曲
void addSong()
{ Song newSong; ... }
- 用户输入歌曲信息,并检查编号的唯一性。
- 使用
getline
方法确保能够读取包含空格的歌曲名称或歌手信息。 - 将新歌曲添加到
songDatabase
中。
4. 显示所有歌曲
void displaySongs()
{ ... }
- 检查
songDatabase
是否为空,若不为空则遍历元素并输出每首歌的信息。
5. 编辑歌曲
void editSong()
{ ... }
- 用户输入要编辑的歌曲编号,如果找到了相应的歌曲,则允许用户输入新信息并替换旧信息。
- 使用
find_if
函数寻找歌曲。
6. 删除歌曲
void deleteSong()
{ ... }
此处删除歌曲时直接调用 erase
方法进行删除。
PS:
如何使用 erase
erase
是被用来删除在songDatabase
向量中的歌曲。以下是关于如何使用它的一些细节:
- 在确定要删除的元素之后,通常先用
remove_if
或其他方法确定要删除的元素,并获得指向新“尾部”的迭代器。- 将
remove_if
返回的迭代器与vector::end()
传递给erase
方法,以便实际删除这些元素。
7. 插入歌曲
void insertSong()
{ ... }
- 显示现有歌曲列表,要求用户输入插入位置,并进行验证。
- 调用
addSong
函数用于添加新歌曲。
8. 排序歌曲
void sortSongs()
{ sort(songDatabase.begin(), songDatabase.end(), [](const Song& s1, const Song& s2)
{ return s1.songNumber < s2.songNumber; }); }
- 使用
sort
对songDatabase
进行排序。
9.统计歌曲数量:
void countSongs()
{
cout << "总歌曲数量: " << songDatabase.size() << endl;
}
countSongs
函数用于计算当前songDatabase
中存储的歌曲数量,并输出。
10.歌曲搜索功能:
void searchSongs()
{
}
-
searchSongs
函数的主要功能是根据用户的输入来查找歌曲。用户可以选择按歌曲名称、编号或者歌手进行搜索。 - 输入处理:使用
cin >> ws
来清理输入中的前导空白,确保可以读取字符串。 - 搜索逻辑:根据用户选择的搜索类型,通过不同的条件判断从
songDatabase
中查找匹配的歌曲。 - 对于按编号搜索,则找出并显示符合条件的那首歌曲。
- 对于按名称和按歌手搜索,使用了
vector
来收集所有匹配的结果并输出
源代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include<sstream>
#include <string>
using namespace std;
struct Song
{
int songNumber;
string songName;
string singer;
string language;
string releaseDate;
int downloads;
};
vector<Song> songDatabase;
//储存
void saveToFile()
{
ofstream file("songs.txt");
if (!file)
{
cout << "无法打开文件。" << endl;
return;
}
for (const auto& song : songDatabase)
{
file << song.songNumber << " " << song.songName << " " << song.singer << " " << song.language << " " << song.releaseDate << " " << song.downloads << endl;
}
cout << "歌曲已保存到文件。" << endl;
}
//加载文件
void loadFromFile()
{
ifstream file("songs.txt");
if (!file) {
cout << "无法打开文件。" << endl;
return;
}
songDatabase.clear();
int songNumber;
string songName, singer, language, releaseDate;
int downloads;
while (file >> songNumber >> songName >> singer >> language >> releaseDate >> downloads) {
Song song = { songNumber, songName, singer, language, releaseDate, downloads };
songDatabase.push_back(song);
}
cout << "歌曲已从文件加载。" << endl;
}
//添加
void addSong()
{
Song newSong;
cout << "请输入歌曲编号: ";
cin >> newSong.songNumber;
for (const auto& song : songDatabase) {
if (song.songNumber == newSong.songNumber) {
cout << "歌曲编号已存在,取消添加。" << endl;
return;
}
}
cout << "请输入歌曲名称: ";
cin >> ws;
getline(cin, newSong.songName);
cout << "请输入歌手: ";
cin >> ws;
getline(cin, newSong.singer);
cout << "请选择语言 (1. 中文 2. 英文): ";
int languageChoice;
cin >> languageChoice;
newSong.language = (languageChoice == 1) ? "中文" : "英文";
cout << "请输入发行日期 (YYYY-MM-DD): ";
cin >> ws;
getline(cin, newSong.releaseDate);
cout << "请输入下载量: ";
cin >> newSong.downloads;
songDatabase.push_back(newSong);
cout << "歌曲添加成功。" << endl;
}
//显示歌曲
void displaySongs()
{
if (songDatabase.empty())
{
cout << "没有任何歌曲。" << endl;
return;
}
cout << "歌曲列表: " << endl;
for (const auto& song : songDatabase)
{
cout << "歌曲编号: " << song.songNumber << ", 名称: " << song.songName << ", 歌手: " << song.singer << ", 语言: " << song.language << ", 发行日期: " << song.releaseDate << ", 下载量: " << song.downloads << endl;
}
}
//编辑与修改
void editSong()
{
int songNumber;
cout << "请输入要编辑的歌曲编号: ";
cin >> songNumber;
auto song = find_if(songDatabase.begin(), songDatabase.end(), [songNumber](const Song& s)
{
return s.songNumber == songNumber;
});
if (song != songDatabase.end())
{
cout << "请输入新的歌曲名称: ";
cin >> song->songName;
cout << "请输入新的歌手: ";
cin >> song->singer;
cout << "请输入新的语言: ";
cin >> song->language;
cout << "请输入新的发行日期: ";
cin >> song->releaseDate;
cout << "请输入新的下载量: ";
cin >> song->downloads;
cout << "歌曲编辑成功。" << endl;
}
else
{
cout << "未找到歌曲。" << endl;
}
}
//删除
void deleteSong()
{
int songNumber;
cout << "请输入要删除的歌曲编号: ";
cin >> songNumber;
auto song = find_if(songDatabase.begin(), songDatabase.end(), [songNumber](const Song& s)
{
return s.songNumber == songNumber;
});
if (song != songDatabase.end())
{
songDatabase.erase(song);
cout << "歌曲删除成功。" << endl;
}
else
{
cout << "未找到歌曲。" << endl;
}
}
//插入添加
void insertSong()
{
displaySongs();
int position;
cout << "请输入要插入歌曲的位置 (0-" << songDatabase.size() << "): ";
cin >> position;
if (position >= 0 && position <= songDatabase.size())
{
Song newSong;
cout << "请输入歌曲编号: ";
cin >> newSong.songNumber;
for (const auto& song : songDatabase)
{
if (song.songNumber == newSong.songNumber)
{
cout << "歌曲编号已存在,取消插入。" << endl;
return;
}
}
addSong();
}
else
{
cout << "无效的位置,取消插入。" << endl;
}
}
void sortSongs()
{
sort(songDatabase.begin(), songDatabase.end(), [](const Song& s1, const Song& s2)
{
return s1.songNumber < s2.songNumber;
});
cout << "歌曲已按歌曲编号排序。" << endl;
}
void countSongs() {
cout << "总歌曲数量: " << songDatabase.size() << endl;
}
void searchSongs() {
if (songDatabase.empty()) {
cout << "歌曲数据库为空,无需搜索。" << endl;
return; // 如果数据库为空,直接返回
}
int searchType;
cout << "请选择搜索类型 (1.按歌曲名称 2. 按歌曲编号 3. 按歌手): ";
cin >> searchType;
if (searchType == 1)
{
string songName;
cout << "请输入歌曲名称: ";
cin >> ws;
getline(cin, songName);
auto song = find_if(songDatabase.begin(), songDatabase.end(), [&songName](const Song& s)
{
return s.songName == songName;
});
if (song != songDatabase.end()) {
cout << "找到的歌曲: [编号: " << song->songNumber << "] 名称: " << song->songName
<< ", 歌手: " << song->singer << ", 语言: " << song->language
<< ", 发行日期: " << song->releaseDate << ", 下载量: " << song->downloads << endl;
}
else {
cout << "未找到歌曲。" << endl;
}
}
else if (searchType == 2) {
int songNumber;
cout << "请输入歌曲编号: ";
cin >> songNumber; // 直接使用 cin 读取整数
auto song = find_if(songDatabase.begin(), songDatabase.end(), [songNumber](const Song& s) {
return s.songNumber == songNumber; // 直接比较整数
});
if (song != songDatabase.end()) {
cout << "找到的歌曲: [编号: " << song->songNumber << "] 名称: " << song->songName
<< ", 歌手: " << song->singer << ", 语言: " << song->language
<< ", 发行日期: " << song->releaseDate << ", 下载量: " << song->downloads << endl;
}
else {
cout << "未找到歌曲。" << endl;
}
}
else if (searchType == 3) {
string singer;
cout << "请输入歌手: ";
cin >> ws;
getline(cin, singer);
auto song = find_if(songDatabase.begin(), songDatabase.end(), [&singer](const Song& s) {
return s.singer == singer;
});
if (song != songDatabase.end()) {
cout << "找到的歌曲: [编号: " << song->songNumber << "] 名称: " << song->songName
<< ", 歌手: " << song->singer << ", 语言: " << song->language
<< ", 发行日期: " << song->releaseDate << ", 下载量: " << song->downloads << endl;
}
else {
cout << "未找到歌曲。" << endl;
}
}
else {
cout << "无效的搜索类型。" << endl;
}
}
int main()
{
int choice;
while (true)
{
cout << "1. 从文件加载" << endl;
cout << "2. 添加歌曲" << endl;
cout << "3. 删除歌曲" << endl;
cout << "4. 修改歌曲" << endl;
cout << "5. 显示歌曲" << endl;
cout << "6. 插入添加歌曲" << endl;
cout << "7. 统计歌曲数量" << endl;
cout << "8. 搜索歌曲" << endl;
cout << "9. 歌曲排序" << endl;
cout << "10. 保存到文件" << endl;
cout << "11. 退出" << endl;
cout << "请输入选择: ";
cin >> choice;
switch (choice)
{
case 1:
loadFromFile();
break;
case 2:
addSong();
break;
case 3:
deleteSong();
break;
case 4:
editSong();
break;
case 5:
displaySongs();
break;
case 6:
insertSong();
break;
case 7:
countSongs();
break;
case 8:
searchSongs();
break;
case 9:
sortSongs();
break;
case 10:
saveToFile();
break;
default:
return 0;
}
}
}