您的位置:首页 > 编程语言 > C语言/C++

用c语言来简单制作歌曲界面,让c不在枯燥~各位官爷快来围观吧

2020-04-02 07:56 1066 查看

文章目录

一、效果显示

二、操作流程

各位官爷,看到这么可爱的皮卡丘有没有心动呐,哈哈哈,赶快加入打包带走吧,不废话了,来,上干货~
想直接看原码的可去代码原文件查看哦
1、流程分析
a、先将歌词读取内当中;
用fopen打开歌词文件 FILE *fp = fopen(“简单爱.lrc”, “r”);
使用fseek将文件流指针 定位到文件尾部 获得文件总大小;
使用rewind 复位文件流置针
根据文件总大小 从堆区 申请 合适的空间 char *arr ;
使用fread 读取文件数据 到内存中 arr;
关闭文件;
b、将提取出的内存数据 按行"\r\n"切割 存入 字符指针数组 char *buf[128]={NULL};(window下换行符由\r\n组成呦)
提取结束后记得保存一下行数,后期用的到呐;
c、逐行分析,分别提取对应的时间和歌词内容
[1]、为降低难度,咱们将歌词分开,先分析前四行


原数据:
[ti:简单爱]
[ar:周杰伦]
[al:范特西]
[by:大脸猫]
那如何实现上述效果呐,各位官爷请看我的表演:

char tmp[4][128];
int i=0;
for(i=0;i<4;i++)
{
sscanf(buf[i],"%*[^:]:%[^]]",tmp[i]);
}
clear_screen();
cusor_moveto(10,2);
printf("歌名:%s\n",tmp[0]);
cusor_moveto(10,3);
printf("歌手:%s\n",tmp[1]);
cusor_moveto(10,4);
printf("专辑:%s\n",tmp[2]);
cusor_moveto(10,5);
printf("制作:%s\n",tmp[3]);

hhh,一顿操作猛如虎,一看战绩0-5 !
[2]、逐行分析剩下的行 将时间+歌词 一一对应 插入链表
先设计一个简单的链表:

typedef struct lrc{
//数据域
int time;
char lrc[128];
//指针域
struct lrc *next;
}LRC;

是心动吗~哈哈,皮一下
接下来时间和歌词插入

LRC tmp;
int i=4;

for(i=4;i<num;i++)
{
char *str_lrc=buf[i];//获取歌词

while(*str_lrc=='[')
str_lrc+=10;
char *str_time=buf[i];//获取时间
while(*str_time=='[')
{
int m=0,s=0;
sscanf(str_time,"[%d:%d:%*d]",&m,&s);
int time =m*60+s;//将时间转为数值,方便后面比较
tmp.time=time;
strcpy(tmp.lrc,str_lrc);
head=insert_link(head,tmp);//创建链表
str_time+=10;
}

}

完成一半喽,此处建议打印一下链表,修改一下出现的buf,整装待发,咱们继续~
d、模拟时钟,让时间走起来吧
给各位官爷一串模拟时钟代码,有时间和想法可以研究一下呐,下面用到的几乎一样

#include <stdio.h>
int main(int argc, char *argv[])
{
int i=0;
while(1)
{
printf("\r%02d:%02d",i/60,i%60);
fflush(stdout);
//到链表查询
LRC *ret = search_link(head,i);
if(ret != NULL)
{
printf("%s\n", ret->lrc);
}
sleep(1);//休眠1s
i++;
}
return 0;
}

e、让歌词滚屏(光标定位)
f、给歌词添加颜色。//皮肤丝滑有活力~哈哈哈
g、启动音乐
h、释放申请的动态空间,谁污染谁治理原理,咳咳,做一个负责的好公民。
为方便各位官爷查看,我把这几部分代码直接放到总代码区,下面有请~

代码原文件

main.c文件

