赞
踩
作为基础篇,实现软件的那些功能呢?
a.构建基本框架
b.围绕歌曲信息的增删查改进行的
c.将内容通过文件操作存进文档
d.整理歌曲内容(排序)
e.实现简单的歌曲播放功能
有人可能就会问了,需要掌握C语言那些知识才能实现这些功能呢?
主要是 :数组,函数,指针,结构体,文件操作等知识即可.
接下来,带大家一起实操
首先,为了让部分功能分工明确,我们可以建立三个cpp文件,(播放音乐需要在c++的环境下)一个头文件,将他看成一个盖房子的过程:
CL-music.h 头文件(建筑图纸)
Basic struct.cpp 用来构建框架,地基
Function interface.cpp 功能界面(给建筑上色,标明门牌号)
play.cpp 实现各部分功能(家具)
首先从创建好的Basic struct.cpp开始实现
想象一下
在我们登录类似于QQ音乐,网易音乐的时候刚开始是不是都有一个登录界面,然后显示音乐logo
这里我们可以分装两个函数
- //初始化界面
- Init_picture();
- //登录
- Lojin();
接着在CL-music.h实现函数声明(可以把所有需要引用的头文件都写入CL-music.h,其他文件只需要引用一下此头文件即可,例如#include"CL-music.h")
这两项都不需要返回值,所以写成void即可
- //初始化加载界面
- void Init_picture();
-
- //登录/注册
- void Lojin();
接下来在Basic struct.cpp里实现
初始化界面就不展示啦,大家可以根据自己的创意来设计logo~
登录如何实现呢?
想象一下
大家刚开始在使用这个软件的时候是不是都没账号,所以要有注册界面,然后再登录(已有账号可以直接跳过注册),账号通过两个数组来维护,一个是注册时输入的,一个是登录时确定的,通过比较即可确定是否输入正确,密码也是如此,账号或密码输入需要重新输入.
下面是登录代码:
- //登录
- void Lojin()
- {
-
- printf("|-----------------------------------------|\n");
- printf(" 请登录 \n");
- printf("|-----------------------------------------|\n");
- char account[10] = { 0 };
- char password[10] = { 0 };
- char account_1[10] = { 0 };
- char password_1[10] = { 0 };
- while (1)
- {
- printf("请输入账号(如果您还没有账号请输入\"*\"注册账号) :");
- scanf("%s", account_1);
- if (account_1[0] == '*')
- {
- printf("\n请输入您要注册的账号:");
- scanf("%s", account);
- printf("\n请输入您要注册的密码:");
- scanf("%s", password);
- printf("注册成功\n");
- }
- else
- {
- if (strcmp(account, account_1) == 0)
- {
- printf("请输入密码:");
- scanf("%s", &password_1);
- if (strcmp(password, password_1) == 0)
- {
- printf("登录成功\n");
- printf("正在为您加载...\n");
- Sleep(4000);
- system("cls");
- return;
- }
- else
- {
- printf("密码错误,请重新输入!\n");
- }
- }
- else
- {
- printf("账户错误,请重新输入!\n");
- }
- }
- }
-
- }
成功登录进入后,是不是因该转入功能界面了呢?
大家可以自己想象设计一下功能界面,比如热门歌曲选项,主页,搜索,等等
由于是基础篇,不需要考虑网络搭建,有些界面只需要一个形式即可
下面是功能界面代码实现:
- //加载功能界面--主界面
- int Func_picture()
- {
- printf("|-----------------------------------------|\n");
- printf("| 搜索(1): |\n");
- printf("|-----------------------------------------|\n");
- printf("| 热门(2) | 歌单(3) | 主页(4) |\n");
- printf("|-----------------------------------------|\n");
- printf("|-----------------------------------------|\n");
- printf("| |\n");
- printf("| |\n");
- printf("| 欢迎您来到 |\n");
- printf("| |\n");
- printf("| CL |\n");
- printf("| 海报 海报 |\n");
- printf("| musci |\n");
- printf("| |\n");
- printf("| ... |\n");
- printf("| |\n");
- printf("| 关闭程序(0) |\n");
- printf("| |\n");
- printf("|-----------------------------------------|\n");
- printf("请输入您要进行操作的序号:");
- int input = 0;
- scanf("%d", &input);
- system("cls");
- return input;
- }
以上各功能只需输入对应的序号即可执行操作,并通过system("cls");清除界面,实现界面跳转
补充一点,system函数来源于stdlib.h文件,登录界面的字符串比较函数来自string.h因此需要在头文件里包含
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
int Func_picture();这个功能界面为什么需要返回值呢?
接下来看主体框架
- int main()
- {
- //初始化加载界面
- Init_picture();
- int input1 = 0;
- Lojin();//登录
- do
- {
- switch (input1 = Func_picture())
- {
- case 1:
- break;
- case 2:
- break;
- case 3:
- break;
- case 4:
- break;
- case 5:
- break;
- case 0:
- printf("退出音乐\n");
- return 0;
- default:
- printf("输入非法,请重新输入!\n");
- break;
- }
- } while (input1);
- return 0;
- }
通过 Func_picture();的返回值来判断进入哪个case语句,并实现相应功能
既然是歌曲库,那么何来的库呢?
这里通过结构来创建歌曲库
结构体放入.h文件即可
- typedef struct Songinfo //歌曲相关信息
- {
- char Charname[NAME_MAX];
- char Charauthor[AUTHOR_MAX];
- char Charsinger[SINGER_MAX];
- char Charpub_date[DATE_MAX];
- }Songinfo;
这里的数量我用的#define定义的,可以方便后期维护和修改
- #define NAME_MAX 20
- #define AUTHOR_MAX 20
- #define SINGER_MAX 20
- #define DATE_MAX 11
可是我们总不可能写入一个歌曲信息就去手动创建一个
可以另外创建一个结构体,实现真正的歌曲库,里面包含一个结构体数组和一个计数器,每添加一个歌曲信息就将计数器加1,这样不仅实现了多信息的存储,也记录了信息的存储数量
- typedef struct Song_library //歌曲库
- {
- Songinfo arr[MUSIC_MAX];//添加进的歌曲
- int sz;//记录当前有效信息数
- }Song_library
创建歌曲库,命名为son
- //歌曲库
- Song_library son;
下一步,将结构体数据初始化,写入play.cpp
注意这里传址
- //初始化库存音乐
- void Init_library(Song_library* son)
- {
- son->sz = 0;
- memset(son->arr, 0, sizeof(son->arr));
- }
接下来就可以一步一步实现功能界面部分功能啦
既然是实现功能,不妨将这些功能分装成不同的函数,放在play.cpp中
注意:不要忘记将这些函数声明哦~
首先是
搜索歌曲功能
通过搜索歌曲名,展示出歌曲相应信息
如何实现呢
可以通过遍历数组,用字符串比较函数的方法来查询
下面是搜索代码实现
- //查找信息
- static int Find_song(const Song_library* son, char name[NAME_MAX])
- {
- assert(son != NULL);
- int i = 0;
- for (i = 0; i < son->sz; i++)
- {
- if (0 == strcmp(name, son->arr[i].Charname))
- {
- return i;
- }
- }
- return -1;
- }
注:assert(son != NULL);保证指针有效性
细心的小伙伴可能就发现了,
这里的static是干什么的?
const又是干什么的?
第一个问题:想象一下,如果在未来的公司里,每个文件分别实现不同功能,当代码量特别大的时候,在两个不同的文件下定义了两个同名的函数,但是要实现不同的功能,这时代码就会出现冗余的现象,为了避免,加上static关键字,将其修饰为静态变量,使其函数功能的实现只能在本文件里使用,就有效防止了代码的冗余.
第二个问题:搜索功能不需要去修改什么,const是为了防止Song_library* son被修改,这样加强了代码,未来实现一个大的工程,不是只有你一个人在完成这个项目,别人可能并不知道这个变量不能被修改!
第二个模块:
热门选项:
- //热门
- void Hot()
- {
-
- printf("|-----------------------------------------|\n");
- printf("| 热门 |\n");
- printf("|-----------------------------------------|\n");
- printf("| 今日榜单 |\n");
- printf("| |\n");
- printf("| 说好不哭 周杰伦 试听(1) |\n");
- printf("| |\n");
- printf("| 不为谁而作的歌 林俊杰 试听(2) |\n");
- printf("| |\n");
- printf("| 七里香 周杰伦 试听(3) |\n");
- printf("| |\n");
- printf("| ... |\n");
- printf("| 返回(0) |\n");
- printf("| |\n");
- printf("|-----------------------------------------|\n");
-
- int input = 0;
- printf("请选择:");
- scanf("%d", &input);
- switch (input)
- {
- case 1:
- system("cls");
- Music(input);
- break;
- case 2:
- system("cls");
- Music(input);
- break;
- case 3:
- system("cls");
- Music(input);
- break;
- case 0:
- system("cls");
- break;
- default:
- printf("输入非法,请重新输入!\n");
- break;
- }
- system("cls");
一个简易的播放界面,作为试听歌曲
第三个模块:
歌单界面:
- int Playlist_menu()
- {
- printf("|-----------------------------------------|\n");
- printf("| *** LC *** |\n");
- printf("| |-------------------------| |\n");
- printf("| | 添加歌曲(1) | |\n");
- printf("| |-------------------------| |\n");
- printf("| | 删除歌曲(2) | |\n");
- printf("| |-------------------------| |\n");
- printf("| | 查询歌单(3) | |\n");
- printf("| |-------------------------| |\n");
- printf("| | 修改歌曲(4) | |\n");
- printf("| |-------------------------| |\n");
- printf("| 返回(0) |\n");
- printf("|-----------------------------------------|\n");
- printf("请输入您要进行操作的序号:");
- int input = 0;
- scanf("%d", &input);
- system("cls");
- return input;
- }
这就是整个信息管理系统的核心部分,对歌曲信息进行增删查改功能
因此,我们因该在Basic struct.cpp这个基础框架中添加选项,如下代码:
- do
- {
- switch (input1 = Func_picture())
- {
- case 1:
- Search(&son);
- break;
- case 2:
- Hot();
- break;
- case 3:
- do
- {
- switch (input2 = Playlist_menu())//歌单
- {
- case 1:
- //增加歌曲
- Add_song(&son);
- Bubble_sort(&son);
- break;
- case 2:
- //删除歌曲
- Delete(&son);
- break;
- case 3:
- //查询歌曲
- Show_list(&son);
- break;
- case 4:
- //修改信息
- Modify(&son);
- break;
- case 0:
- break;
- default:
- printf("输入非法,请重新输入\n");
- break;
- }
- } while (input2);
- break;
- case 4:
- Home_page();
- break;
- case 5:
- Music(input1);
- break;
- case 0:
- printf("退出音乐\n");
- return 0;
- default:
- printf("输入非法,请重新输入!\n");
- break;
- }
- } while (input1);
先来看看添加歌曲
- //增加歌曲
- void Add_song(Song_library* son)
- {
- assert(son != NULL);
- if (son->sz == MUSIC_MAX)
- {
- printf("歌曲库已满,无法添加\n");
- }
- else
- {
- FILE* write = NULL;
- if (son->sz == 0)
- {
- write = fopen("歌曲库.txt", "w");
- if (write == NULL)
- {
- return;
- }
- }
- else
- {
- write = fopen("歌曲库.txt", "a");
- if (write == NULL)
- {
- return;
- }
- }
- printf("请输入歌曲名:");
- scanf("%s",&(son->arr[son->sz].Charname));
- printf("请输入作者:");
- scanf("%s", &(son->arr[son->sz].Charauthor));
- printf("请输入演唱者:");
- scanf("%s", &(son->arr[son->sz].Charsinger));
- printf("请输入发行时间:");
- scanf("%s", &(son->arr[son->sz].Charpub_date));
-
- //写入歌曲库
- fprintf(write, "%-10s\t", son->arr[son->sz].Charname);
- fprintf(write, "%-10s\t", son->arr[son->sz].Charauthor);
- fprintf(write, "%-10s\t", son->arr[son->sz].Charsinger);
- fprintf(write, "%-10s\t\n", son->arr[son->sz].Charpub_date);
- son->sz++;
- printf("添加成功!\n");
- fclose(write);
- write = NULL;
- }
- }
想象一下,进入此模块,首先因该想到该歌曲库是否已经被填满
接下来,要注意,不能只是简单的进行"w"操作,"w"为只写,我们每次往文件里添加歌曲的时候都会覆盖上一个创建的文件,如果没有文件,则会重新创建一个,所以这首先因该判断,如果歌曲库的歌曲个数为零,则可以通过"w"创建一个txt文件,倘若歌曲个数不为零,我们则可以通过"a"来追加
下一个功能:
删除歌曲
- //删除歌曲
- void Delete(Song_library* son)
- {
- assert(son != NULL);
- char name[NAME_MAX] = { 0 };
- printf("请输入要删除的歌曲的名字:");
- scanf("%s", name);
- int ret = Find_song(son, name);//查找
- if (ret == -1)
- {
- printf("对不起,没有您要找的歌曲信息!\n");
- }
- else
- {
- int i = 0; //从后向前覆盖
- for (i = ret; i < son-> sz - 1; i++)
- {
- son->arr[i] = son->arr[i + 1];
- }
- son->sz--;
- //重新写入文件
- FILE* write = fopen("歌曲库.txt", "w");
- if (write == NULL)
- {
- return;
- }
- for (i = 0; i < son->sz; i++)
- {
- fprintf(write, "%-10s\t", son->arr[i].Charname);
- fprintf(write, "%-10s\t", son->arr[i].Charauthor);
- fprintf(write, "%-10s\t", son->arr[i].Charsinger);
- fprintf(write, "%-10s\t\n", son->arr[i].Charpub_date);
- }
- printf("删除成功!\n");
- fclose(write);
- write = NULL;
- }
- system("pause");
- system("cls");
- }
输入的歌曲名通过数组存放,再用之前的查找函数Find_song进行搜索,没找到输出提示,找到了进行删除歌曲信息操作,如何删除呢,由于歌曲库未添加歌曲的地方被初始化成全0,所以通过从后向前覆盖的方式进行删除
下一个功能:
查找歌曲信息
- //歌单列表
- void Show_list(const Song_library* son)
- {
- assert(son != NULL);
- FILE* read = fopen("歌曲库.txt", "r");
- if (read == NULL)
- {
- return;
- }
- int i = 0;
- for (i = 0; i < son->sz; i++)
- {
- fscanf(read, "%s", &(son->arr[i].Charname));
- fscanf(read, "%s", &(son->arr[i].Charauthor));
- fscanf(read, "%s", &(son->arr[i].Charsinger));
- fscanf(read, "%s", &(son->arr[i].Charpub_date));
- }
- printf("|------------------------------------------------------------|\n");
- printf(" %-18s\t%-8s\t%-8s\t%-11s\n", "歌曲名", "作词人", "演唱者", "日期");
- for (i = 0; i < son->sz; i++)
- {
- if (i % 10 == 0 && i != 0)
- {
- system("pause");
- }
- printf(" %-18s\t%-8s\t%-8s\t%-11s\n",
- son->arr[i].Charname,
- son->arr[i].Charauthor,
- son->arr[i].Charsinger,
- son->arr[i].Charpub_date);
- }
- printf("|------------------------------------------------------------|\n");
- system("pause");
- system("cls");
- fclose(read);
- read = NULL;
- }
通过fscanf函数从歌曲库中获取信息,再通过printf进行打印,分屏输出,每次10条歌曲信息
注意:
- for (i = 0; i < son->sz; i++)
- {
- if (i % 10 == 0 && i != 0)
- {
- system("pause");
- }
这里的 i = 0 时进入 i % 10 = 0 依然成立,所以这里要注意并且的条件
下一个功能:
修改歌曲信息
- //修改
- void Modify(Song_library* son)
- {
- assert(son != NULL);
- char name[NAME_MAX] = { 0 };
- printf("请输入您要修改信息的歌曲名:");
- scanf("%s", name);
- int ret = Find_song(son, name);
- if (ret == -1)
- {
- printf("对不起,没有您要找的歌曲信息!\n");
- }
- else
- {
- FILE* modif = fopen("歌曲库.txt", "a");
- if (modif == NULL)
- {
- return;
- }
- printf("请输入歌曲名:");
- scanf("%s", &(son->arr[ret].Charname));
- printf("请输入作者:");
- scanf("%s", &(son->arr[ret].Charauthor));
- printf("请输入演唱者:");
- scanf("%s", &(son->arr[ret].Charsinger));
- printf("请输入发行时间:");
- scanf("%s", &(son->arr[ret].Charpub_date));
-
- //重新写入文件
- FILE* write = fopen("歌曲库.txt", "w");
- if (write == NULL)
- {
- return;
- }
- int i = 0;
- for (i = 0; i < son->sz; i++)
- {
- fprintf(write, "%-10s\t", son->arr[i].Charname);
- fprintf(write, "%-10s\t", son->arr[i].Charauthor);
- fprintf(write, "%-10s\t", son->arr[i].Charsinger);
- fprintf(write, "%-10s\t\n", son->arr[i].Charpub_date);
- }
- printf("修改成功!\n");
- fclose(write);
- write = NULL;
- }
- system("pause");
- system("cls");
- }
首先,通过查找歌曲函数先找到歌曲信息,然后对歌曲重新写入,覆盖之前的歌曲信息,最后修改成功并给予反馈
增删查改功能到这里就完成啦,为了让歌曲信息直观有序,继续创建一个模块
排序功能
- //排序
- void Bubble_sort(Song_library* son)
- {
- assert(son != NULL);
- char tmp_name[NAME_MAX] = { 0 };
- //写入结构体数组
- int i = 0;
- for (i = 0; i < son->sz - 1; i++)
- {
- int j = 0;
- for (j = 0; j < son->sz - i - 1; j++)
- {
- if (strcmp(son->arr[j].Charname, son->arr[j + 1].Charname) > 0)
- {
- //名字
- strcpy(tmp_name, son->arr[j].Charname);
- strcpy(son->arr[j].Charname, son->arr[j + 1].Charname);
- strcpy(son->arr[j + 1].Charname, tmp_name);
- //作者
- strcpy(tmp_name, son->arr[j].Charauthor);
- strcpy(son->arr[j].Charauthor, son->arr[j + 1].Charauthor);
- strcpy(son->arr[j + 1].Charauthor, tmp_name);
- //演唱者
- strcpy(tmp_name, son->arr[j].Charsinger);
- strcpy(son->arr[j].Charsinger, son->arr[j + 1].Charsinger);
- strcpy(son->arr[j + 1].Charsinger, tmp_name);
- //发行日期
- strcpy(tmp_name, son->arr[j].Charpub_date);
- strcpy(son->arr[j].Charpub_date, son->arr[j + 1].Charpub_date);
- strcpy(son->arr[j + 1].Charpub_date, tmp_name);
- }
- }
- }
- //重新写入文件
- FILE* write = fopen("歌曲库.txt", "w");
- if (write == NULL)
- {
- return;
- }
- for (i = 0; i < son->sz; i++)
- {
- fprintf(write, "%-10s\t", son->arr[i].Charname);
- fprintf(write, "%-10s\t", son->arr[i].Charauthor);
- fprintf(write, "%-10s\t", son->arr[i].Charsinger);
- fprintf(write, "%-10s\t\n", son->arr[i].Charpub_date);
- }
- printf("修改成功!\n");
- fclose(write);
- write = NULL;
-
- }
比较首元素ASCII码值的大小,由小到大进行排序,创建一个临时数组 char tmp_name[NAME_MAX] = { 0 }; 用来临时存放歌曲信息,方便交换,相当于你要交换一个油瓶和一个醋瓶中的液体一样,肯定是需要一个空瓶来临时存放的,这里的临时数组就相当于空瓶,最后重新写入文件,注意这里因该覆盖掉之前的文件内容;此功能可以放在增添歌曲功能的后面
如下代码:
- case 1:
- //增加歌曲
- Add_song(&son);
- Bubble_sort(&son);
- break;
- case 2:
最后一个模块
音乐播放
这里首先要保证是在cpp环境下进行,并且需要修改字符集,修改为使用多字节字符集,如下图
下一步,需要引用一些头文件
- //加载音乐需要的头文件
- #include<Windows.h>
- #include<mmsystem.h>//包含多媒体设备接口头文件
- #pragma comment (lib,"winmm.lib")//加载静态库
接着,将需要播放的音乐下载好,(注意:网易音乐不行,有加密),放在当前路径下
接着如下代码
- mciSendString("open 说好不哭.mp3 alias a", 0, 0, 0);// alias 是重命名
- mciSendString("play a", 0, 0, 0);//播放刚刚被命名的a音乐
如果需要暂停音乐,可以用如下代码
mciSendString("close a", 0, 0, 0);
模仿音乐播放功能,就有了如下代码
- //音乐播放
- void Music(const int ret)
- {
- int input = 0;
- if (ret == 1)
- {
- A:
- printf("|-----------------------------------------|\n");
- printf(" 正在为您播放“说好不哭”\n");
- mciSendString("close a", 0, 0, 0);
- mciSendString("close b", 0, 0, 0);
- mciSendString("close c", 0, 0, 0);
- mciSendString("open 说好不哭.mp3 alias a", 0, 0, 0);
- mciSendString("play a", 0, 0, 0);
- printf(" 播放(1) 关闭播放(2) 单曲循环(3)\n");
- printf(" 返回(0)\n");
- printf("|-----------------------------------------|\n");
- }
- else if (ret == 2)
- {
- B:
- printf("|-----------------------------------------|\n");
- printf(" 正在为您播放“不为谁而作的歌”\n");
- mciSendString("close a", 0, 0, 0);
- mciSendString("close b", 0, 0, 0);
- mciSendString("close c", 0, 0, 0);
- mciSendString("open 不为谁而作的歌.mp3 alias b", 0, 0, 0);
- mciSendString("play b", 0, 0, 0);
- printf(" 播放(1) 关闭播放(2) 单曲循环(3)\n");
- printf(" 返回(0)\n");
- printf("|-----------------------------------------|\n");
- }
- else if (ret == 3)
- {
- C:
- printf("|-----------------------------------------|\n");
- printf(" 正在为您播放“七里香”\n");
- mciSendString("close a", 0, 0, 0);
- mciSendString("close b", 0, 0, 0);
- mciSendString("close c", 0, 0, 0);
- mciSendString("open 七里香.mp3 alias c", 0, 0, 0);
- mciSendString("play c", 0, 0, 0);
- printf(" 播放(1) 关闭播放(2) 单曲循环(3)\n");
- printf(" 返回(0)\n");
- printf("|-----------------------------------------|\n");
- }
- while (1)
- {
- printf("请选择:");
- scanf("%d", &input);
- if (input == 1)
- {
- if (ret == 1)
- {
- system("cls");
- goto A;
- }
- else if (ret == 2)
- {
- system("cls");
- goto B;
- }
- else if (ret == 3)
- {
- system("cls");
- goto C;
- }
- }
- else if (input == 2)
- {
- if (ret == 1)
- mciSendString("close a", 0, 0, 0);
- else if(ret == 2)
- mciSendString("close b", 0, 0, 0);
- else if(ret == 3)
- mciSendString("close c", 0, 0, 0);
- }
- else if (input == 3)
- {
- if (ret == 1)
- mciSendString("repeat a", 0, 0, 0);
- else if (ret == 2)
- mciSendString("repeat b", 0, 0, 0);
- else if(ret == 3)
- mciSendString("repeat c", 0, 0, 0);
- }
- else if (input == 0)
- {
- break;
- }
- }
- system("cls");
- }
这样一个基本的框架就建立好啦
码字不易~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。