当前代码只适用于Windows,以后也许会考虑多平台通用。
代码:https://github.com/jthmath/LrcParser
一、LRC简介
LRC歌词的结构,大概是这个样子的:
[00:20.50]ステンカラーのコート 【折式立领的外套】 [00:23.60]私に巻きつけた 【将我裹在其中】 [00:26.49]风邪をひくよといって 【你说着“会感冒的哦”】 [00:31.41] [00:33.25]君の指がそっと 【你的手指】 [00:36.25]长い髪に触れた 【触碰我的长发】 [00:39.14]いつか 梦见たシーン 【仿佛总是在梦中出现的场景】
方括号中的是时间标签,后面紧跟一行文本作为歌词。
值得注意的是,下面的方式也是可以的。如此一来,两个时刻对应同一段歌词。
[01:35.22][00:26.49]风邪をひくよといって 【你说着“会感冒的哦”】
二、代码简介
用这个类表示一行歌词:
class Line
{
public:
int Time_{ 0 };
std::wstring Text_;
public:
Line() = default;
Line(int Time, const std::wstring &str);
};
这个类表示整个歌词:
class Lyric
{
public:
std::vector<Line> Lines_;
// 其他内容
};
歌词解析完成后,会逐行存入Lyric::Lines_。
下面的类是一个解析器:
class Parser
{
bool LoadFile(const std::wstring &FileName);
bool MakeLyric(Lyric *pLrc);
// 其他内容
};
其中,LoadFile的作用是读取一个文件,MakeLyric的作用是将解析出来的数据放入一个Lyric对象。
在我的代码中,上面三个类都在一个叫做lrc的名称空间(namespace)中。
三、示例
#include <iostream>
#include "Parser.h"
void init()
{
std::wcout.imbue(std::locale("chs"));
}
void Println(const wchar_t *p)
{
std::wcout << p << std::endl;
}
void PrintLrc(const lrc::Lyric &l)
{
const auto End = l.Lines_.cend();
for (auto it = l.Lines_.begin(); it != End; ++it)
{
std::wcout << it->Time_ << ‘ ‘ << it->Text_ << std::endl;
}
}
int wmain()
{
init();
lrc::Parser par; // 建立一个解析器
if (!par.LoadFile(std::wstring(L"D:\\小小约会.lrc"))) // 载入文件
{
Println(L"载入文件失败");
return 0;
}
lrc::Lyric l;
if (!par.MakeLyric(&l)) // 放进去
{
Println(L"生成歌词数据结构失败");
return 0;
}
PrintLrc(l); // 输出出来
return 0;
}
把LoadFile的参数改为一个歌词文件(歌词文件的编码必须是Unicode,目前只支持这个)的路径,编译运行,你会看到下面的结果。

原文:http://my.oschina.net/jthmath/blog/391538