// main.c
#include
#include
#include
#include
#include
#include
#include struct lrc
{ // 定义一个链表串起时间和歌词int time; // 时间char lrc_buf[200]; // 歌词int lrc_num; // 第几句歌词struct lrc *next; // 链表的指针
};
typedef struct lrc LRC; // 结构体重定义
extern char *open_file(); // 打开文件函数
extern int strtok_deal(char *f, char **song_line); // 歌词切割函数
extern void four_deal(char **song_line, char *four[50]); // 对于前四行特殊处理
extern LRC *init(); // 确定链表头指针
extern void insert(LRC *p, LRC **head);
extern LRC *divide_deal(char **song_line, int n); // 分开时间与歌词
extern void time_delay(int sec); // 时间延迟
extern void set_fg_color(int color); // 设置前景颜色
extern void clear_screen(void); // 清屏函数
extern void set_bg_color(int color); // 设置背景颜色
extern void song_print(LRC *head, char **four); // 歌词打印+效果
char *open_file()
{FILE *fp;fp = fopen("../简单爱.lrc", "rb");if (fp == NULL){printf("NULL!\n");return 0;}fseek(fp, 0L, SEEK_END); // 光标定位int len = ftell(fp); // 读取字节以便申请空间rewind(fp);char *f = (char *)malloc(len);fread(f, len, 1, fp); // 读取return f;
}
int strtok_deal(char *f, char **song_line)
{char *temp = NULL;int k = 0;temp = strtok(f, "\r\n"); // 遇‘\r''\n'切割while (temp){song_line[k++] = temp; // 每行读入temp = strtok(NULL, "\r\n");}return k;
}void four_deal(char **song_line, char *four[50])
{int i;for (i = 0; i < 4; i++){char *temp = strtok(song_line[i], "[]"); // 遇'[]'的切割four[i] = temp;}
}LRC *init()
{LRC *p = (LRC *)malloc(sizeof(LRC));p = NULL;p->next = NULL;return p;
}
void insert(LRC *p, LRC **head)
{ // 一边构建链表一边排序(对链表要求较高)if (*head == NULL){*head = p;return;}LRC *temp = *head, *mid = *head;while (temp->next && temp->time < p->time){mid = temp;temp = temp->next;}if (temp->time >= p->time){p->next = temp;mid->next = p;return;}else{temp->next = p;p->next = NULL;return;}
}LRC *divide_deal(char **song_line, int n)
{char song[100][100], mid[100][100] = {0};char *temp;LRC *head = NULL;int k = 0, i, m = 0, q = 0;for (i = 0; i < n; i++){temp = strtok(song_line[i], "[]");while (temp){strcpy(mid[k++], temp);temp = strtok(NULL, "[]");}}for (i = 0; i < k; i++){if (!isdigit(mid[i][0])){strcpy(song[q++], mid[i]);}}int j = 0;for (i = 0; i < k; i++){if (isdigit(*mid[i])){char hh[5], mm[5], ss[5];LRC *p = (LRC *)malloc(sizeof(LRC));p->time = sscanf(mid[i], "%2s:%2s.%2s", hh, mm, ss);// 这种格式可以让时间以标准形式输出p->time = atoi(hh) * 60 + atoi(mm);// 将时间转化为秒存储到链表中p->lrc_num = ++m;strcpy(p->lrc_buf, song[j]);insert(p, &head); // 找准时机,插入链表}elsej++;}return head;
}
void time_delay(int sec)
{int s_time, e_time;s_time = time(NULL);while (1){e_time = time(NULL);if (e_time == s_time + sec)break;}
}
void clear_screen(void)
{printf("\033[2J");fflush(stdout);
}
void set_fg_color(int color)
{printf("\033[%dm", color);fflush(stdout);
}
void set_bg_color(int color)
{printf("\033[%dm", (color + 10));fflush(stdout);
}
void cusor_moveto(int x, int y)
{printf("\033[%d;%dH", y, x);fflush(stdout);
}
/*// 函数名:song_print
// 参数:
// - head: LRC结构体指针,指向歌曲链表的头部
// - four: 字符串数组指针,包含要打印的歌曲信息
// 返回值:无*/
void song_print(LRC *head, char **four)
{int num = 0, y = 0; // 初始化歌曲编号和纵坐标LRC *p_mov = head; // 指向当前歌曲的指针LRC *p_mov2; // 用于遍历歌曲链表的临时指针LRC *p_mov_front = head, *p_mov_front2; // 指向链表中的前一个和当前歌曲的指针int i, flag = 0; // 循环计数器和标志位while (1){ // 无限循环,直到链表结束或打印完所有歌曲的信息clear_screen(); // 清空屏幕y = 1;// 设置纵坐标为1,表示第一行开始打印歌词for (i = 0; i < 4; i++)// 打印歌手、歌曲名、时长和歌词信息{cusor_moveto(34, y++);// 移动光标到第i行的起始位置printf("\t\t\t\t\t%s\n", four[i]);// 打印字符串元素}cusor_moveto(34, y++);// 移动光标到第5行的起始位置,准备打印下一行的时间信息printf("\t\t\t\t\t %02d:%02d\n", num / 60, num % 60); // 打印时间信息(分钟:秒)if (flag < 4)// 如果还没有打印完四行信息,则将指针移动到链表头部p_mov_front = head;if (num == p_mov->time)// 如果当前歌曲的时间与上一首歌相同,则继续遍历下一首{p_mov = p_mov->next;// 移动指针到下一首歌flag++;// 标记已经遍历了一首新歌if (flag > 4)// 如果已经遍历了四首新歌,则将指针移动回链表头部,以便重新开始遍历p_mov_front = p_mov_front->next;}p_mov2 = p_mov;// 保存当前歌曲的指针,以备后面遍历时使用p_mov_front2 = p_mov_front;// 保存前一个歌曲的指针,以备后面遍历时使用while (p_mov_front2 != p_mov)// 遍历链表中的所有歌曲,并打印出每首歌曲的歌词{cusor_moveto(60, y++);// 移动光标到歌词行的起始位置,准备打印歌词内容printf("\t%s\n", p_mov_front2->lrc_buf);// 打印歌词内容(假设为字符串)p_mov_front2 = p_mov_front2->next;// 移动指针到下一首歌词所在的歌曲}for (i = 0; i < 5; i++)// 如果还有更多的歌曲需要打印,则继续遍历并打印歌词{if (i == 0)// 设置前景色和背景色,以便区分不同歌曲的歌词显示效果{set_fg_color(31);// 设置前景色为蓝色(31)set_bg_color(30);// 设置背景色为黑色(30)}else{set_fg_color(37); // 设置前景色为白色(37)set_bg_color(30);// 设置背景色为黑色(30)}if (p_mov2 != NULL){cusor_moveto(60, y++); // 光标控制printf("\t%s\n", p_mov2->lrc_buf);p_mov2 = p_mov2->next;}}if (p_mov == NULL)break;time_delay(1);num++;}
}
// void playMusic(char* musicFilename) {
// char command[100];
// sprintf(command, "mplayer %s", musicFilename);
// system(command);
// }
void mplayer_play(char *mplayer_play)
{pid_t pid;pid = fork();if (pid < 0){perror("fork");}else if (pid == 0){close(1);close(2);execlp("mplayer", "mplayer", "-slave", "-quiet", mplayer_play, NULL);exit(0);}else{return;}
}
int main()
{char *temp = NULL;char *song_line[100];int line_num, i;char *four[50];temp = open_file(); // open_file 打开文件LRC *head = NULL;line_num = strtok_deal(temp, song_line); // hang_strtokfour_deal(song_line, four);line_num -= 4;for (i = 0; i < line_num; i++){song_line[i] = song_line[i + 4];}head = divide_deal(song_line, line_num);mplayer_play("../简单爱.mp3");song_print(head, four);return 0;
}
Linux中c语言歌词解析
// main.c#include #include #include #include #include #include #include s
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!