LRC歌词解析(C++版)

当前代码只适用于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,目前只支持这个)的路径,编译运行,你会看到下面的结果。

LRC歌词解析(C++版)

你可能感兴趣的:(LRC歌词解析(C++版))