一、设计要求
KTV点歌系统:
设计并实现一个KTV点歌程序,实现点歌功能。要求实现二级菜单:
并使之能提供以下功能:
(1)显示已点歌曲:按照点歌顺序显示已点歌曲;
(2)查询已点歌曲:输入查询歌曲名称后进行查询,若存在显示歌名以及序号;若不存 在,显示:未点播此歌曲;
(3)删除已点歌曲:在显示已点歌曲后,输入删除歌曲序号,将次歌曲删除,并重新排 列序号。
(4)置顶:在显示已点歌曲后,选择置顶歌曲的序号,将歌曲置顶,并重新排序列号。 (5)上移一位:在显示已点歌曲后,选择上移一位歌曲的序号,将该歌曲上移一位后, 重新排列序号。
补充功能:
<1> 查看初始歌单
<2> 字体颜色变换
<3> 错误警告功能
<4> 查询已点歌曲
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
二、代码设计思路
数据结构如下:
Typedef struct sing { int num; char name[20]; char singer[20]; char letter1; char letter2; } Sing;
通过对项目分析,设计了上述结构类型,其中还有一个类似结构的数组(未展示),这样便于分别处理初始歌单与已歌单。因为数组便于处理固定数据,就由数组存储初始歌单(固定),链表存储需要处理的已点歌单。并且用typedef函数将struct sing结构体简化为Sing,以便于声明该结构变量。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
各功能模块的算法处理流程图及使用说明:
(1)main( )函数及program1()函数
调用program1()函数,并将返回值存储在alselect变量中。这个返回值表示用户在program1菜单 中选择的操作。
使用if-else if结构来处理用户的选择:
如果用户选择2(点歌),则调用program2()函数并清屏。
如果用户选择0(退出),则使用break语句退出循环,并退出程序。
如果用户选择1(输出歌库),则调用program3()函数,并在之后打印一个换行符。
如果用户选择3(管理已点歌),则调用program5()函数,并在之前打印一个换行符(但通常换行符应 该在调用函数之后打印,以保持输出的一致性)。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
当用户输入4时,代码执行system(“cls”);和continue;,这会导致屏幕清屏,并继续下一次循环。当用户输入一个非法的值(即不是0-4的数字)时,程序会打印“输入错误!”,暂停屏幕,清屏,然后再次显示菜单。这也是正确的行为。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
(2)int program2(),void program6()及Sing* program4()函数
通过 printf 函数,该函数创建并显示了一个包含四个选项的菜单,允许用户选择不同的歌曲排序方式。使用 scanf 函数从用户处获取输入,并将该输入存储在 num2 变量中。
如果用户输入 4,则清除屏幕并返回 0,表示用户希望返回主菜单。如果用户输入的数不在 1 到 4 之间,则打印一个错误消息,暂停屏幕,清除屏幕,并使用 continue 关键字回到循环的开始,重新显示菜单。如果用户输入的数在 1 到 3 之间,则调用 program6 函数,并传入用户的选择作为参数。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
如果num2等于3,调用program33()函数(该函数未在代码中给出),并将a赋值给b。如果num2等于1,对a所指向的数组(假设它是一个数组)按照letter1字段进行排序,并打印排序后的结果。冒泡排序实现。如果num2等于2,对a所指向的数组按照letter2字段进行排序,并打印排序后的结果。
函数最后返回b,排序后的歌曲列表的指针。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
(3)int program5()函数
system(“cls”); 在 Windows 系统中用于清屏。在调用菜单前执行,以确保屏幕上没有之前的输出。
菜单显示:
函数首先打印出一个包含多个选项的菜单供用户选择。
用户输入循环:
使用 while(1) 创建一个无限循环,直到用户选择退出(num5 == 4)。
选项处理:
根据用户输入的 num5 值,函数执行相应的操作。
显示已点歌曲:
如果链表 head(可能是用于存储已点歌曲的链表)为空,则调用 printaddsing() 函数(可能是打印一个空列表的消息)。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
在 while 循环中,current 指针沿着链表移动,直到它到达链表的末尾(即 current->next 为 NULL)。在每次迭代中,都会打印出当前节点的信息,并将 current 指向下一个节点。
当遍历完整个链表后,while 循环结束,函数返回。此时,用户可以看到已点歌曲的完整列表。
如果链表不为空,函数会提示用户输入要查找的歌曲名称,并使用 scanf 函数读取用户输入。但是,scanf 函数中 &name 的使用是错误的,因为 name 已经是一个数组名,它本身就代表了数组的首地址函数将 current 指针重置为链表的头节点,并开始遍历链表。在遍历过程中,它使用 strcmp 函数比较当前节点的歌曲名称与用户输入的歌曲名称。如果两者相等,则输出歌曲信息,将 flag 设置为 1,并使用 break 跳出循环。
如果在遍历完整个链表后仍未找到歌曲(即 flag 仍为 0),则输出一条消息告知用户未找到指定的歌曲。
无论是否找到歌曲,函数最后都会输出一条消息,提示用户选择(1-7)进行后续操作。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
(4)void delsing()
应用while以及定义俩个指针becurrent,current遍历指针,找到后判断位置选择删除方法。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
(5)void shangyising()
如果链表为空,输出提示信息。如果链表只有一个节点,输出无需上移的提示信息。提示用户输入想要上移的歌曲名称,并读取输入。遍历链表查找用户输入的歌曲。如果找到歌曲,根据歌曲在链表中的位置进行不同的处理:如果歌曲是第一个节点,则输出提示信息表示已经是第一个了。如果歌曲是第二个节点(即head->next),则将其与第一个节点交换,并更新head指针。
(6)void zhidengsing()
current:遍历链表的指针。zsing:用于临时存储当前节点current的下一个节点。temp:动态分配的节点,但在当前实现中并未正确使用。becurrent:用于存储current的前一个节点。flag:用于标记是否找到了歌曲。name:存储用户输入的歌曲名称。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈
三、代码展示
#include<stdio.h> #include <stdlib.h> #include<string.h> #include<windows.h> #include<time.h> typedef struct sing//歌单结构指针 { int num; char name[20]; char singer[20]; char letter1; char letter2; struct sing *next; } Sing; Sing* head=NULL;//全局指针 音乐库 int program1();//一级菜单07/04/24 08:54 int program2();//选2二级菜单 void program3();//初始化歌单 void program33();//初歌单 Sing* program4(int num2);//排序 int program5();//选3二级菜单 void program6(int number2);//点歌顺序 void addsingg(Sing* a,int n);//存储已点歌曲链表 void printaddsing();//打印已点歌曲 void delsing();//删除已点歌曲 void zhidengsing();//置顶 void shangyising();//上移一位 void forsing();//查找 void rangesing();//重编序号 > 👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈 //一级菜单07/04/24 08:54 int program1() { system("cls"); int select; while(1) { printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); printf("$$ $$\n"); printf("$$"); printf(" ktv点歌 $$\n"); printf("$$"); printf(" 1.查看歌曲库 $$\n"); printf("$$"); printf(" 2.点歌 $$\n"); printf("$$"); printf(" 3.修改、查看已点歌曲 $$\n"); printf("$$"); printf(" 4.返回主菜单 $$\n"); printf("$$"); printf(" 0.退出 $$\n"); printf("$$ $$\n"); printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); printf("\n"); printf("请选择:"); scanf("%d",&select); if(select>=0&&select<4) { // 代码 略... // 代码 略... // 代码 略... // 代码 略... // 代码 略... } system("cls"); } } > 👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈 //点歌菜单 int program2() { int num2=0,number2; while(1) { printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n") ; printf("*-* *-*\n"); printf("*-*"); printf(" 1)按照歌曲的拼音字母排序显示(a-z)"); printf(" *-*\n"); printf("*-*"); printf(" 2)按照演唱者的名字排序显示(a-z)"); printf(" *-*\n"); printf("*-*"); printf(" 3)按照原歌单顺序显示"); printf(" *-*\n"); printf("*-*"); printf(" 4)返回主菜单"); printf(" *-*"); printf("\n"); printf("*-* *-*"); printf("\n*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n"); printf("\n"); printf("请输入序号:"); scanf("%d",&num2); printf("\n"); if(num2==4) { system("cls"); return 0; } else if(num2<1||num2>4) { printf("输入错误请输入序号1-4\n"); system("pause"); system("cls"); continue; } else program6(num2); } system("pause"); system("cls"); } //歌单 static关键 Sing* gedan() { static Sing a[6]= { {0}, {1,"第三人称","买辣椒也用券",'d','m'}, {2,"王招君","任素汐",'w','r'}, {3,"星光就在前方","抠抠",'x','k'}, {4, "李香兰","邓紫棋",'l','d'}, {5,"带我去找夜生活","告五人",'d','g'}, };//歌单 return a; } void program3()//一级菜单输出歌单 { system("cls"); int n; printf("序号 歌名 歌手\n"); program33(); printf("输入4返回主菜单。\n") ; printf(":"); while(1) { // 代码 略... // 代码 略... // 代码 略... // 代码 略... else { printf("输入错误!重新输入。\n"); printf(":"); } } //与33的不同之处,是界面更便捷 system("cls"); } //歌单**** void program33() { // 代码 略... // 代码 略... // 代码 略... // 代码 略...> 👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈 for(int i=1; i<= 5; i++) { printf("%-10d%-16s%s\n",a[i].num,a[i].name,a[i].singer); if(i!=5) printf("\n"); } } //排序* Sing* program4(int num2) { Sing* a; Sing* b; Sing temp; // 代码 略... // 代码 略... // 代码 略...> 👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈 // 代码 略... // 代码 略... return b; } int program5()//选3管理点歌曲的二级菜单*** { system("cls"); int num5; printf("*************************\n"); printf("* 1)显示已点歌曲 *\n"); printf("* 2)查询已点歌曲 *\n"); printf("* 3)删除已点歌曲 *\n"); printf("* 4)返回主菜单 *\n"); printf("* 5)上移一位 *\n"); printf("* 6)置顶 *\n"); printf("* 7)清屏 *\n"); printf("*************************\n"); printf("\n"); printf("请选择:"); } void shangyising()//上移一位 { char name[20]; Sing* current=head; Sing* becurrent=head; Sing* zsing=head; Sing* temp=NULL; int flag=0; if(head==NULL) { printf("目前您未点歌请按4返回点歌。\n"); } else if(head->next==NULL) { printf("\n目前你只点了一首歌无需上移。\n"); printf("请选择(1-7):"); } else { printaddsing(); printf("请输入想要上移的歌曲名称:"); scanf("%s",&name); while(current!=NULL) { if(strcmp(current->name,name)==0) { if(current==head) { printf("\n%s已经是第一个了。\n",name); flag=1; break; } else if(head->next==current)//**** { zsing->next=current->next; current->next=zsing; head=current; printf("上移成功!\n") ; flag=1; break; } else { > 👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈 } } if(current!=head&¤t!=head->next) { becurrent=becurrent->next; becurrent->next=current; } current=current->next; } if(flag==0) { printf("您未点该歌曲%s\n",name); } printf("请选择(1-7):"); } } void rangesing()//已点歌曲排序 { Sing* current; int i=1; current=head; while(current!=NULL) { current->num=i; i++; current=current->next; } } > 👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈 int main() { int alselect; while(1) { alselect=program1(); if(alselect==2)//点歌 { system("cls"); program2(); } else if(alselect==0)//退出 { break; } else if(alselect==1)//输出歌库 { printf("\n"); program3(); } else if(alselect==3)//管理已点歌 { program5(); printf("\n"); } } return 0; }
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 点歌” 获取。👈👈👈