学会在Linux环境下用c语言多文件制作lrc歌词解析器

效果:
在这里插入图片描述

需要掌握的知识

1. 链表的熟悉运用。
懂得在链表的插入,排序。
2. 学会Linux下基本命令指令。
sudo apt-get install vim //下载vim
sudo apt-get install gcc //下载编译软件gcc
ls //查看当前目录下的文件
在这里插入图片描述
cd Desktop/ (Tab 会自动补全唷) //进入桌面
在这里插入图片描述
vim main.c //编辑main.c文件
在这里插入图片描述
进入vim后点击i进入编辑模式
在这里插入图片描述
按下Esc后,点击’Shift‘+ ‘;’ ,输入wq 即可保存
在这里插入图片描述
gcc main.c other.c other.h -o main
//把main.c 与other.c 与other.h 文件 编译成main可执行文件
在这里插入图片描述
./main //运行文件
在这里插入图片描述

基本思想

一般的lrc文件长成这样…

在这里插入图片描述
大致思想是…

  1. 将歌词与时间切割出来
  2. 用链表使其一句歌词对应一个时间
  3. 设置时钟函数记录时间
  4. 最后清屏加时间延迟以及效果显示

下面是代码:

//other.h文件
#ifndef __OTHER_H__   //防止重定义格式
#define __OTHER_H__

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);  //歌词打印+效果

#endif
//other.c
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include"other.h"
char *open_file(){
  FILE *fp;
  fp = fopen("love.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 time[50], k = 0, i, m = 0, q = 0, flag[100];
  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); //找准时机,插入链表
    } else j++;
  }
  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);
} 
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;
	  for(i = 0; i < 4; i++){
          cusor_moveto(34, y++);
	      printf("\t\t\t\t\t%s\n", four[i]);
	  } 
	cusor_moveto(34, y++);
	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);
				set_bg_color(30);
			}else{
				set_fg_color(37);
				set_bg_color(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++;
	}
}
//main.c
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<time.h>
#include"other.h"   
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_strtok
  four_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);
  song_print(head, four);
  return 0;
}
发布了28 篇原创文章 · 获赞 14 · 访问量 2973

猜你喜欢

转载自blog.csdn.net/qq_43408978/article/details/88563144