00. 目录

文章目录

  • 00. 目录
  • 01. 项目简介
  • 02. 环境部署(省略)
  • 03. LRC格式(了解)
    • 3.1 LRC概述
    • 3.2 LRC格式
    • 3.3 LRC制作
    • 3.4 LRC应用
    • 3.5 LRC详细说明
  • 04. 终端控制码
  • 05. 启动mplayer接口函数(省略)
  • 06. 延时函数
  • 07. 函数封装
  • 08. lrc_read_file函数
  • 09. lrc_strtok_buf函数
  • 10. lrc_parse_head函数
  • 11. lrc_song_head_free函数
  • 12. lrc_song_head_print函数
  • 13. lrc_color_print函数
  • 14. lrc_time_print函数
  • 15. dlist_find_by_key函数(链表)
  • 16. lrc_lyric_parse函数
  • 17. lrc_lyric_print函数
  • 18. lrc_make_time函数
  • 19. dlist_find_by_key函数测试
  • 20. dlist_sort_by_key函数(链表)
  • 21. 测试程序(最终)
  • 22. 测试结果
  • 23. 总结
  • 24. 附录

01. 项目简介

1.1 项目演示

1.2 涉及到技术点

  • 文件操作

  • 链表

  • 字符串处理

  • 函数封装

  • VT码

02. 环境部署(省略)

2.1 查看系统是否支持mplayer命令

deng@local:~/share/project/lrc_linux$ mplayerCommand 'mplayer' not found, but can be installed with:sudo apt install mplayer

2.2 安装mplayer软件

deng@local:~/share/project/lrc_linux$ sudo apt install mplayer

2.3 查看mplayer是否安装成功

deng@local:~/share/project/lrc_linux$ mplayer --help
Usage:   mplayer [options] [url|path/]filename

03. LRC格式(了解)

3.1 LRC概述

lrc是英文lyric(歌词)的缩写,被用做歌词文件的扩展名。以lrc为扩展名的歌词文件可以在各类数码播放器中同步显示。LRC 歌词是一种包含着“:”形式的“标签(tag)”的、基于纯文本的歌词专用格式。最早由郭祥祥先生(Djohan)提出并在其程序中得到应用。这种歌词文件既可以用来实现卡拉OK功能(需要专门程序),又能以普通的文字处理软件查看、编辑。当然,实际操作时通常是用专门的LRC歌词编辑软件进行高效编辑的。

3.2 LRC格式

1、标准格式: [分钟:秒.毫秒] 歌词

注释:中括号、冒号、点号全都要求英文输入状态;

2、其他格式①:[分钟:秒] 歌词;

3、其他格式②:[分钟:秒:毫秒] 歌词,与标准格式相比,秒后边的点号被改成了冒号。

3.3 LRC制作

LRC文件是通过编辑器把歌词按歌曲歌词出现的时间编辑到一起,然后在播放歌曲时同步依次将歌词显示出来的,用记事本按照上述格式写好后,将扩展名改为lrc即可做出“文件名.LRC”的歌词文件。当然,要进行高效的lrc歌词制作需要专门的软件。

专门制作LRC歌词的软件有Lrc歌词编辑器2010、千千静听等,它们都支持傻瓜操作和专业操作,即针对新手,有一看就会的制作歌词的方法,针对专业人士,也有高级编辑模式,具体操作可以点击链接进入它们的专门词条查看。

还有一种文本转语音的软件在把文字导出成MP3声音文件的同时也能导出LRC文件,导出后用支持LRC的播放器播放MP3的时候LRC会被自动加载并显示出来,这方面的典型代表软件是TTSUU文本转语音软件,其典型应用是用来制作单词、句子以及课文等的双语对照朗读的MP3以及同步LRC歌词字幕,对学生学习外语很有帮助。

3.4 LRC应用

市场上的支持显示歌词的音乐播放器都有相同的规定,要求歌曲和LRC歌词的文件名相同(即除了扩展名.mp3、.wma、.lrc等不同之外,点前面的文字、文字格式要一模一样)并且放在同一目录下(即同一文件夹中),用带显示歌词功能的播放器播放歌曲时歌词就可以同步显示,方便查看和学歌。

3.5 LRC详细说明

lrc歌词文本中含有两类标签

一是标识标签,其格式为“[标识名:值]”主要包含以下预定义的标签:

[ar:歌手名]、[ti:歌曲名]、[al:专辑名]、[by:编辑者(指lrc歌词的制作人)]、[offset:时间补偿值] (其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的,但多数的MP3可能不会支持这种标签)。

二是时间标签,形式为“[mm:ss]”或“[mm:ss.ff]”(分钟数:秒数.百分之一秒数),时间标签需位于某行歌词中的句首部分,一行歌词可以包含多个时间标签(比如歌词中的迭句部分)。当歌曲播放到达某一时间点时,MP3就会寻找对应的时间标签并显示标签后面的歌词文本,这样就完成了“歌词同步”的功能。

  • 时间标签(Time-tag)

形式为"[mm:ss]“(分钟数:秒数)或”[mm:ss.ff]“。数字须为非负整数, 比如”[12:34.50]“是有效的,而”[0x0C:-34.50]"无效(但也有不太规范的歌词采用[00:-0.12]的方式表示负值以显示歌曲名,部分播放器是支持的)。 它可以位于某行歌词中的任意位置。一行歌词可以包含多个时间标签(比如歌词中的迭句部分)。根据这些时间标签,用户端程序会按顺序依次高亮显示歌词,从而实现卡拉OK功能。另外,标签无须排序。

  • 标识标签(ID-tags)

