歌词解析
項目步驟:
打開歌曲文件(rb方式) 測文件大小 申請空間,讀入文件內(nèi)容。 用strtok 以"\r\n"(2進(jìn)制文件行尾是以"\r\n"結(jié))切割字符串,用指針數(shù)組去指向切出來的字符串。 處理前四行 處理后面的帶時間的行,創(chuàng)建鏈表。 創(chuàng)建模擬時鐘,搜索鏈表中的結(jié)點,找到了打印歌詞。
注意事項:
1、本程序完成功能:完成lrc格式歌詞的文件讀取、解析、鏈表創(chuàng)建等,同時在屏幕上將解析出的歌詞進(jìn)行實時顯示。
2、延時函數(shù)需要包含? #include<unistd.h>sleep(1);//延時1s或usleep(1000*1000);//延時1s或者用time_delay.c 中自己封裝的函數(shù)3、鏈表中每個節(jié)點的數(shù)據(jù)結(jié)構(gòu)類型
typedef struct lrc{int time;//歌詞時間點char lrc_buf[200];//歌詞內(nèi)容int lrc_cur_num;//第幾句歌詞struct lrc *next;//指向鏈表中的下一個節(jié)點}LRC;
1、本程序完成功能:完成lrc格式歌詞的文件讀取、解析、鏈表創(chuàng)建等,同時在屏幕上將解析出的歌詞進(jìn)行實時顯示。
2、延時函數(shù)需要包含? #include<unistd.h>sleep(1);//延時1s或usleep(1000*1000);//延時1s或者用time_delay.c 中自己封裝的函數(shù)3、鏈表中每個節(jié)點的數(shù)據(jù)結(jié)構(gòu)類型
typedef struct lrc{int time;//歌詞時間點char lrc_buf[200];//歌詞內(nèi)容int lrc_cur_num;//第幾句歌詞struct lrc *next;//指向鏈表中的下一個節(jié)點}LRC;
Windows下實現(xiàn):
clock.h#include <Windows.h> #ifndef _CONSOLE_H_ #define _CONSOLE_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #endif typedef struct clock {int h;//時int m;//分int s;// 秒 }CLOCK; void update(CLOCK *m_clock) {m_clock->s++;if(m_clock->s==60){m_clock->m++;m_clock->s=0;}if(m_clock->m==60){m_clock->h++;m_clock->m=0;}if(m_clock->h==24){m_clock->h=0;} } void Show(CLOCK *m_clock) {Sleep(1000);printf("\r%2d:%2d:%2d",m_clock->h,m_clock->m,m_clock->s);fflush(stdout);update(m_clock);} console.h#ifndef _CONSOLE_H_ #define _CONSOLE_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #endif#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 藍(lán) COLOR_YELLOW 黃 COLOR_WHITE 白 COLOR_CYAN 青 COLOR_MAGENTA 洋紅 */extern void cusor_moveto(int x, int y);//光標(biāo)跳轉(zhuǎn)到 y行 x列 extern void cusor_get_pos(void);//保存光標(biāo)位置 extern void cusor_hide(void); extern void cusor_set_pos(void);//恢復(fù)光標(biāo)位置 extern void clear_screen(void);//清屏 extern void set_fg_color(int color);//設(shè)置字體前景色 extern void set_bg_color(int color);//設(shè)置字體背景色void cusor_moveto(int x, int y) {// ESC[y;xHprintf("\033[%d;%dH",y,x);fflush(stdout); } //保存光標(biāo)位置 void cusor_get_pos(void) {// ESC[sprintf("\033[s");fflush(stdout); } //恢復(fù)光標(biāo)位置 void cusor_set_pos(void) {// ESC[uprintf("\033[u");fflush(stdout); } void cusor_hide(void) {printf("\033[?25l"); } //清屏 void clear_screen(void) {// ESC[2Jprintf("\033[2J");fflush(stdout); }/* COLOR_RED 紅 COLOR_BLACK 黑 COLOR_GREEN 綠 COLOR_BLUE 藍(lán) COLOR_YELLOW 黃 COLOR_WHITE 白 COLOR_CYAN 青 COLOR_MAGENTA 洋紅 */ //設(shè)置前景顏色 void set_fg_color(int color) {// ESC[#mprintf("\033[%dm",color);fflush(stdout); }//設(shè)置背景顏色 void set_bg_color(int color) {// ESC[#mprintf("\033[%dm",(color+10));fflush(stdout); }music.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "clock.h" #include "console.h" #define _CONSOLE_H_ typedef struct lrc {int m_time;char lrc_buf[200];struct lrc *front;struct lrc *next; }LRC; char *lrc_buf1; int bh=0; int msg_deal(char *msg_src,char *msg_done[],char *str) {int i=0;msg_done[i]=strtok(msg_src,str);while(msg_done[i]!=NULL){i++;msg_done[i]=strtok(NULL,str);}return i; } void link_insert_num(LRC **p_head,LRC *p_new) {LRC *pb,*pf;pb=*p_head;if(*p_head == NULL)//鏈表為空,新來的節(jié)點就是頭節(jié)點{*p_head=p_new;p_new->front=NULL;p_new->next=NULL;return ;}while((p_new->m_time >= pb->m_time) && (pb->next!=NULL) ){pb=pb->next ;}if(p_new->m_time < pb->m_time)//找到了一個pb的num比新來的節(jié)點的num大,插在pb前邊{if(pb==*p_head)//找到的節(jié)點是頭節(jié)點,插在頭節(jié)點的前邊{p_new->next=*p_head;(*p_head)->front=p_new;p_new->front=NULL;*p_head=p_new;}else{pf=pb->front;//pf指向 找到節(jié)點的前一個節(jié)點p_new->next=pb;p_new->front=pf;pf->next=p_new;pb->front=p_new;}}else//所有pb指向節(jié)點的num都比p_new指向的節(jié)點的num小,插在最后{pb->next=p_new;p_new->front=pb;p_new->next=NULL;}} LRC *link_search_num(LRC *head,int num) {LRC *p_mov=head;while(p_mov!=NULL){if(p_mov->m_time == num){bh++;return p_mov;}else{p_mov=p_mov->next;}}return NULL; } int ReadLink(LRC **head) {int i=0;LRC *phead=*head;if(phead==NULL)return 0;while(phead->next!=NULL){phead=phead->next;i=i+1;}return i; } //void get_file_name(char * src_file_name) //{ // printf("請輸入你要解析的文件名稱(30個字符)"); // scanf("%s",src_file_name); //} void read_src_file(unsigned long int *file_length); int main() {//要為字符串開辟空間的大小unsigned long int file_length;//切割字符串的一些變量int time_buf[5];int i=0,j,k,temp=0;char *str;int min,sec;LRC *head=NULL,*p_new,*pb;char *q[100];int len=0;int count;//時鐘的一些變量初始化CLOCK m_clock;m_clock.h=0;m_clock.m=0;m_clock.s=0;//---------------------------------------//get_file_name(src_file_name);read_src_file(&file_length);//----------------------------------------len=msg_deal(lrc_buf1,q,"\r\n");for(k=4;k<len;k++)//處理第5行到最后一行{str=q[k];i=0;while(*str=='['){sscanf(str,"[%2d:%2d",&min,&sec);time_buf[i]=60*min+sec;i++;str=str+10; }for(j=0;j<i;j++){//申請節(jié)點p_new=(LRC *)malloc(sizeof(LRC));//節(jié)點的時間成員賦值p_new->m_time=time_buf[j];//節(jié)點的歌詞成員賦值strcpy(p_new->lrc_buf,str);//插入鏈表link_insert_num(&head,p_new);}}count=ReadLink(&head);while(1){int i=0;Show(&m_clock);set_fg_color(COLOR_BLUE);//Sleep(1000);temp++;//按temp查找節(jié)點 調(diào)link_search_time pb=link_search_num(head,temp);//找到打印if(pb!=NULL) { if(bh==count+1){cusor_moveto(17, ++i);printf("%s\n",pb->front->front->front->front->lrc_buf);printf("%s\n",pb->front->front->front->lrc_buf);printf("%s\n",pb->front->front->lrc_buf);printf("%s\n",pb->front->lrc_buf);set_fg_color(COLOR_RED);printf("%s\n",pb->lrc_buf); set_fg_color(COLOR_BLUE);}else if(bh==count){cusor_moveto(17, ++i);printf("%s\n",pb->front->front->front->lrc_buf);printf("%s\n",pb->front->front->lrc_buf);printf("%s\n",pb->front->lrc_buf);set_fg_color(COLOR_RED);printf("%s\n",pb->lrc_buf);set_fg_color(COLOR_BLUE);printf("%s\n",pb->next->lrc_buf);}else if(bh>=1&&bh<=3){cusor_moveto(17, ++i);set_fg_color(COLOR_RED);printf("%s\n",pb->lrc_buf);set_fg_color(COLOR_BLUE);printf("%s\n",pb->next->lrc_buf);printf("%s\n",pb->next->next->lrc_buf);printf("%s\n",pb->next->next->next->lrc_buf);printf("%s\n",pb->next->next->next->next->lrc_buf);}else if(bh==2){cusor_moveto(17, ++i);printf("%s\n",pb->front->lrc_buf);set_fg_color(COLOR_RED);printf("%s\n",pb->lrc_buf);set_fg_color(COLOR_BLUE);printf("%s\n",pb->next->lrc_buf);printf("%s\n",pb->next->next->lrc_buf);}else{cusor_moveto(17, ++i);printf("%s\n",pb->front->front->lrc_buf);printf("%s\n",pb->front->lrc_buf);set_fg_color(COLOR_RED);printf("%s\n",pb->lrc_buf);set_fg_color(COLOR_BLUE);printf("%s\n",pb->next->lrc_buf);printf("%s\n",pb->next->next->lrc_buf);}Sleep(1000);system("cls");//clear_screen();}}return 0; } void read_src_file(unsigned long int *file_length) {//系統(tǒng)文件指針FILE *fp;if((fp=fopen("C:\\Users\\84553\\Documents\\Visual Studio 2012\\Projects\\歌詞解析\\aaa.txt","rb+"))==NULL){printf("Cannot open the file\n"); return ;}if(fp==NULL){printf("Cannot open the file\n");return ;}//定位文件末尾位置fseek(fp,-1,SEEK_END);//測文件字節(jié)數(shù)*file_length=ftell(fp);//復(fù)位讀寫位置到文件的開始rewind(fp);//根據(jù)第3步得到的字節(jié)數(shù),申請內(nèi)存lrc_buf1=(char *)malloc(*file_length+1); //文件中讀取內(nèi)容,存到申請的空間里fread(lrc_buf1,*file_length,1,fp); lrc_buf1[*file_length]=0;return ; }Linux下實現(xiàn):
console.h#ifndef _CONSOLE_H_ #define _CONSOLE_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #endif#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 藍(lán) COLOR_YELLOW 黃 COLOR_WHITE 白 COLOR_CYAN 青 COLOR_MAGENTA 洋紅 */extern void cusor_moveto(int x, int y);//光標(biāo)跳轉(zhuǎn)到 y行 x列 extern void cusor_get_pos(void);//保存光標(biāo)位置 extern void cusor_hide(void); extern void cusor_set_pos(void);//恢復(fù)光標(biāo)位置 extern void clear_screen(void);//清屏 extern void set_fg_color(int color);//設(shè)置字體前景色 extern void set_bg_color(int color);//設(shè)置字體背景色void cusor_moveto(int x, int y) {// ESC[y;xHprintf("\033[%d;%dH",y,x);fflush(stdout); } //保存光標(biāo)位置 void cusor_get_pos(void) {// ESC[sprintf("\033[s");fflush(stdout); } //恢復(fù)光標(biāo)位置 void cusor_set_pos(void) {// ESC[uprintf("\033[u");fflush(stdout); } void cusor_hide(void) {printf("\033[?25l"); } //清屏 void clear_screen(void) {// ESC[2Jprintf("\033[2J");fflush(stdout); }/* COLOR_RED 紅 COLOR_BLACK 黑 COLOR_GREEN 綠 COLOR_BLUE 藍(lán) COLOR_YELLOW 黃 COLOR_WHITE 白 COLOR_CYAN 青 COLOR_MAGENTA 洋紅 */ //設(shè)置前景顏色 void set_fg_color(int color) {// ESC[#mprintf("\033[%dm",color);fflush(stdout); }//設(shè)置背景顏色 void set_bg_color(int color) {// ESC[#mprintf("\033[%dm",(color+10));fflush(stdout); }lrc.h#ifndef __LRC_H__ #define __LRC_H__typedef struct lrc{int m_time;char lrc_buf[200];struct lrc *front;struct lrc *next; }LRC;extern char*read_lrc_file(char*lrc_file_name); extern int lrc_deal(char*lrc_src,char*lrc_done[],char*str); extern void lrc_insert(LRC**p_head,LRC*p_new); extern LRC*lrc_search_time(LRC*head,int num); #endifmusic.c#include<stdio.h> #include <stdlib.h> #include<string.h> #include <unistd.h> #include "console.h" #include"lrc.h"char*read_lrc_file(char*lrc_file_name) {FILE*fp=fopen(lrc_file_name,"rb");char*lrc;unsigned long int length;if(fp==NULL)return NULL;fseek(fp,0,2);length=ftell(fp);rewind(fp);lrc=(char*)malloc(length+1);fread(lrc,length,1,fp);lrc[length]='\0';fclose(fp);return lrc; }int lrc_deal(char*lrc_src,char*lrc_done[],char*str) {int i=0;lrc_done[i]=strtok(lrc_src,str);while(lrc_done[i]!=NULL)lrc_done[++i]=strtok(NULL,str);return i; }void lrc_insert(LRC**p_head,LRC*p_new) {LRC *pb,*pf;pb=*p_head;if(*p_head == NULL)//鏈表為空,新來的節(jié)點就是頭節(jié)點{*p_head=p_new;p_new->front=NULL;p_new->next=NULL;return ;}while((p_new->m_time >= pb->m_time) && (pb->next!=NULL) ){pb=pb->next ;}if(p_new->m_time < pb->m_time)//找到了一個pb的num比新來的節(jié)點的num大,插在pb前邊{if(pb==*p_head)//找到的節(jié)點是頭節(jié)點,插在頭節(jié)點的前邊{p_new->next=*p_head;(*p_head)->front=p_new;p_new->front=NULL;*p_head=p_new;}else{pf=pb->front;//pf指向 找到節(jié)點的前一個節(jié)點p_new->next=pb;p_new->front=pf;pf->next=p_new;pb->front=p_new;}}else//所有pb指向節(jié)點的num都比p_new指向的節(jié)點的num小,插在最后{pb->next=p_new;p_new->front=pb;p_new->next=NULL;} }LRC*lrc_search_time(LRC*head,int num) {LRC*p_mov;p_mov=head;while(p_mov!=NULL){if(p_mov->m_time==num)//找到了{(lán)return p_mov;}p_mov=p_mov->next;}return NULL;//沒有找到 }int main() {LRC *head=NULL,*p_new,*pb,*pf;unsigned int i=0,j,k,temp=0;char lrc_name[30],singer[30];char *str;int min,sec,time_buf[5];char *q[100];unsigned int len=0;char*lrc_file_name="簡單愛.lrc";char*lrc_buf=read_lrc_file(lrc_file_name);len=lrc_deal(lrc_buf,q,"\r\n");sscanf(q[0],"%*4c%[^]]",lrc_name);sscanf(q[1],"%*4c%[^]]",singer);for(k=4;k<len;k++)//處理第5行到最后一行{str=q[k];i=0;while(*str=='['){sscanf(str,"[%2d:%2d",&min,&sec);time_buf[i++]=min*60+sec;str=str+10;}for(j=0;j<i;j++){p_new=(LRC*)malloc(sizeof(LRC));//申請節(jié)點p_new->m_time=time_buf[j];//節(jié)點的時間成員賦值strcpy(p_new->lrc_buf,str);//節(jié)點的歌詞成員賦值lrc_insert(&head,p_new);//插入鏈表 }}pf=head;clear_screen();//清屏cusor_hide();while(1){ sleep(1);temp++;i=0;clear_screen();pb=lrc_search_time(head,temp);min=temp/60;sec=temp%60; cusor_moveto(20, ++i);set_fg_color(COLOR_CYAN);printf("歌曲:%s\n",lrc_name);cusor_moveto(20, ++i);printf("歌手:%s\n",singer);cusor_moveto(25, ++i);printf("%02d:%02d\n",min,sec);if(pb==NULL);else pf=pb;if(pf->front!=NULL&&pf->front->front==NULL){cusor_moveto(17, ++i);printf("%s",pf->front->lrc_buf);}if(pf->front!=NULL&&pf->front->front!=NULL){cusor_moveto(17, ++i);printf("%s",pf->front->lrc_buf);cusor_moveto(17, ++i);printf("%s",pf->front->front->lrc_buf);}cusor_moveto(17, ++i);set_fg_color(COLOR_BLUE);printf("%s",pf->lrc_buf);if(pf->next!=NULL&&pf->next->next==NULL){cusor_moveto(17, ++i);set_fg_color(COLOR_CYAN);printf("%s",pf->next->lrc_buf);cusor_moveto(17, ++i);}if(pf->next!=NULL&&pf->next->next!=NULL){cusor_moveto(17, ++i);set_fg_color(COLOR_CYAN);printf("%s",pf->next->lrc_buf);cusor_moveto(17, ++i);printf("%s",pf->next->next->lrc_buf);}if(temp==300)break;}cusor_get_pos();system("clear");set_fg_color(COLOR_BLACK);return 0; }總結(jié)
- 上一篇: HUAWEI MH5000-31 5G
- 下一篇: SDL2音视频渲染入门