歌词解析器代码详情Word文件下载.docx
《歌词解析器代码详情Word文件下载.docx》由会员分享,可在线阅读,更多相关《歌词解析器代码详情Word文件下载.docx(18页珍藏版)》请在冰豆网上搜索。
//存储歌曲的信息
/*************************************************************************
*函数功能:
歌词解析器整体的控制
*参数:
无
*返回值:
**************************************************************************/
intmain()
{
intfile_length=0;
//存储lrc文件内容的大小
char*file_buf=NULL;
//指向malloc的空间,其中存放着lrc文件中所有的内容
char*lrc_text[200]={NULL};
//指向,按照\r\n切割后的一行歌词
intlrc_line=0;
//lrc文件中的行数
inti=0;
LRC*head=NULL,*p;
//head记录歌词链表头
ints_time=0;
//模拟时间变量
file_buf=read_src_file(&
file_length,"
./lrc/兰亭序.lrc"
);
//从lrc文件中读出歌词内容
lrc_line=strtok_lrc_buf(lrc_text,file_buf);
//按行切割歌曲内容
lrc_head_resolve(song_msg,lrc_text);
//切割歌曲信息
print_song_message(song_msg);
//显示歌曲信息
head=lrc_resolve(lrc_line,lrc_text);
//保存时间:
歌词到链表中
//print(head);
//遍历链表,用来测试链表
//ShellExecute(NULL,NULL,"
TTPlayer.exe"
"
兰亭序.mp3"
NULL,1);
//开启千千静听
m_time.second=0;
m_time.minute=0;
while
(1)//每秒钟到链表里面去找相应的歌词,如果找到那么就显示
{
/*
*1.定位光标,显示歌词
*/
GoToXY(20,5);
printf("
%02d:
%02d"
m_time.minute,m_time.second);
p=search(head,s_time);
//到连表里查找当前时间点对应的歌词,如果有那么就返回歌词的首地址
if(p!
=NULL)
{
lrc_show(p);
}
*1.运行模拟时间
Sleep(500);
//延时,注意在windows平台Sleep
(1);
延时1毫秒
s_time=s_time+1;
++m_time.second;
if(m_time.second==60)
m_time.second=0;
++m_time.minute;
if(m_time.minute==60)
m_time.minute=0;
}
return0;
}
/*****************************************************************************/
lrc.h
#ifndef__LRC_H__
#define__LRC_H__
typedefstructlrc{
inttime;
charlrc_buf[200];
structlrc*next;
}LRC;
externchar*read_src_file(int*file_length,char*src_file_name);
externintstrtok_lrc_buf(char*lrc_text[],char*file_buf);
externvoidlrc_head_resolve(char*lrc_head_info[],char*lrc_text[]);
externvoidprint_song_message(char*msg_info[]);
externLRC*lrc_resolve(intlrc_line,char*lrc_text[]);
externLRC*InsertList(LRC*head,LRC*lrc_link);
externvoidprint(LRC*head);
externLRC*search(LRC*head,inttime);
externvoidlrc_show(LRC*pi);
externvoidprint_lrc(char*lrc);
#endif
lrc.c
读出文件内容
*file_length:
整型指针,此地址中保存文件字节数。
*src_file_name:
文件名字,从此文件中读取内容。
读出字符串的首地址
char*read_src_file(int*file_length,char*src_file_name)
unsignedlongintFILE_SIZE=0;
char*src_file_text=NULL;
FILE*fp=NULL;
fp=fopen(src_file_name,"
rb"
if(fp==NULL)
open%sfaild\n"
src_file_name);
return0;
fseek(fp,0,SEEK_END);
FILE_SIZE=ftell(fp);
*file_length=FILE_SIZE;
//返回歌词文件内容的大小
rewind(fp);
//一定要把“文件指针”移动到文件开始处
src_file_text=(char*)malloc(FILE_SIZE);
if(fread(src_file_text,FILE_SIZE,1,fp)==0)
readfromsrc_filefaild\n"
returnNULL;
fclose(fp);
//关闭文件
returnsrc_file_text;
/************************************************************************
切割歌词数组
*lrc_text指针数组,让其指针指向切出来的内容
*file_buf歌词内容数组
*返回值:
切割出来的字符串的个数
*************************************************************************/
intstrtok_lrc_buf(char*lrc_text[],char*file_buf)
lrc_text[i++]=strtok(file_buf,"
\r\n"
while((lrc_text[i++]=strtok(NULL,"
))!
=NULL);
returni;
/**************************************************************************
解析lrc前四行,歌曲的信息如歌手、专辑等。
。
*lrc_text指针数组lrc中的前四行
*song_msg指针数组用来指向处理好的歌曲信息
voidlrc_head_resolve(char*song_msg[],char*lrc_text[])
char*message[]={"
[ti"
[ar"
[al"
[by"
};
char*temp;
for(i=0;
i<
4;
i++)//循环四次找到四个头信息的开始
if(strncmp(lrc_text[i],message[i],3)==0)
temp=lrc_text[i];
/*
[ti:
兰亭序]
[ar:
李维]
[al:
情已逝DSD]
[by:
朱古力]
*/
while(*temp!
='
]'
)//找到头信息],然后改为'
\0'
{
temp++;
}
*temp='
;
song_msg[i]=lrc_text[i]+4;
//跳过ti:
三个字母,保存歌词信息;
打印歌曲信息
*song_msg歌曲信息指针数组指向歌曲头信息内容
*注意点:
voidprint_song_message(char*song_msg[])
char*name[4]={"
歌名:
"
歌手:
专辑:
制作:
i++)
%s%s\n"
name[i],song_msg[i]);
解析歌曲信息
*lrc_text指向歌词内容(以行的方式存储)的指针数组
*lrc_line歌词的行数
LRC*lrc_resolve(intlrc_line,char*lrc_text[])
LRC*head=NULL,*lrc_link;
inti=0,j=0,CurOffset;
char*LrcFile;
intCurTime[10];
//用来暂时记录歌词中的时间,单位为:
毫秒
intnum=0;
//用来暂时记录本句歌词有多少个时间与其对应
for(i=4;
lrc_line-1;
LrcFile=lrc_text[i];
//一行的歌词:
[00:
25.21]兰亭临帖行书如行云流水
CurOffset=1;
//标识时间位置的偏移量
if((LrcFile[CurOffset])>
='
0'
&
&
(LrcFile[CurOffset])<
9'
)//检测到歌词时间标签
char*lrc;
//用来暂时记录时间后面的歌词
num=0;
//解析每句歌词时,要把本句歌词对应的时间数初始化为0
//[00:
//[02:
04.94][00:
36.09]我想大声宣布对你依依不舍
while(LrcFile[CurOffset]>
LrcFile[CurOffset]<
)//取出这句歌词所有时间标签
CurTime[num++]=(((LrcFile[CurOffset]-'
)*10+(LrcFile[CurOffset+1]-'
))*60+((LrcFile[CurOffset+3]-'
)*10+LrcFile[CurOffset+4]-'
))*1000+\
(LrcFile[CurOffset+6]-'
)*100+(LrcFile[CurOffset+7]-'
)*10;
CurOffset=CurOffset+10;
//解析一句歌词在不同时间出现的情况时,需要把指针往后偏移10
//lrc=&
LrcFile[CurOffset-1];
//得到这句歌词首地址“我想大声宣布对你依依不舍”
lrc=LrcFile+10;
//根据本句歌词对应的时间个数,把歌词与时间保存到链表中
for(j=0;
j<
num;
j++)
lrc_link=(LRC*)malloc(sizeof(LRC));
//申请节点,存放解析出歌词与时间
lrc_link->
time=CurTime[j];
strcpy(lrc_link->
lrc_buf,lrc);
//将解析出的时间、歌词内容插入到单向链表并进行排序
head=InsertList(head,lrc_link);
returnhead;
往链表中插入歌词节点。
*head链表的头节点地址。
*lrc_link将要插入的节点首地址。
插入之后链表的头节点的地址
LRC*InsertList(LRC*head,LRC*lrc_link)
LRC*pb,*pf;
if(head==NULL)//如果原先链表为空head为pi
lrc_link->
next=NULL;
head=lrc_link;
returnhead;
pb=pf=head;
while((lrc_link->
time>
pb->
time)&
(pb->
next!
=NULL))//查找比pi->
num更大的节点
{
pf=pb;
pb=pb->
next;
if(lrc_link->
time<
=pb->
time)//如果上面的while循环式因为找到lrc_link->
time而推出的
if(pb==head)//如果找到的节点为第一个,则pi应该放到head的前面
lrc_link->
next=head;
//把pi放到链表里
head=lrc_link;
//把pi变成头节点
else//如果是pb普通节点的话在pf和pb之间插入pi
pf->
next=lrc_link;
//pb的前一个节点的指针域指向pi
next=pb;
//pi的指针域指向pb
else//如果链表中的节点的time都比pi->
time小,则插到链表尾端
pb->
//pb的指针域指向pi
//pi的下一个为NULL即pi为链表的尾
从歌词链表中查找时间为time的结点
*time要查询的时间
时间为time的结点的首地址
LRC*search(LRC*head,inttime)//在一个已建立的链表中查找某一节点
LRC*p,*pi=NULL;
p=head;
//导入已存在链表的头文件
while((p->
time/1000)!
=time&
p->
=NULL)//判断是否找到要找的数据,判断是否到链表尾。
p=p->
//不是要找的结点后移一步
if((p->
time/1000)==time)
pi=p;
//找到数据则返回相应指针地址
elseif(p->
next==NULL)//到链表尾则打印数据未找到
pi=NULL;
returnpi;
遍历链表
voidprint(LRC*head)
printf("
\n链表所有信息如下:
\n"
TIME\t\tLRC_BUF\n"
while(head!
%d\t\t%s\n"
head->
time,head->
lrc_buf);
head=head->
{//表示日期时间的数据结构
externTIMEm_time;
externchar*song_msg[4];
charlrc_buf[6][200]={"
歌词显示
*pi新查找到得结点
voidlrc_show(LRC*pi)
staticintx=0,y=11;
staticintlrc_num=0;
if(lrc_num<
6)
*1:
前6行歌词显示的方式
*2:
strcpy(lrc_buf[lrc_num],pi->
//lrc_num=0、1、2、3、4、5
if(lrc_num>
0)
GoToXY(x,y-1);
printf("
%s\n"
lrc_buf[lrc_num-1]);
//只覆盖上1次显示绿颜色的那一行歌词
GoToXY(x,y);
print_lrc(pi->
//当