1

我有一个要标记的字符串。它的形式是HHmmssff, H, m,sf数字。

它应该被标记为四个 2 位数字,但我需要它也接受速记形式,就像sff它解释为00000sff. 我想使用boost::tokenizer'soffset_separator但它似乎只适用于正偏移量,我想让它向后工作。

好的,一个想法是从左边用零填充字符串,但也许社区想出了一些超级智能的东西。;)

编辑: 其他要求刚刚开始发挥作用。

更智能的解决方案的基本需求是处理所有情况,如f, ssff,mssff等,但也接受更完整的时间符号,HH:mm:ss:ff如其速记形式,例如s:ff,甚至s:(这应该被解释为s:00)。

在字符串以结尾的情况下,:我显然也可以用两个零填充它,然后去掉所有分隔符,只留下数字并用精神解析结果字符串。

int但是,如果有一种方法可以使偏移标记器从字符串的末尾返回(偏移量 -2、-4、-6、-8)并将数字转换为s ,这似乎会更简单一些。

4

3 回答 3

1

我一直在宣扬 BNF 符号。如果您可以写下定义问题的语法,您可以轻松地将其转换为 Boost.Spirit 解析器,它会为您完成。

TimeString := LongNotation | ShortNotation

LongNotation := Hours Minutes Seconds Fractions

Hours := digit digit
Minutes := digit digit
Seconds := digit digit
Fraction := digit digit

ShortNotation := ShortSeconds Fraction
ShortSeconds := digit

编辑:附加约束

VerboseNotation = [ [ [ Hours ':' ] Minutes ':' ] Seconds ':' ]  Fraction
于 2008-11-13T13:56:25.080 回答
0

回应评论“不意味着要成为性能怪胎,但此解决方案涉及一些字符串复制(输入是 const & std::string)”。

如果您真的非常关心性能以至于不能使用像正则表达式这样的大型旧库,则不会冒险使用 BNF 解析器,也不想假设 std::string::substr 会避免使用分配的副本(因此不能使用 STL 字符串函数),甚至不能将字符串字符复制到缓冲区和带有 '0' 字符的左填充:

void parse(const string &s) {
    string::const_iterator current = s.begin();
    int HH = 0;
    int mm = 0;
    int ss = 0;
    int ff = 0;
    switch(s.size()) {
        case 8:
            HH = (*(current++) - '0') * 10;
        case 7:
            HH += (*(current++) - '0');
        case 6:
            mm = (*(current++) - '0') * 10;
        // ... you get the idea.
        case 1:
            ff += (*current - '0');
        case 0: break;
        default: throw logic_error("invalid date");
        // except that this code goes so badly wrong if the input isn't
        // valid that there's not much point objecting to the length...
   }
}

但从根本上说,仅 0 初始化这些 int 变量几乎与将字符串复制到带有填充的 char 缓冲区一样多,因此我不希望看到任何显着的性能差异。因此,我实际上并不在现实生活中推荐这种解决方案,只是作为过早优化的练习。

于 2008-11-13T14:20:26.920 回答
0

正则表达式浮现在脑海。"^0*?(\\d?\\d?)(\\d?\\d?)(\\d?\\d?)(\\d?\\d?)$"类似的东西boost::regex。子匹配将为您提供数字值。采用数字之间带有冒号的其他格式应该不难(请参阅 sep61.myopenid.com 的答案)。boost::regex是最快的正则表达式解析器之一。

于 2008-11-13T13:56:56.173 回答