#include<stdio.h>
#include "start_mplayer.h"
#include"fun.h"
#include<string.h>
int main(int argc, char const *argv[])
{
char *arr=NULL;
//将歌词内容提取到内存中
FILE *fp=fopen("简单爱.lrc","r");
arr=read_file(fp);
char *buf[128]={arr};
//歌词切割
int i=0;
while((buf[i++]=strtok(buf[i],"\r\n")));
int num=i-1;
//打印前四行
//char *lrc=NULL;
printf_link1(buf);
//打印剩余歌词
LRC *head=NULL;
head=printf_link2(head, buf,num);
//printf_link(head);
//模拟时钟,歌词的滚屏,反显,启动音乐
clock_lnk(head);
free_link(head);
return 0;}

fun.c文件

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include"fun.h"
#include "start_mplayer.h"
#include"console.h"

char *read_file(FILE *fp)//将歌词读取到内存
{
char *file_data=NULL;
if(fp==NULL)
{
perror("fopen");
return NULL;
}
//判断文件大小
fseek(fp,0,2);
long file_len=ftell(fp);
rewind(fp);
//申请动态空间
file_data=(char*)calloc(1,file_len+1);
if(file_data==NULL)
{
perror("calloc");
return NULL;
}
fread(file_data,file_len ,1,fp);
fclose(fp);
return file_data;
}
void printf_link1(char *buf[])//提取前四行歌词
{
char tmp[4][128];
int i=0;
for(i=0;i<4;i++)
{
sscanf(buf[i],"%*[^:]:%[^]]",tmp[i]);
}
clear_screen();
cusor_moveto(10,2);

printf("歌名:%s\n",tmp[0]);
cusor_moveto(10,3);
printf("歌手:%s\n",tmp[1]);
cusor_moveto(10,4);
printf("专辑:%s\n",tmp[2]);
cusor_moveto(10,5);
printf("制作:%s\n",tmp[3]);

return ;
}
LRC *insert_link(LRC *head,LRC tmp)//有序插入链表
{
LRC *pi=NULL;
pi=(LRC*)calloc(1,sizeof(LRC));
if(pi==NULL)
{
perror("calloc");
return NULL;
}
*pi=tmp;
pi->next=NULL;
if(head==NULL)
{
head=pi;
return head;
}
else
{
LRC *pd=head,*pf=head;
while(pd->time<pi->time&&pd->next!=NULL)
{
pf=pd;
pd=pd->next;
}
if(pd->time>pi->time)
{
if(pd==head)
{
pi->next=head;
head=pi;
return head;
}
else
{
pf->next=pi;
pi->next=pd;
return head;
}
}
else
{
pd->next=pi;
return head;
}
}
}
LRC *printf_link2(LRC *head,char *buf[],int num)//提取其他行歌词
{
LRC tmp;
int i=4;
for(i=4;i<num;i++)
{
char *str_lrc=buf[i];
while(*str_lrc=='[')
str_lrc+=10;
char *str_time=buf[i];
while(*str_time=='[')
{
int m=0,s=0;
sscanf(str_time,"[%d:%d:%*d]",&m,&s);
int time =m*60+s;
tmp.time=time;
strcpy(tmp.lrc,str_lrc);
head=insert_link(head,tmp);//将提取出的内容插入到链表
str_time+=10;
}
}
return head;
}
#if 0
void printf_link(LRC *head)//打印链表
{
if(head==NULL)
{
printf("link not find\n");
return ;
}
else
{
LRC *pd=head;
while(pd!=NULL)
{
printf("%d %s\n",pd->time,pd->lrc);
pd=pd->next;
}
}
}
#endif
void clock_lnk(LRC *head)
{
mplayer_play("简单爱.mp3");//启动音乐
int i=0;
char buf1[128]="";
char buf2[128]="";
char buf3[128]="";
char buf4[128]="";
while(1)
{
//打印时间
cusor_moveto(8,6);
printf("%02d:%02d ",i/60,i%60);
cusor_moveto(19,6);
printf(" 04:30");
//打印皮卡丘字符图片
set_fg_color(COLOR_YELLOW);
cusor_moveto(40,6);
printf("     `;-.          _--\n");
cusor_moveto(40,7);
printf("       `.`\\_...._/`.-\"`\n");
cusor_moveto(40,8);
printf("         \\        /      ,\n");
cusor_moveto(40,9);
printf("         /()   () \\    .' `-._\n");
cusor_moveto(40,10);
printf("        |)  .    ()\\  /   _.'\n");
cusor_moveto(40,11);
printf("        \\  -'-     ,; '. <\n");
cusor_moveto(40,12);
printf("         ;.__     ,;|   > \n");
cusor_moveto(40,13);
printf("        / ,    / ,  |.-'.-'\n");
cusor_moveto(40,14);
printf("       (_/    (_/ ,;|.<`\n");
cusor_moveto(40,15);
printf("         \\    ,     ;-`\n");
cusor_moveto(40,16);
printf("          >   \\    /\n");
cusor_moveto(40,17);
printf("         (_,-'`> .'\n");
cusor_moveto(40,18);
printf("              (_,' \n");
set_fg_color(COLOR_BLACK);
fflush(stdout);
#if 1

LRC *ret=search_link(head,i);//插入链表
if(ret!=NULL)
{
//歌词滚屏
strcpy(buf1,buf2);
strcpy(buf2,buf3);
strcpy(buf3,buf4);
strcpy(buf4,ret->lrc);
cusor_moveto(7,9);
printf("%s                   \n", buf1);
cusor_moveto(7,10);
printf("%s                   \n", buf2);
cusor_moveto(7,11);
printf("%s                   \n", buf3);
cusor_moveto(7,12);
set_fg_color(COLOR_RED);
printf("%s                   \n", buf4);
set_fg_color(COLOR_BLACK);

}
#endif
sleep(1);
i++;
}
return ;
}
LRC *search_link(LRC *head,int i)//链表查找
{
if(head==NULL)
{
printf("link not fine\n");
return NULL;
}
else
{
LRC *pd=head;
while(pd->time!=i && pd->next!=NULL)
{
pd=pd->next;
}
if (pd->time == i )
{
return pd;
}
else
{
return NULL;
}
}
}
void free_link(LRC *head)//链表释放
{
if(head==NULL)
{
printf("link not find\n");
}
else
{
LRC *pb=head;
while(pb!=NULL)
{
head=pb->next;
free(pb);
pb=head;
}
}
return ;
}

