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调试。
相关文章推荐
- 【C++探索之旅】开宗明义+第一部分第一课:什么是C++?
- 【C++探索之旅】开宗明义+第一部分第一课:什么是C++?
- NotePad++与MinGw的第一次HelloWorld——C语言环境配置说明
- vs2013出现ISO C++ conformant解决办法
- C++静态变量对象的建立和删除,兼论MFC开始运行的起点(全局对象)
- C++字符串转化为数字的库函数
- mystring c++ 自己的string 封装
- c++关于结尾遇到‘\n’或其他特殊字符结束读取的问题(个人总结,大神勿喷)
- C++面试宝典(整理版)3
- Effective C++条款07解读:为多态基类声明virtual析构函数 (某公司招聘面试试题)
- 用Natvis定制C++对象在Visual Studio调试时如何显示
- 【学习笔记】【C语言】变量的内存分析
- 《Effective C++》学习笔记——条款32
- [转]100个经典C语言程序(益智类问题)
- C++--何时需要定义赋值/复制构造函数
- 树的简单c语言实现(先中后序遍历)
- chapter13test3
- Effective C++条款06解读 : 若不想使用编译器自动生成的函数, 就应该明确拒绝
- C++标准库学习笔记(Weak Pointer)-4
- 顺序队列的c++实现