其格式为"[标识名:值]"。大小写等价。以下是预定义的标签。

[ar:艺人名]

[ti:曲名]

[al:专辑名]

[by:编者(指编辑LRC歌词的人)]

[offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。

歌词文件示例

[ti:依赖]——ti.=title,标题,即歌曲名
[ar:蔡健雅]——ar.=artist,艺术家,即歌手名
[al:MY SPACE]——al.=album,专辑,即歌曲被收录的专辑
[by:Chapter Chang]——by somebody,即LRC歌词文件的制作者
[offset:0]——补偿时值。500=0.5秒,正负值分别提前和延长相应的时间(其值多为500的倍数)
(以下为歌词内容,前面中括号内的数字为内容显示时的时值精确到毫秒;后面为在播放器上显示的内容,可以介绍歌曲的名称、演唱者和作者等ID3信息等。相同的歌词内容反复时可以在词句前加上其依次出现时的时值)
[00:00.50]蔡健雅 - 依赖
[00:07.94]词、曲:蔡健雅、陶晶莹
[00:11.60]关了灯把房间整理好
[00:15.48]凌晨三点还是睡不著
[00:19.64]你应该是不在 所以把电话挂掉
[00:30.39]在黑暗手表跟着心跳
[00:34.57]怎么慢它停也停不了
[00:39.70]我应该只是心情不好
[00:45.00]那又怎样
[00:48.50]但本来是这样
[01:21.36]朋友们对我的安慰
[01:25.20]都是同样的一个话题
[01:29.73]我一定要变得更坚强
[01:34.68]说很简单
[00:38.50]但是做却很难
[00:53.00][01:43.88][02:11.23]虽然无所谓写在脸上
[00:58.21][01:48.44][02:15.79]我还是舍不得让你离开
[01:02.97][01:53.50][02:20.60]虽然闭着眼假装听不到
[01:07.84][01:58.23][02:25.11][02:33.15]你对爱 已不再 想依赖

04. 终端控制码

提示: 会调用提供的接口函数即可

console.h(不需要实现 会使用即可)

#ifndef  _CONSOLE_H_
#define  _CONSOLE_H_/*
COLOR_RED              红
COLOR_BLACK            黑
COLOR_GREEN            绿
COLOR_BLUE             蓝
COLOR_YELLOW           黄
COLOR_WHITE            白
COLOR_CYAN             青
COLOR_MAGENTA          洋红
*/
#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          35void cusor_moveto(int x, int y);//光标跳转到 y行 x列
void cusor_save_pos(void);//保存光标位置
void cusor_recover_pos(void);//恢复光标位置
void cusor_hide(void);//隐藏光标
void cusor_show(void);//显示光标
void clear_screen(void);//清屏
void set_fg_color(int color);//设置字体前景色
void set_bg_color(int color);//设置字体背景色#endif    //_CONSOLE_H_

console.c

#include <stdio.h>
#include <stdlib.h>
#include "console.h"//光标跳转到y行 x列
void cusor_moveto(int x, int y)
{//ESC[y;xHprintf("\033[%d;%dH",y,x);fflush(stdout);
} //保存光标位置
void cusor_save_pos(void)
{//ESC[sprintf("\033[s");fflush(stdout);
} //恢复光标位置
void cusor_recover_pos(void)
{   // ESC[uprintf("\033[u");fflush(stdout);
}
//隐藏光标
void cusor_hide(void)
{printf("\033[?25l");
}
//显示光标
void cusor_show(void)
{printf("\33[?25h");
}
//清屏
void clear_screen(void)
{// ESC[2Jprintf("\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[#mprintf("\033[%dm",color);fflush(stdout);
}//设置背景颜色
void set_bg_color(int color)
{// ESC[#mprintf("\033[%dm",(color+10));fflush(stdout);
}

test.c

#include <stdio.h>
#include "console.h"int main(void)
{printf("hello vt\n");//清屏clear_screen(); cusor_moveto(100, 50);set_fg_color(COLOR_RED);printf("Hello, I Love 1000phone1\n");cusor_moveto(50, 100);set_bg_color(COLOR_BLUE);printf("Hello, I Love 1000phone2\n");return 0;
}

Makefile

TARGET:=test
CC:=gcc
OBJS:=obj/console.o obj/test.o  obj/lrc.o obj/dlist.o
CFLAGS:=-Wall$(TARGET):$(OBJS)$(CC) $(CFLAGS) $^ -o $@obj/%.o:%.c$(CC) -c $< -o $@.PHONY:clean
clean:rm -rf $(OBJS) $(TARGET)

05. 启动mplayer接口函数(省略)

提示:不用实现,暂时会调用接口函数即可

mplayer.h

#ifndef __MPLAYER_H__
#define __MPLAYER_H__void mplayer_play(char *path);#endif/*__MPLAYER_H__*/

mplayer.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void mplayer_play(char *path)
{pid_t pid = -1;//创建子进程pid = fork();if (pid < 0){perror("fork");}else if (0 == pid){close(1);close(2);execlp("mplayer", "mplayer", "-slave", "-quiet", path, NULL);exit(0);}else{}
}

06. 延时函数

#include <unistd.h>int usleep(useconds_t usec);
功能:参数:usec 睡眠微秒
返回值:
#include <unistd.h>unsigned int sleep(unsigned int seconds);
功能:参数:seconds睡眠秒数
返回值:

07. 函数封装

lrc.h

#ifndef __LRC_H__
#define __LRC_H__#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dlist.h"//时间相关结构体类型
typedef struct _lrc_time_t{//分钟unsigned short min;    //秒unsigned short sec;
}lrc_time_t;//歌词节点信息
typedef struct _lrc_node_t{int time;char lrcbuf[200];
}lrc_node_t;//加载歌词文件
char *lrc_read_file(const char *filename);//使用\r\n切割歌词
int lrc_strtok_buf(char *lrc_text[], char *ptext);//解析lrc文件前4行 歌手 歌名 专辑 制作等等
int lrc_parse_head(char *lrc_text[], char *song_msg[]);//显示歌曲信息 前4行
int lrc_song_head_print(char *song_msg[]);//释放song_head内存
int lrc_song_head_free(char *song_msg[], int n);//指定字体颜色输出字符串
int lrc_color_print(char *str, int x, int y, int color);//显示歌词的时间
int lrc_time_print(lrc_time_t *t);//解析歌词信息 歌词和时间
int lrc_lyric_parse(dlist_t *d, int lrc_lines, char *lrc_text[]);//打印链表中5个节点的信息到屏幕上
int lrc_lyric_print(node_t *start, node_t *cur);//将秒数转化为分和秒 lrc_time_t类型
int lrc_make_time(lrc_time_t *t);#endif /*__LRC_H__*/

lrc.c

#include "lrc.h"
#include "console.h"//加载歌词文件
char *lrc_read_file(const char *filename)
{return NULL;
}//使用\r\n切割歌词 返回歌词的行数
int lrc_strtok_buf(char *lrc_text[], char *ptext)
{return 0;
}//解析lrc文件前4行 歌手 歌名 专辑 制作等等
//[ti:简单爱]
//[ar:周杰伦]
//[al:范特西]
//[by:大脸猫]
int lrc_parse_head(char *lrc_text[], char *song_msg[])
{return 0;
}//释放song_head内存
int lrc_song_head_free(char *song_msg[], int n)
{return 0;
}//显示歌曲信息 前4行
int lrc_song_head_print(char *song_msg[])
{return 0;
}//指定字体颜色输出字符串
int lrc_color_print(char *str, int x, int y, int color)
{return 0;
}//显示歌词的时间
int lrc_time_print(lrc_time_t *t)
{return 0;
}//解析歌词信息 歌词和时间
int lrc_lyric_parse(dlist_t *d, int lrc_lines, char *lrc_text[])
{return 0;
}//打印链表中5个节点的信息到屏幕上
int lrc_lyric_print(node_t *start, node_t *cur)
{return 0;
}//将秒数转化为分和秒 lrc_time_t类型
int lrc_make_time(lrc_time_t *t)
{return 0;
}

08. lrc_read_file函数

lrc.c

//加载歌词文件
char *lrc_read_file(const char *filename)
{int ret = 0;//文件大小long filesize = 0;char *ptext = NULL;FILE *fp = NULL;//参数检查if (NULL == filename){printf("lrc_read_file NULL\n");goto err0;}//打开文件fp = fopen(filename, "r");if (NULL == fp){printf("fopen failed..\n");goto err0;}//文件定位到文件最后fseek(fp, 0, SEEK_END);//获取文件大小filesize = ftell(fp);//动态分配空间ptext = malloc(filesize + 1);if (NULL == ptext){printf("malloc failed...\n");goto err1;}memset(ptext, 0, filesize + 1);//文件定位到开头rewind(fp);//读取文件所有内容 ret = fread(ptext, filesize, 1, fp);    if (0 == ret){printf("fread failed...\n");goto err1;}//关闭文件fclose(fp);return ptext;
err1:fclose(fp);
err0:return NULL;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"int main(void)
{char *ptext = NULL;ptext = lrc_read_file("./love.lrc");printf("%s", ptext);if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

执行结果:

deng@local:~/code/project/3lrc$ ./test
[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]想~~~ 简!简!单!单! 爱~~~

09. lrc_strtok_buf函数

lrc.c

//使用\r\n切割歌词 返回歌词的行数
int lrc_strtok_buf(char *lrc_text[], char *ptext)
{int i = 0;//切割获取文件第一行lrc_text[i] = strtok(ptext, "\r\n");while(NULL != lrc_text[i]){i++;lrc_text[i] = strtok(NULL, "\r\n");}return i;
err0:return -1;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"int main(void)
{int i = 0;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);for (i = 0; i < lines; i++){printf("%s\n", lrc_line_text[i]);}//释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

执行结果

deng@local:~/code/project/3lrc$ ./test
lines: 29
[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]想~~~ 简!简!单!单! 爱~~~

10. lrc_parse_head函数

lrc.c

//解析lrc文件前4行 歌手 歌名 专辑 制作等等
//[ti:简单爱]
//[ar:周杰伦]
//[al:范特西]
//[by:大脸猫]
int lrc_parse_head(char *lrc_text[], char *song_msg[])
{int i = 0;//分隔符char *tok[] = {"[ti", "[ar", "[al", "[by"};for (i = 0; i < 4; i++){if (strncmp(lrc_text[i], tok[i], 3) == 0){song_msg[i] = malloc(strlen(lrc_text[i]) - 4);if (NULL == song_msg[i]){printf("lrc_parse_head malloc failed...\n");break;}sscanf(lrc_text[i], "%*4s%[^]]", song_msg[i]);}else{//不存在该字段song_msg[i] = NULL;}}return 0;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];int main(void)
{int i = 0;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);lrc_parse_head(lrc_line_text, song_msg); //验证是否获取歌曲信息是否成功for (i = 0; i < 4; i++){printf("%s\n", song_msg[i]);}//释放内存 song_msg[i]for (i = 0; i < 4; i++){free(song_msg[i]);}//释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

运行结果

deng@local:~/code/project/3lrc$ ./test
lines: 29
简单爱
周杰伦
范特西
大脸猫
deng@local:~/code/project/3lrc$

11. lrc_song_head_free函数

lrc.c

//释放song_head内存
int lrc_song_head_free(char *song_msg[], int n)
{int i = 0;for (i = 0; i < n; i++){if (NULL != song_msg[i]){free(song_msg[i]);song_msg[i] = NULL;}}return 0;
}

12. lrc_song_head_print函数

lrc.c

//显示歌曲信息 前4行
int lrc_song_head_print(char *song_msg[])
{int i = 0;char *head_name[4] = {"歌名", "歌手", "专辑", "制作"};//清屏clear_screen();//隐藏光标cusor_hide();//设置字体颜色为蓝色set_fg_color(COLOR_BLUE); //输出歌曲信息for (i = 0; i < 4; i++){if (NULL != song_msg[i]){//移动光标到i + 1行 35列cusor_moveto(35, i + 1);printf("%s : %s\n", head_name[i], song_msg[i]);}}return 0;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];int main(void)
{int i = 0;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);lrc_parse_head(lrc_line_text, song_msg); lrc_song_head_print(song_msg);//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

运行结果

13. lrc_color_print函数

lrc.c

//指定字体颜色输出字符串
int lrc_color_print(char *str, int x, int y, int color)
{//光标移动到指定位置cusor_moveto(x, y);//设置字体颜色set_fg_color(color);//输出字符串printf("%s\n", str);return 0;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];//时间
lrc_time_t lrc_time = {0, 0};int main(void)
{int i = 0;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);//解析歌词信息 前4行lrc_parse_head(lrc_line_text, song_msg); //输出歌词信息 前4行lrc_song_head_print(song_msg);//测试控制字体颜色输出字符串lrc_color_print("千锋扫地僧", 40, 5, COLOR_RED);//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

14. lrc_time_print函数

lrc.c

//显示歌词的时间
int lrc_time_print(lrc_time_t *t)
{char str[32];memset(str, 0, 32);sprintf(str, "%02d:%02d", t->min, t->sec);lrc_color_print(str, 40, 5, COLOR_BLUE);return 0;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];//时间
lrc_time_t lrc_time = {0, 0};int main(void)
{int i = 0;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);//解析歌词信息 前4行lrc_parse_head(lrc_line_text, song_msg); //输出歌词信息 前4行lrc_song_head_print(song_msg);//显示歌词时间lrc_time_print(&lrc_time);//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

运行结果

15. dlist_find_by_key函数(链表)

dlist.h

//通过key检索链表节点数据
node_t *dlist_find_by_key(dlist_t *d, void *key, cmp_t my_cmp);

dlist.c

//通过key检索链表节点数据
node_t *dlist_find_by_key(dlist_t *d, void *key, cmp_t my_cmp)
{int i = 0;node_t *tmp = NULL;//参数检查if (NULL == d || NULL == key || NULL == my_cmp|| NULL == d->p){printf("dlist_find_by_key NULL\n");goto err0;}//指向第一个节点tmp = d->p;do {if (my_cmp(tmp->data, key) == 0) {break;}i++;tmp = tmp->next;}while(tmp != d->p);//找不到的情形if (i == d->count){goto err0;}return tmp;
err0:return NULL;
}

16. lrc_lyric_parse函数

lrc.c

//解析歌词信息 歌词和时间 然后插入到链表中
int lrc_lyric_parse(dlist_t *d, int lrc_lines, char *lrc_text[])
{int i = 0;int j = 0;int min;int sec;//歌词节点信息lrc_node_t node;int time_array[10] = {0};int time_counts = 0;char *src = NULL;if (NULL == d || NULL == lrc_text){printf("lrc_lyric_parse NULL\n");goto err0;}if (lrc_lines <= 0){printf("歌词行数<= 0\n");goto err0;}//从第5行开始解析 前面4行是基本信息for (i = 4; i < lrc_lines; i++){//[00:26.44]说不上为什么 我变得很主动src = lrc_text[i]; //同一句歌词重复次数time_counts = 0;//解析时间 一句歌词可能有多个时间 重复 while('[' == *src) {sscanf(src, "[%2d:%2d", &min, &sec);time_array[time_counts++] = min * 60 + sec;//[00:26.44] 有十个字符src = src + 10;}//解析完一行所有的时间后,src就为歌词的首地址//根据歌词的时间个数, 将歌词和时间保存到链表中for (j = 0; j < time_counts; j++){memset(&node, 0, sizeof(node));node.time = time_array[j]; strcpy(node.lrcbuf, src);dlist_append(d, &node);}}return 0;
err0:return -1;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];int my_print(void *data)
{lrc_node_t *l = data;printf("%d %s\n", l->time, l->lrcbuf);
}//时间
lrc_time_t lrc_time = {0, 0};int main(void)
{int i = 0;//链表dlist_t *d = NULL;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);//解析歌词信息 前4行lrc_parse_head(lrc_line_text, song_msg); //输出歌词信息 前4行lrc_song_head_print(song_msg);//显示歌词时间lrc_time_print(&lrc_time);//链表d = dlist_create(sizeof(lrc_node_t));//链表遍历lrc_lyric_parse(d, lines, lrc_line_text);dlist_traverse(d, my_print);printf("counts: %d\n", dlist_count(d));//链表销毁dlist_destroy(d);if (NULL != d){free(d);d = NULL;}//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

运行结果

deng@local:~/code/project/3lrc$ ./test
lines: 29歌名 :   简单爱歌手 :   周杰伦专辑 :   范特西制作 :   大脸猫00:00
4 周杰伦 Chow, Jay Jou
10 简单爱(台视Star blue蓝星主题曲)
18 词:徐若瑄 曲:周杰伦
26 说不上为什么 我变得很主动
31 若爱上一个人 什么都会值得去做
124 我想大声宣布 对你依依不舍
36 我想大声宣布 对你依依不舍
129 连隔壁邻居都猜到我现在的感受
41 连隔壁邻居都猜到我现在的感受
134 河边的风 在吹着头发 飘动
46 河边的风 在吹着头发 飘动
139 牵着你的手 一阵莫名感动
51 牵着你的手 一阵莫名感动
144 我想带你 回我的外婆家
55 我想带你 回我的外婆家
148 一起看着日落 一直到我们都睡着
59 一起看着日落 一直到我们都睡着
214 我想就这样牵着你的手不放开
154 我想就这样牵着你的手不放开
65 我想就这样牵着你的手不放开
219 爱能不能够永远单纯没有悲哀
159 爱能不能够永远单纯没有悲哀
70 爱能不能够永远单纯没有悲哀
224 我想 带你骑单车
163 我想 带你骑单车
75 我想 带你骑单车
226 我想 和你看棒球
166 我想 和你看棒球
78 我想 和你看棒球
229 想这样没担忧
169 想这样没担忧
80 想这样没担忧
231 唱着歌 一直走☆
171 唱着歌 一直走☆
82 唱着歌 一直走☆
234 我想就这样牵着你的手不放开
174 我想就这样牵着你的手不放开
85 我想就这样牵着你的手不放开
239 爱可不可以简简单单没有伤害
179 爱可不可以简简单单没有伤害
90 爱可不可以简简单单没有伤害
243 你 靠着我的肩膀
183 你 靠着我的肩膀
95 你 靠着我的肩膀
246 你 在我胸口睡着
186 你 在我胸口睡着
97 你 在我胸口睡着
249 像这样的生活
189 像这样的生活
100 像这样的生活
251 我爱你 你爱我★
191 我爱你 你爱我★
102 我爱你 你爱我★
193 想~~~ 简!简!单!单! 爱~~~
104 想~~~ 简!简!单!单! 爱~~~
203 想~~~ 简!简!单!单! 爱~~~
114 想~~~ 简!简!单!单! 爱~~~counts: 57
deng@local:~/code/project/3lrc$

17. lrc_lyric_print函数

lrc.c

//打印链表中5个节点的信息到屏幕上
int lrc_lyric_print(node_t *start, node_t *cur)
{int i = 0;lrc_node_t *lrc_node = NULL;for (i = 0; i < 5; i++){lrc_node = (lrc_node_t*)start->data;//红色高亮显示节点if(start == cur){lrc_color_print(lrc_node->lrcbuf, 30, 6 + i, COLOR_RED); }else{lrc_color_print(lrc_node->lrcbuf, 30, 6 + i, COLOR_BLUE); }//指向链表下一个节点start = start->next;}return 0;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];int my_print(void *data)
{lrc_node_t *l = data;printf("%d %s\n", l->time, l->lrcbuf);
}//时间
lrc_time_t lrc_time = {0, 0};int main(void)
{int i = 0;//链表dlist_t *d = NULL;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);//解析歌词信息 前4行lrc_parse_head(lrc_line_text, song_msg); //输出歌词信息 前4行lrc_song_head_print(song_msg);//显示歌词时间lrc_time_print(&lrc_time);//链表d = dlist_create(sizeof(lrc_node_t));//歌词解析lrc_lyric_parse(d, lines, lrc_line_text);//测试显示前面五条歌词lrc_lyric_print(d->p, NULL);//链表销毁dlist_destroy(d);if (NULL != d){free(d);d = NULL;}//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

运行结果

                                  歌名 :   简单爱歌手 :   周杰伦专辑 :   范特西制作 :   大脸猫00:00周杰伦 Chow, Jay Jou简单爱(台视Star blue蓝星主题曲)词:徐若瑄 曲:周杰伦说不上为什么 我变得很主动若爱上一个人 什么都会值得去做
deng@local:~/code/project/3lrc$

18. lrc_make_time函数

lrc.c

//将秒数转化为分和秒 lrc_time_t类型
int lrc_make_time(lrc_time_t *t)
{t->sec++;if (60 == t->sec){t->sec = 0; t->min++;if (60 == t->min){t->min = 0;}}return 0;
}

测试代码 test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];int my_print(void *data)
{lrc_node_t *l = data;printf("%d %s\n", l->time, l->lrcbuf);
}//时间
lrc_time_t lrc_time = {0, 0};int main(void)
{int i = 0;int sec = 0;//链表dlist_t *d = NULL;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);//解析歌词信息 前4行lrc_parse_head(lrc_line_text, song_msg); //输出歌词信息 前4行lrc_song_head_print(song_msg);//显示歌词时间lrc_time_print(&lrc_time);//链表d = dlist_create(sizeof(lrc_node_t));//歌词解析lrc_lyric_parse(d, lines, lrc_line_text);//测试显示前面五条歌词lrc_lyric_print(d->p, NULL);//开始计时显示歌词while(1){//显示歌词时间lrc_time_print(&lrc_time);//每隔一秒钟刷新一次sleep(1);sec++;//时间结构体赋值lrc_make_time(&lrc_time); }//显示光标cusor_show();//链表销毁dlist_destroy(d);if (NULL != d){free(d);d = NULL;}//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

运行结果

19. dlist_find_by_key函数测试

测试代码 test.c (每隔一段时间自动刷新歌词 验证链表功能)

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];int my_print(void *data)
{lrc_node_t *l = data;printf("%d %s\n", l->time, l->lrcbuf);
}int my_cmp(void *data, void *key)
{lrc_node_t  *t = data; return t->time - *(int*)key;
}//时间
lrc_time_t lrc_time = {0, 0};int main(void)
{int i = 0;int sec = 0;//链表dlist_t *d = NULL;node_t *start = NULL;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);//解析歌词信息 前4行lrc_parse_head(lrc_line_text, song_msg); //输出歌词信息 前4行lrc_song_head_print(song_msg);//显示歌词时间lrc_time_print(&lrc_time);//链表d = dlist_create(sizeof(lrc_node_t));//歌词解析lrc_lyric_parse(d, lines, lrc_line_text);//测试显示前面五条歌词lrc_lyric_print(d->p, NULL);//统计显示歌词节点数i = 0;//开始计时显示歌词while(1){//显示歌词时间//lrc_time_print(&lrc_time);//通过时间查找链表节点start = dlist_find_by_key(d, &sec, my_cmp);if (NULL != start){i++;my_print(start->data);//结束循环if (i == d->count){printf("歌词显示完毕\n");break;}}//每隔一秒钟刷新一次sleep(1);sec++;//时间结构体赋值lrc_make_time(&lrc_time); }//显示光标cusor_show();//链表销毁dlist_destroy(d);if (NULL != d){free(d);d = NULL;}//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

运行结果

输出信息如下:

deng@local:~/code/project/3lrc$ ./test
lines: 29歌名 :   简单爱歌手 :   周杰伦专辑 :   范特西制作 :   大脸猫00:00周杰伦 Chow, Jay Jou简单爱(台视Star blue蓝星主题曲)词:徐若瑄 曲:周杰伦说不上为什么 我变得很主动若爱上一个人 什么都会值得去做
4 周杰伦 Chow, Jay Jou
10 简单爱(台视Star blue蓝星主题曲)
18 词:徐若瑄 曲:周杰伦
26 说不上为什么 我变得很主动
31 若爱上一个人 什么都会值得去做
36 我想大声宣布 对你依依不舍
41 连隔壁邻居都猜到我现在的感受
46 河边的风 在吹着头发 飘动
51 牵着你的手 一阵莫名感动
55 我想带你 回我的外婆家
59 一起看着日落 一直到我们都睡着
65 我想就这样牵着你的手不放开
70 爱能不能够永远单纯没有悲哀
75 我想 带你骑单车
78 我想 和你看棒球
80 想这样没担忧
82 唱着歌 一直走☆
85 我想就这样牵着你的手不放开
90 爱可不可以简简单单没有伤害
95 你 靠着我的肩膀
97 你 在我胸口睡着
100 像这样的生活
102 我爱你 你爱我★
104 想~~~ 简!简!单!单! 爱~~~
114 想~~~ 简!简!单!单! 爱~~~
124 我想大声宣布 对你依依不舍
129 连隔壁邻居都猜到我现在的感受
134 河边的风 在吹着头发 飘动
139 牵着你的手 一阵莫名感动
144 我想带你 回我的外婆家
148 一起看着日落 一直到我们都睡着
154 我想就这样牵着你的手不放开
159 爱能不能够永远单纯没有悲哀
163 我想 带你骑单车
166 我想 和你看棒球
169 想这样没担忧
171 唱着歌 一直走☆
174 我想就这样牵着你的手不放开
179 爱可不可以简简单单没有伤害
183 你 靠着我的肩膀
186 你 在我胸口睡着
189 像这样的生活
191 我爱你 你爱我★
193 想~~~ 简!简!单!单! 爱~~~
203 想~~~ 简!简!单!单! 爱~~~
214 我想就这样牵着你的手不放开
219 爱能不能够永远单纯没有悲哀
224 我想 带你骑单车
226 我想 和你看棒球
229 想这样没担忧
231 唱着歌 一直走☆
234 我想就这样牵着你的手不放开
239 爱可不可以简简单单没有伤害
243 你 靠着我的肩膀
246 你 在我胸口睡着
249 像这样的生活
251 我爱你 你爱我★
歌词显示完毕
deng@local:~/code/project/3lrc$ 

20. dlist_sort_by_key函数(链表)

根据时间节点排序,无需实现,直接使用即可。

dlist.h

//根据关键字排序
int dlist_select_sort(dlist_t *d,  cmp_t my_cmp);

dlistc


//排序链表 选择排序
int dlist_select_sort(dlist_t *d,  cmp_t my_cmp)
{node_t *tmp_i;node_t *tmp_j;node_t *tmp_k;void *tmp_data = NULL;//参数检查if (NULL == d || NULL == my_cmp){printf("dlist_select_sort NULL\n");}//分配空间tmp_data = malloc(d->size);if (NULL == tmp_data){printf("malloc failed...\n");goto err0;}memset(tmp_data, 0, d->size);tmp_i = d->p;do{tmp_k = tmp_i;tmp_j = tmp_i->next;do{if (my_cmp(tmp_k->data, tmp_j->data) > 0){tmp_k = tmp_j;}tmp_j = tmp_j->next;}while(tmp_j != d->p);if (tmp_k != tmp_i){memcpy(tmp_data, tmp_k->data, d->size);memcpy(tmp_k->data, tmp_i->data, d->size);memcpy(tmp_i->data, tmp_data, d->size);}tmp_i = tmp_i->next;}while(tmp_i != d->p->prev);//释放内存free(tmp_data);return 0;
err0:return -1;
}

21. 测试程序(最终)

test.c

#include <stdio.h>
#include <unistd.h>
#include "console.h"
#include "lrc.h"//保存歌曲的信息 前四行
char *song_msg[4];int my_print(void *data)
{lrc_node_t *l = data;printf("%d %s\n", l->time, l->lrcbuf);
}int my_cmp(void *data, void *key)
{lrc_node_t  *t = data; return t->time - *(int*)key;
}//时间
lrc_time_t lrc_time = {0, 0};int main(void)
{int i = 0;int sec = 0;//链表dlist_t *d = NULL;node_t *start = NULL;//存储歌词的行数int lines = 0;//存储歌词每一行char *lrc_line_text[200] = {NULL};//保存歌词char *ptext = NULL;ptext = lrc_read_file("./love.lrc");//切割歌词 \r\n分隔lines = lrc_strtok_buf(lrc_line_text, ptext);printf("lines: %d\n", lines);//解析歌词信息 前4行lrc_parse_head(lrc_line_text, song_msg); //输出歌词信息 前4行lrc_song_head_print(song_msg);//显示歌词时间lrc_time_print(&lrc_time);//链表d = dlist_create(sizeof(lrc_node_t));//歌词解析lrc_lyric_parse(d, lines, lrc_line_text);//排序歌词dlist_select_sort(d, my_cmp);//测试显示前面五条歌词lrc_lyric_print(d->p, NULL);//统计显示歌词节点数i = 0;//开始计时显示歌词while(1){//显示歌词时间lrc_time_print(&lrc_time);//通过时间查找链表节点start = dlist_find_by_key(d, &sec, my_cmp);if (NULL != start){i++;//my_print(start->data);//输出歌词信息 前4行lrc_song_head_print(song_msg);//显示歌词时间lrc_time_print(&lrc_time);//前面3行 不滚动显示if (i <= 3){lrc_lyric_print(d->p, start);}else if (i >= d->count - 5) //最后5行 不滚动显示{//d->p->prev->prev->prev->prev->prev 表示倒数第五个节点lrc_lyric_print(d->p->prev->prev->prev->prev->prev, start);}else{//start->prev->prev表示当前节点前面两个节点lrc_lyric_print(start->prev->prev, start);}//结束循环if (i == d->count){//printf("歌词显示完毕\n");break;}}//每隔一秒钟刷新一次sleep(1);sec++;//时间结构体赋值lrc_make_time(&lrc_time); }//显示光标cusor_show();//链表销毁dlist_destroy(d);if (NULL != d){free(d);d = NULL;}//释放内存 song_msg[i]lrc_song_head_free(song_msg, 4); //释放内存if (NULL != ptext){free(ptext);ptext = NULL;}return 0;
}

22. 测试结果

23. 总结

24. 附录

【课程设计】歌词解析项目相关推荐

  1. 【源码+图片素材】Java王者荣耀游戏开发_开发Java游戏项目【王者荣耀】1天搞定!!!腾讯游戏_Java课程设计_Java实战项目_Java初级项目

    王者荣耀是当下热门手游之一,小伙伴们是否想过如何制作一款属于自己的王者荣耀游戏呢? 本课程讲解了一个王者荣耀游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE ...

  2. lrc 歌词解析项目

    lrc 歌词解析项目 步骤: 0.先上网查找lrc歌词的格式,链接http://baike.baidu.com/view/80650.htm ,分析歌词格式 1.下载歌词文件 2.将歌词文件内容 通过 ...

  3. 【基于物联网的智能草莓种植系统的设计与实现系列教程】0-项目简介 (课程设计、毕设项目、树莓派、yolov5)

    [基于物联网的智能草莓种植系统]详细实现教程 项目各章节跳转 教程简介 项目简介 系统操作界面展示 系统主要功能概述 系统硬件结构概述 特别致谢 猜你需要 项目各章节跳转 可点击跳转到对应章节 ==& ...

  4. 【基于物联网的智能草莓种植系统的设计与实现系列教程】8.项目整体验证(课程设计、毕设项目、树莓派、yolov5、物联网)

    [基于物联网的智能草莓种植系统]BH1750 光照度传感器验证与参考代码 项目各章节跳转 树莓派环境说明 硬件连接 猜你需要 项目各章节跳转 可点击跳转到对应章节 ==> 努力更新中... 0. ...

  5. 设计制作计算机组装评论,计算机组装与维护课程设计_new解析.doc

    计算机组装与维护课程设计 一.根据自己或同学实际需要,按照计算机组成的相关理论和方法,组装一台微型计算机.请列出此微型计算机的具体配置方案以及配置的理由. 配件类型 型号 理由处理器 AMD羿龙II ...

  6. 智能蜂箱管理系统——物联网工程专业软硬结合课设 计算机专业课程设计 大作业 项目(安卓,Springboot后端,网页数据展示前端,ESP8266传输数据,MQTT服务器)

    项目一 智能蜂箱管理系统 (有需要请私聊) 包括安卓端.数据展示的前端(含登录注册),Springboot后端,ESP8266硬件端传输数据的代码,以及文档. 功能简介 安卓端 安卓端具有创建蜂箱.删 ...

  7. Java毕业设计、课程设计、实战项目之[含源码等]基于SSM+Vue的SSM学业预警平台信息管理系统[包运行成功]

    基于SSM+Vue的SSM学业预警平台信息管理系统> 后台框架:Spring.SpringMVC.MyBatis 前端:HTML+CSS+JavaScript+vue 数据库:MySQL 管理员 ...

  8. 【基于物联网的智能草莓种植系统的设计与实现系列教程】1-项目相关硬件购买清单与资料下载 (课程设计、毕设项目、树莓派、yolov5)

    [基于物联网的智能草莓种植系统]项目相关硬件购买清单与资料下载 项目各章节跳转 硬件清单 软件下载 代码下载 猜你需要 项目各章节跳转 可点击跳转到对应章节 ==> 努力更新中... 0.基于物 ...

  9. 【基于物联网的智能草莓种植系统的设计与实现系列教程】7-树莓派触3.5寸控屏连接翻转与触屏校准 (课程设计、毕设项目、树莓派、yolov5)

    [基于物联网的智能草莓种植系统]项目3.5寸触控屏连接验证与相关问题解决 项目各章节跳转 树莓派环境说明 显示屏硬件连接 驱动获取与传输 驱动安装与调试 猜你需要 项目各章节跳转 可点击跳转到对应章节 ...

  10. 计算机毕业设计、课程设计、实战项目之[含论文+源码等]基于SpringBoot在线电影订票系统[包运行成功]

    <基于SpringBoot在线电影订票系统>该项目采用技术后台:Springboot.spring.springmvc.springdata.mysql数据库.前台:FreeMarker. ...

最新文章

  1. 【Matlab 图像】HSV 空间图片分离器
  2. Java 必知必会的 20 种常用类库和 API
  3. Python开发技巧-使用Python生成HTML表格
  4. 记录 之 numpy查看数据类型和类型转换
  5. 关于async与await的FAQ 转
  6. 【概率论】1-2:计数方法(Counting Methods)
  7. DMA流程简介--CPU/内存/网卡之间的交互
  8. Oracle11g新特性:在线操作功能增强-可等待DDL操作
  9. SpringBoot POM 热部署(spring-boot-devtools)
  10. 图像形状特征(八)--SC形状上下文
  11. C++ 常用数学函数
  12. VMware虚拟机安装MAC OS原版系统,轻松体验苹果操作系统
  13. 算法工程师也有35岁危机吗?
  14. ――关于几个著名小说的胡思乱想
  15. 汇编 INT 10H功能
  16. C++ 直接计算多项式的值
  17. FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of me
  18. 程序设计与算法三~C++面向对象程序设计~北大郭炜MOOC学习笔记~第二章:类和对象初步(新标准C++程序设计)
  19. 基于动态径向基函数(DRBF)代理模型的优化策略
  20. VB 中chr(10)、chr(13)和vblf、vbcr、vbcrlf的分别

热门文章

  1. 小程序框架语法详解以及页面生命周期的代码预演
  2. html颜色代码指令,js实现的网页颜色代码表全集
  3. 【5min+】 这些C#的运算符您都认识吗?
  4. 华为程序员:月薪27w了解一下,网友:嫉妒让我面目全非
  5. 《算法概论》习题8.3证明
  6. python导入鸢尾花数据集_用Python进行K次交叉验证,探索鸢尾花数据集(含代码)...
  7. 标签注释、基础图元--osgearth_annotation
  8. 上海拓盟计算机科技,邱兆文-东北林业大学信息与计算机工程学院
  9. SVG在Android中的使用
  10. 2020年自考计算机应用基础和实践是什么,2020年自考计算机应用基础复习重点3