您的位置:首页 > 编程语言 > C语言/C++

C++中使用std::regex提取lrc歌词文件

2015-06-18 03:45 676 查看

提取lrc文件

本文介绍使用C++11中新增的std::regex而不是boost::regex提取lrc歌词文件中的信息。

lrc文件格式

[ti:亲爱的小孩]
[ar:苏芮]
[al:亲爱的小孩]
[by:]
[offset:0]
[00:00.38]亲爱的小孩 - 苏芮
[00:01.79]词:杨立德
[00:02.80]曲:陈复明


这是典型的lrc文件样例,其中开头部分,ti、ar、al、by、offset、re、ve等信息分别表示歌名、词作者、专辑名、创建者、时间戳偏移值、创建应用名、版本号。属于歌曲的基本信息。

歌词部分的格式为时间+歌词,时间在中括号内,以分、秒、百分之一秒表示。

regex匹配

对于开头部分基本信息的匹配较为简单,匹配括号及标签即可。

下面介绍匹配歌词正文部分的方法。

首先是从读取的全文中匹配出每一行的内容。(假设输入的lrc文件未分行)下面代码的输入为全文歌词str,输出参数为一个tuple,tuple中的项分别为歌曲开始到此句歌词的百分之一秒数和本句歌词内容。

auto res = [](string str) -> list<tuple<long, string>>
{
list<tuple<long, string>> tuple_res;
const regex pattern("\\[\\d*:\\d{2}\\.\\d{2}\\][^\\[]*");
for (sregex_iterator i = std::sregex_iterator(str.begin(), str.end(), pattern); i != std::sregex_iterator(); ++i)
{
smatch match = *i;
string res = match.str();
string time = res;
time.assign(time.c_str() + 1, time.find(']') - 1);
long milsec = GetTime(time);
string content = res.assign(res.c_str() + res.find(']') + 1);
tuple_res.push_back(make_tuple(milsec, content));
}
return tuple_res;
}(str);


匹配的方式是,首先匹配中括号,中括号里面匹配3个数字,数字中间匹配冒号。中括号结束以后匹配非左中括号(如匹配\w会发生中文无法匹配的问题)。

在成功获取每一行的内容后,匹配每一行中的右中括号,凭借此将该串分割为时间与正文两部分。此匹配过程中匹配字符简单且只匹配一次,可以直接用find函数做。

将时间字符串转为以百分之一秒的数字代表的时间,自己实现GetTime函数,可采用stringstream做类型转换。将其与歌词正文一起加入tuple。

在最后实际播放的时候,设置定时器,到达相应时间,在界面上输出相应语句即可。

示例代码通过VS2015调试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: