先给出要求:

设计一个KTV点歌系统,该系统的主要功能是管理员对歌曲进行管理、统计等操作、以及用户根据关键字或风格等对歌曲进行查询等操作

  1. 程序主函数:系统入口,监控程序运行。
  2. 系统界面要求:接收键盘输入,根据跳转相应界面或输出错误信息,可以自行设计欢迎、欢送等界面,使系统界面更美观、友好。
  3. 设置两个用户登录模式,一个是管理员、另一个是用户。
  4. 管理员对歌曲进行增删改查,并进行对歌曲火热度的统计。
  5. 用户对歌曲进行查找,并进行对歌曲的打分等操作。
  6. 退出功能:在分支服务界面选择退出时返回上一级界面,在主界面退出时直接退出程序。

我这个代码运用到的算法有二叉排序树(实现排行榜的功能),kmp算法(实现模糊查询)

没有任何套路,完全是自己手搓,大概600多行,如果觉得帮到你了,麻烦点个赞谢谢!!

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <windows.h>
#define MAX_SONGS 1000
#define MAX_ARTISTS 1000
// 歌曲结构体
typedef struct {char name[100];char artist[100];char genre[50];int rating_count;    //点到该首歌的次数float rating;        //该首歌的评分
} Song;// 用户结构体
typedef struct {char username[50];char password[50];bool isAdmin;    //判断是否为管理员,如果是就为1,若不是就为0
} User;// 歌曲列表结构体
typedef struct {Song songs[MAX_SONGS];//表示全部歌曲的集合int count;           //记录一共有多少首,起到一个循环调用控制作用
} SongList;// 用户列表结构体
typedef struct {User users[MAX_ARTISTS];int count;
} UserList;// 树节点结构体
typedef struct tree_node {Song* song;struct tree_node* left;struct tree_node* right;
} TreeNode;
void insert_song(TreeNode** root, Song* song);
void inorder_traversal(TreeNode* root);
void generate_ranking(SongList* list);
Song* findSong(SongList* list, const char* name,int flag);
User* adminLoginView(UserList* users, SongList* list);
User* userLoginView(UserList* users, SongList* list);
void adminMenu();
void userMenu();
void addSongView(SongList* list);
void removeSongView(SongList* list);
void updateSongView(SongList* list);
void countHotnessView(SongList* list);
void searchSongView(SongList* list);
void rateSongView(SongList* list, Song* song);
void daily_recommendation(SongList list);//管理员注册
void register_ADM(UserList* userlist) {system("cls");printf("\n**************************欢迎来到ktv点歌系统***********************************\n");printf("注册请填写以下信息:\n");printf("请输入您的账户名字(不超过 32 个字符):");scanf("%s", userlist->users[userlist->count].username);getchar();printf("密码(不超过 32 个字符):");scanf("%s", userlist->users[userlist->count].password);// 保存用户信息到文件中FILE* fp;int user_count = userlist->count;if ((fp = fopen("users.txt", "a")) != NULL) {fprintf(fp, "%s %s %d\n", userlist->users[user_count].username, userlist->users[user_count].password, 1);fclose(fp);printf("注册成功,请返回上一级,重新登录!\n");}else {printf("无法打开文件!\n");}getchar();getchar();return;
}//用户注册
void register_user(UserList * userlist) {system("cls");printf("\n**************************欢迎来到ktv点歌系统***********************************\n");printf("注册请填写以下信息:\n");printf("请输入您的账户名字(不超过 32 个字符):");scanf("%s", userlist->users[userlist->count].username);getchar();printf("密码(不超过 32 个字符):");scanf("%s", userlist->users[userlist->count].password);// 保存用户信息到文件中FILE* fp;int user_count = userlist->count;if ((fp = fopen("users.txt", "a")) != NULL) {fprintf(fp, "%s %s %d\n", userlist->users[user_count].username, userlist->users[user_count].password, 0);fclose(fp);printf("注册成功,请返回上一级,重新登录!\n");}else {printf("无法打开文件!\n");}getchar();getchar();return;
}//构建二叉排序树
void insert_song(TreeNode** root, Song* song) {// 如果树为空,直接将歌曲作为根节点if (*root == NULL) {*root = (TreeNode *)malloc(sizeof(TreeNode));(*root)->song = song;(*root)->left = NULL;(*root)->right = NULL;return;}// 如果树非空,则根据歌曲的热度值进行插入if (song->rating_count >= (*root)->song->rating_count) {insert_song(&((*root)->left), song);}else {insert_song(&((*root)->right), song);}
}// 显示歌曲列表
void show_song_list(SongList* songlist) {int num=1;printf("===============================================================\n");printf("歌曲编号\t歌曲名称\t歌手\t\t类型\t评分\n");printf("===============================================================\n");for (int i = 0; i < songlist->count; i++) {printf("%-8d\t%-10s %-10s\t%s\t%.2f\n",num++, songlist->songs[i].name, songlist->songs[i].artist, songlist->songs[i].genre, songlist->songs[i].rating);}printf("===============================================================\n");
}//点歌
void play_song(SongList* songlist) {system("cls");show_song_list(songlist);int song_id=0;printf("请输入你要点歌的编号:");scanf("%d", &song_id);printf("正在播放《%s》演唱者:%s\n", songlist->songs[song_id-1].name, songlist->songs[song_id-1].artist);getchar();getchar();rateSongView(songlist,&songlist->songs[song_id-1]);
}// 中序遍历树并输出歌曲信息
void inorder_traversal(TreeNode* root) {static int count = 0;if (root != NULL) {inorder_traversal(root->left);printf("第%d. %s - %s (%s, hotness: %.2d  评分: %.2f)\n", ++count, root->song->artist, root->song->name, root->song->genre, root->song->rating_count, root->song->rating);inorder_traversal(root->right);}
}// 对歌曲进行分类并生成排行榜
void generate_ranking(SongList* list) {TreeNode* root = NULL;// 将歌曲插入二叉排序树中并按热度值排序for (int i = 0; i < list->count; i++) {insert_song(&root, &(list->songs[i]));}inorder_traversal(root);getchar();getchar();
}//输出全部歌曲
void getlist(SongList* list)
{for (int i = 0; i < list->count; i++){printf("%s - %s (%s, hotness: %d, rating: %.2f)\n", list->songs[i].artist, list->songs[i].name, list->songs[i].genre, list->songs[i].rating_count, list->songs[i].rating);}getchar();getchar();
}//获取next数组
void GetNext(char* pattern, int len, int* next) {int i = 0, j = next[0] = -1;while (i < len - 1) {if (j == -1 || pattern[i] == pattern[j]) {++i;++j;next[i] = (pattern[i] != pattern[j]) ? j : next[j];}else {j = next[j];}}
}//基于kmp算法的模糊查询
int  kmp(char* text,int n,char* pattern,int m) {int* next = (int*)malloc(sizeof(int) * m);GetNext(pattern, m, next);int count = 0;// text和pattern的下标int i = 0, j = 0;while (i < n&&j<m) {if (j == -1 || text[i] == pattern[j]) {++i;++j;}else {j = next[j];}}if (j >= m)return 1;else return 0;
}//模糊查找函数
Song* findSong(SongList* list,char* keyword,int flag) {int found=0;printf("已找到下列歌曲:\n");printf("===============================================================\n");printf("歌曲名称\t歌手\t\t类型\t评分\n");printf("===============================================================\n");for (int i = 0; i < list->count; i++) {if (kmp(list->songs[i].name, strlen(list->songs[i].name), keyword, strlen(keyword))||kmp(list->songs[i].artist, strlen(list->songs[i].artist), keyword, strlen(keyword)) ||kmp(list->songs[i].genre, strlen(list->songs[i].genre), keyword, strlen(keyword))) {printf("%-10s %-10s\t%s\t%.2f\n",  list->songs[i].name, list->songs[i].artist, list->songs[i].genre, list->songs[i].rating);found = 1;}}if (!found) printf("未找到匹配的歌曲!\n");if(flag==0){ printf("是否继续查找歌曲?\n");int choose;printf("1.继续查找\n");printf("2.返回上一级\n");scanf("%d", &choose);if (choose == 1){system("cls");searchSongView(list);}else return;}
}// 管理员登录界面
User* adminLoginView(UserList* users, SongList* list) {char username[50];char password[50];int flag = 0;while (flag == 0){printf("管理员账号\n ");scanf("%s", username);getchar();printf("密码:\n");scanf("%s", password);int i;for (i = 0; i < users->count; i++) {if (strcmp(users->users[i].username, username) == 0 && strcmp(users->users[i].password, password) == 0 && users->users[i].isAdmin) {flag = 1;break;}}if (i >= users->count) {printf("账户或者密码输入错误,请重新输入\n"); flag = 0;}}while(1){int choice;system("cls");printf("欢迎回来,尊敬的%s\n", username);printf("请选择你想要执行的操作:\n ");adminMenu();scanf("%d", &choice);switch (choice) {case 1:system("cls");addSongView(list);break;case 2:system("cls");removeSongView(list);break;case 3:system("cls");getlist(list);break;case 4:        system("cls");countHotnessView(list);break;case 5:return;break;default:printf("错误的选择!!\n");}}return NULL;
}// 用户登录界面
User* userLoginView(UserList* users, SongList* list) {char username[50];char password[50];int flag = 0;while(flag==0){printf("用户名:");scanf("%s", username);getchar();printf("密码:");scanf("%s", password);int i;for (i = 0; i < users->count; i++) {if (strcmp(users->users[i].username, username) == 0 && strcmp(users->users[i].password, password) == 0 && !users->users[i].isAdmin) {flag = 1;break;}}if (i >= list->count) {printf("请重新输入账户和密码!\n"); flag = 0;system("cls");}}system("cls");printf("用户登陆成功!\n");while (1){daily_recommendation(*list);// 用户登录状态下显示用户菜单userMenu();int choice;printf("请输入你想要实现的功能:\n ");scanf("%d", &choice);switch (choice) {case 1:system("cls");searchSongView(list);break;case 2:system("cls");play_song(list);break;case 3:system("cls");return 0;break;default:printf("Error: Invalid choice.\n");}}return NULL;}// 管理员菜单
void adminMenu() {printf("\n请问您要执行哪项功能?\n");printf("1. 添加歌曲\n");printf("2. 删除歌曲\n");printf("3. 查找歌曲\n");printf("4. 查看热度值排名\n");printf("5. 登出!\n");
}// 用户菜单
void userMenu() {printf("\n请问您还要执行哪些功能呢?\n");printf("1. 查找歌曲\n");printf("2. 点歌\n");printf("3. 登出\n");
}// 添加歌曲界面
void addSongView(SongList* list) {printf("\n**************************添加歌曲***********************************\n");char name[100];char artist[100];char genre[50];float hotness;getchar();printf("歌名: ");gets(name);printf("歌手: ");gets(artist);printf("风格: ");gets(genre);if (list->count >= MAX_SONGS) {printf("歌库满了,请删点歌吧\n");return;}//在尾部插入歌曲信息strcpy(list->songs[list->count].name, name);strcpy(list->songs[list->count].artist, artist);strcpy(list->songs[list->count].genre, genre);list->songs[list->count].rating_count = 0;list->songs[list->count].rating = 0.0;//一开始都初始化为0,因为没有人点list->count++;FILE* fp = fopen("songs.txt", "a");if (fp != NULL) {fprintf(fp, "%s %s %s %d %.2f\n", name, artist, genre,0, 0.0);fclose(fp);printf("歌曲添加成功!\n");printf("是否继续添加歌曲?");int choose;printf("1.继续添加");printf("2.返回上一级");scanf("%d", &choose);if (choose == 1){system("cls");addSongView(list);}else return;}else {printf("打不开文件\n");}
}// 删除歌曲界面
void removeSongView(SongList* list) {printf("\n**************************删除歌曲***********************************\n");show_song_list(list);char name[100];getchar();printf("请选择需要删除的歌名: ");gets(name);int i;                                        //bug!!!!!根本就不执行下面的for直接就退出了for (i = 0; i < list->count; i++) {if (strcmp(list->songs[i].name, name) == 0) {printf("成功移除歌曲: %s\n", name);getchar();list->count--;for (int j=i; j< list->count; j++) {list->songs[j] = list->songs[j + 1];}//将歌曲从list数组中删除FILE* fp = fopen("songs.txt", "w");if (fp != NULL) {for (int i = 0; i < list->count; i++) {fprintf(fp, "%s %s %s %d %.2f\n",list->songs[i].name, list->songs[i].artist, list->songs[i].genre,list->songs[i].rating_count, list->songs[i].rating);}fclose(fp);}else {printf("打开文件错误!!\n");}break;}}printf("是否继续删除歌曲?\n");int choose;printf("1.继续删除\n");printf("2.返回上一级\n");scanf("%d", &choose);if (choose == 1){system("cls");removeSongView(list);}else return;
}// 统计歌曲火热度界面
void countHotnessView(SongList* list) {printf("************************歌曲火热度排行榜*******************************\n");generate_ranking(list);
}// 搜索歌曲界面
void searchSongView(SongList* list) {printf("\n************************搜索歌曲*******************************\n");char name[100];int count=0;printf("请输入歌名或歌名或风格:");scanf("%s", name);findSong(list, name,0);system("cls");
}//每日随机推荐
void daily_recommendation(SongList list) {// 使用当前时间戳作为随机数种子srand((unsigned)time(NULL));// 随机选择一首歌曲int song_index = rand() % list.count;Song* recommended_song = &(list.songs[song_index]);printf("今日推荐:[%s] - %s (%s),评分:%.2f\n",recommended_song->name,recommended_song->artist,recommended_song->genre,recommended_song->rating);
}// 对歌曲进行评分界面
void rateSongView(SongList* list,Song* song) {system("cls");printf("\n**************************歌曲评分***********************************\n");char name[100];if (song != NULL) {int rating;printf("1-5分你打几分?: ");scanf("%d", &rating);if (rating >= 1 && rating <= 5) {song->rating_count++;song->rating = (song->rating * (song->rating_count - 1) + rating) / song->rating_count;//统计歌曲的评分FILE* fp = fopen("songs.txt", "w");if (fp != NULL) {for (int i = 0; i < list->count; i++) {fprintf(fp, "%s %s %s %d %.2f\n",list->songs[i].name, list->songs[i].artist, list->songs[i].genre,list->songs[i].rating_count, list->songs[i].rating);}fclose(fp);printf("评分成功%s\n", song->name);}else {printf("没有找到文件\n");}}else {printf("错误的输入\n");}}else {printf("没有找到该歌曲.\n");}getchar();getchar();system("cls");
}void init_song_list(SongList* songlist) {songlist->count = 0;
}int main() {FILE* fp = fopen("songs.txt", "r");SongList list;init_song_list(&list);if (fp != NULL) {while (list.count < MAX_SONGS) {Song new_song;int result = fscanf(fp, "%s %s %s %d %f\n", new_song.name, new_song.artist, new_song.genre, &(new_song.rating_count), &(new_song.rating));if (result == 5) {// 成功读取一行,将新歌曲加入列表list.songs[list.count++] = new_song;}else if (result == EOF) {// 已到达文件末尾,退出循环break;}else {// 格式错误,忽略该行,并继续读取下一行char buffer[256];fgets(buffer, 256, fp);}}fclose(fp);}else {printf("打开文件失败!\n");return 1;}// printf("%d\n", list.count);    // 从文件中读取用户列表fp = fopen("users.txt", "r");UserList userList;userList.count = 0;if (fp != NULL) {while (fscanf(fp, "%s %s %d\n", userList.users[userList.count].username, userList.users[userList.count].password, &(userList.users[userList.count].isAdmin)) == 3) {userList.count++;}fclose(fp);}else {printf("打开文件失败!\n");}User* currentUser = NULL;while (1) {if (currentUser == NULL) {// 未登录状态下显示登录界面printf("\n\t\t***************************************************************\n");printf("\t\t*欢迎光临咱家的ktv,祝你在这里能玩的开心!请选择下列两种登录方式 *\n");printf("\n\t\t**********************************************\n");printf("\t\t*  1. 管理员登录                             *\n");printf("\t\t*  2. 用户登录                               *\n");printf("\t\t*  3. 用户注册                               *\n");printf("\t\t*  4. 管理员注册                               *\n");printf("\t\t*  5. 退出                                   *\n");printf("\t\t**********************************************\n\n");int choice;printf("\t\t请选择需要实现的功能: ");scanf("%d", &choice);switch (choice) {case 1:adminLoginView(&userList,&list);system("cls");break;case 2:userLoginView(&userList,&list);system("cls");break;case 3:register_user(&userList);system("cls");break;case 4:register_ADM(&userList);system("cls");break;case 5:exit(0);default:printf("Error: Invalid choice.\n");}}}return 0;
}

大一课设ktv点歌系统c语言相关推荐

  1. 广东工业大学数据库课设(点歌系统)

    摘 要 本论文主要是对卡拉OK点歌系统的设计过程,后端设计,前端设计,数据库设计的分析.结合软件工程已经数据库系统概论所学知识,详细内容是系统的实现背景,设计过程,功能的实现以及部分的个人感悟. 前言 ...

  2. c语言课设仓库管理系统,c语言课设仓库管理系统.doc

    <高级语言程序设计>课程设计 小型仓库管理系统 小型仓库管理系统 题 目: 班 级: 学生学号: 学生姓名: 同组成员: 指导老师: 提交时间: 成 绩: 华南农业大学 信息学院 需求分析 ...

  3. 对大一C语言的课程设计——KTV点歌系统的介绍(链表)

    写此博客的目的:一是为了让自己对链表的思考方式更加的清晰,二是对不清楚链表实现方式的讲解! 所有的菜单都没有进行讲解,太简单.另外建议写这种比较大的程序的时候,不要着急先写菜单,要先把每一个功能实现完 ...

  4. c语言售票系统主要函数,c语言课设电影院售票系统.docx

    struct inf { char rate[20]; char name[20]; int time_hour; int time_min; int seat; int sell; }inf[10] ...

  5. C语言课程设计-KTV点歌系统

    需求分析: 1.设计题目:KTV点歌系统模拟(该系统是一个常用的ktv点歌系统,可以让用户根据自己的喜好进行添加.查看.删除等操作.系统应该具有便捷.稳定.功能齐全的特点.) 2.系统功能需求分析: ...

  6. c语言课设报告仓库管理系统,c语言课设仓库管理系统.doc

    c语言课设仓库管理系统.doc 高级语言程序设计课程设计小型仓库管理系统题 目班 级学生学号学生姓名 同组成员 指导老师 提交时间 成 绩华南农业大学 信息学院一. 需求分析1 系统概述本系统用于小型 ...

  7. java毕业设计KTV点歌系统mybatis+源码+调试部署+系统+数据库+lw

    java毕业设计KTV点歌系统mybatis+源码+调试部署+系统+数据库+lw java毕业设计KTV点歌系统mybatis+源码+调试部署+系统+数据库+lw 本源码技术栈: 项目架构:B/S架构 ...

  8. 点歌服务器工作原理,KTV点歌系统方案概述

    <KTV点歌系统方案概述>由会员分享,可在线阅读,更多相关<KTV点歌系统方案概述(7页珍藏版)>请在人人文库网上搜索. 1.一)目前点歌系统的主流方式目前,可以实现的KTV系 ...

  9. 点滴小组KTV点歌系统简介

    ‍‍ 20级青鸟四班 点滴小组 指导老师:穆老师 班主任:佟老师 小组成员: 组长:路鑫 副组长:戴洁 王硕 组员:马蓥芳   组员:徐圣乾 组员:徐圣坤 组员:赵昌杰 制作周期:2021年5月25日 ...

最新文章

  1. 结合批处理功能,配置SQL Server 2005,使其打开远程连接功能
  2. 如何在阅读参考文献时,有效率的做笔记?
  3. 使用Maven管理Eclipse Java项目(多modules编译)
  4. MM(Majorize-Minimization, Minorize-Maximization)优化方法
  5. 从sqlserver中数据写入mysql_从SQL server数据库导入Mysql数据库的体验
  6. 洛谷——P1033 自由落体
  7. P1525-关押罪犯【并查集】
  8. 如何提取明细表头_如何在实际操作中应用偏移修剪?
  9. 力扣116. 填充每个节点的下一个右侧节点指针(C++,附思路)
  10. 基础才是重中之重~类是怎么执行的
  11. python学习第十弹:宝可梦数据分析-平民最强
  12. FusionChartsFree在JSP中的用法
  13. 微信小程序上传图片到云储存中
  14. 双眼融合训练一个月_双眼视觉是什么?为什么要进行视功能训练?
  15. windows10开启http代理服务
  16. 感恩节特辑丨这个世界有无限可能
  17. Python实现学生成绩分析
  18. 十四、理解nn.module方法——学习python面向对象编程(一)
  19. Lvs+keepAlived实现负载均衡高可用集群(DR实现)
  20. 人工智能相关技术的快速发展,主要带来了哪些价值优势?

热门文章

  1. ubuntu nginx html文件,如何在Ubuntu 16.04上更改Nginx Web文档位置
  2. linux sort uniq -c
  3. 光伏并网柜综合监测解决方案之防孤岛保护装置
  4. Alpine Linux常用命令
  5. Python期末复习题:字符串与产生随机数
  6. 路由器多久重启一次比较好?
  7. 还在忍受网盘被下载限速?可以试试奇米快传。
  8. blinker服务器未响应,Blinker ESP32 内存不足 无法连接服务器
  9. Swagger ui接口自动化批量漏洞测试
  10. python实战——JSON转CSV