fun.h 文件
//头文件,用以函数的声明

#ifndef __FUN_H__
#define __FUN_H__
typedef struct lrc
{
int time;
char lrc[128];
struct lrc *next;
}LRC;
extern char *read_file(FILE *fp);
extern void printf_link1(char *buf[]);
extern LRC *insert_link(LRC *head,LRC tmp);
extern LRC *printf_link2(LRC *head,char *buf[],int num);
extern void printf_link(LRC *head);
extern void clock_lnk(LRC *head);
extern LRC *search_link(LRC *head,int i);
extern void free_link(LRC *head);
extern void printf_link3();
#endif

由于我的是在虚拟机内写的,故还需要编译程序
makefile 文件

exec=main
cc=gcc
obj=main.o fun.o start_mplayer.o console.c   #你要修改的地方
cflags=-Wall -g
$(exec):$(obj)
$(cc) $^ -o $@ $(cflags)
%.o:%.c
$(cc) -c $< -o $@ $(cflags)
clean:
rm $(exec) *.o

启动mplayer播放器 程序
start_myplayer.c文件

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
//启动mplayer播放器
//参数song_path 为歌曲的路径
void mplayer_play(char * song_path)
{
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork");
}
else if(pid==0)
{
close(1);
close(2);
execlp("mplayer","mplayer","-slave","-quiet",song_path,NULL);
exit(0);
}
else
;
}

光标定位的程序及头文件
console.c 文件

