大一课设ktv点歌系统c语言

先给出要求:

设计一个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点歌系统需要实现的功能包括管理员对歌曲进行管理、统计等操作,以及用户根据关键字或风格等对歌曲进行查询等操作。下面是一个简单的KTV点歌系统C语言代码示例,实现了管理员和用户的基本功能: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SONGS 1000 #define MAX_NAME 50 #define MAX_SINGER 50 #define MAX_STYLE 20 typedef struct { char name[MAX_NAME]; char singer[MAX_SINGER]; char style[MAX_STYLE]; int score; } Song; Song songs[MAX_SONGS]; int num_songs = 0; void add_song() { if (num_songs >= MAX_SONGS) { printf("The song list is full.\n"); return; } Song song; printf("Please enter the name of the song: "); scanf("%s", song.name); printf("Please enter the name of the singer: "); scanf("%s", song.singer); printf("Please enter the style of the song: "); scanf("%s", song.style); song.score = 0; songs[num_songs++] = song; printf("The song has been added successfully.\n"); } void delete_song() { char name[MAX_NAME]; printf("Please enter the name of the song you want to delete: "); scanf("%s", name); int i; for (i = 0; i < num_songs; i++) { if (strcmp(songs[i].name, name) == 0) { int j; for (j = i; j < num_songs - 1; j++) { songs[j] = songs[j + 1]; } num_songs--; printf("The song has been deleted successfully.\n"); return; } } printf("The song is not found.\n"); } void search_song() { char keyword[MAX_NAME]; printf("Please enter the keyword you want to search: "); scanf("%s", keyword); int i; for (i = 0; i < num_songs; i++) { if (strstr(songs[i].name, keyword) != NULL || strstr(songs[i].singer, keyword) != NULL || strstr(songs[i].style, keyword) != NULL) { printf("%s - %s (%s) [%d]\n", songs[i].name, songs[i].singer, songs[i].style, songs[i].score); } } } void rate_song() { char name[MAX_NAME]; printf("Please enter the name of the song you want to rate: "); scanf("%s", name); int i; for (i = 0; i < num_songs; i++) { if (strcmp(songs[i].name, name) == 0) { int score; printf("Please enter your score (0-10): "); scanf("%d", &score); if (score < 0 || score > 10) { printf("Invalid score.\n"); return; } songs[i].score += score; printf("Your score has been added successfully.\n"); return; } } printf("The song is not found.\n"); } void show_statistics() { int i; int total_score = 0; int num_rated_songs = 0; for (i = 0; i < num_songs; i++) { if (songs[i].score > 0) { total_score += songs[i].score; num_rated_songs++; } } if (num_rated_songs == 0) { printf("No song has been rated yet.\n"); } else { printf("The average score of rated songs is %.2f.\n", (float)total_score / num_rated_songs); } } int main() { while (1) { printf("Welcome to KTV song system.\n"); printf("Please select your role:\n"); printf("1. Administrator\n"); printf("2. User\n"); printf("3. Exit\n"); int role; scanf("%d", &role); if (role == 1) { printf("Please enter the password: "); char password[10]; scanf("%s", password); if (strcmp(password, "admin") != 0) { printf("Incorrect password.\n"); continue; } while (1) { printf("Administrator menu:\n"); printf("1. Add song\n"); printf("2. Delete song\n"); printf("3. Show statistics\n"); printf("4. Back to the previous menu\n"); int choice; scanf("%d", &choice); switch (choice) { case 1: add_song(); break; case 2: delete_song(); break; case 3: show_statistics(); break; case 4: goto end; default: printf("Invalid choice.\n"); break; } } } else if (role == 2) { while (1) { printf("User menu:\n"); printf("1. Search song\n"); printf("2. Rate song\n"); printf("3. Back to the previous menu\n"); int choice; scanf("%d", &choice); switch (choice) { case 1: search_song(); break; case 2: rate_song(); break; case 3: goto end; default: printf("Invalid choice.\n"); break; } } } else if (role == 3) { break; } else { printf("Invalid role.\n"); } } printf("Goodbye.\n"); end: return 0; } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值