#include <stdio.h>
#include <stdlib.h>
#include "console.h"
void cusor_moveto(int x, int y)
{
// ESC[y;xH
printf("\033[%d;%dH",y,x);
fflush(stdout);}
//保存光标位置
void cusor_get_pos(void)
{
// ESC[s
printf("\033[s");
fflush(stdout);
}
//恢复光标位置
void cusor_set_pos(void)
{
// ESC[u
printf("\033[u");
fflush(stdout);
}
void cusor_hide(void)
{
printf("\033[?25l");
}
//清屏
void clear_screen(void)
{
// ESC[2J
printf("\033[2J");
fflush(stdout);
}
/*COLOR_RED              红
COLOR_BLACK            黑
COLOR_GREEN            绿
COLOR_BLUE             蓝
COLOR_YELLOW           黄
COLOR_WHITE            白
COLOR_CYAN             青
COLOR_MAGENTA          洋红
*/
//设置前景颜色
void set_fg_color(int color)
{
// ESC[#m
printf("\033[%dm",color);
fflush(stdout);
}
//设置背景颜色
void set_bg_color(int color)
{// ESC[#m
printf("\033[%dm",(color+10));
fflush(stdout);
}
}

console.h 头文件

#ifndef  _CONSOLE_H_
#define  _CONSOLE_H_
#define     COLOR_RED              31
#define     COLOR_BLACK            30
#define     COLOR_GREEN            32
#define     COLOR_BLUE             34
#define     COLOR_YELLOW           33
#define     COLOR_WHITE            37
#define     COLOR_CYAN             36
#define     COLOR_MAGENTA          35
/*
COLOR_RED              红
COLOR_BLACK            黑
COLOR_GREEN            绿
COLOR_BLUE             蓝
COLOR_YELLOW           黄
COLOR_WHITE            白
COLOR_CYAN             青
COLOR_MAGENTA          洋红
*/
extern void cusor_moveto(int x, int y);//光标跳转到 y行 x列
extern void cusor_get_pos(void);//保存光标位置
extern void cusor_hide(void);
extern void cusor_set_pos(void);//恢复光标位置
extern void clear_screen(void);//清屏
extern void set_fg_color(int color);//设置字体前景色
extern void set_bg_color(int color);//设置字体背景色

#endif //_CONSOLE_H_

歌词文件
简单爱.lrc

[ti:简单爱]
[ar:周杰伦]
[al:范特西]
[by:大脸猫]
[00:04.41]周杰伦 Chow, Jay Jou
[00:10.56]简单爱(台视Star blue蓝星主题曲)
[00:18.48]词:徐若瑄 曲:周杰伦
[00:26.44]说不上为什么 我变得很主动
[00:31.37]若爱上一个人 什么都会值得去做
[02:04.94][00:36.09]我想大声宣布 对你依依不舍
[02:09.97][00:41.26]连隔壁邻居都猜到我现在的感受
[02:14.94][00:46.17]河边的风 在吹着头发 飘动
[02:19.80][00:51.25]牵着你的手 一阵莫名感动
[02:24.61][00:55.86]我想带你 回我的外婆家
[02:28.32][00:59.79]一起看着日落 一直到我们都睡着
[03:34.64][02:34.71][01:05.83]我想就这样牵着你的手不放开
[03:39.68][02:39.34][01:10.71]爱能不能够永远单纯没有悲哀
[03:44.27][02:43.90][01:15.44]我想 带你骑单车
[03:46.74][02:46.60][01:18.05]我想 和你看棒球
[03:49.77][02:49.58][01:20.71]想这样没担忧
[03:51.61][02:51.59][01:22.69]唱着歌 一直走☆
[03:54.38][02:54.35][01:25.57]我想就这样牵着你的手不放开
[03:59.19][02:59.01][01:30.41]爱可不可以简简单单没有伤害
[04:03.77][03:03.73][01:35.04]你 靠着我的肩膀
[04:06.33][03:06.26][01:37.49]你 在我胸口睡着
[04:09.13][03:09.34][01:40.57]像这样的生活
[04:11.36][03:11.26][01:42.66]我爱你 你爱我★
[03:13.76][01:44.97]想~~~ 简!简!单!单! 爱~~~
[03:23.61][01:54.30]想~~~ 简!简!单!单! 爱~~~

内容有点多,各位官爷选择查看哦
音乐文件我就不上传了,可根据需要自行去下载~

  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
果果酱_ 发布了6 篇原创文章 · 获赞 6 · 访问量 277 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: