2008-11-13 4 views
1

У меня есть строка tokenize. Форма составляет HHmmssff, где H, m, s, f - цифры.Реверсивный сдвиг tokenizer

Предполагается, что он обозначается четырьмя двузначными числами, но мне также нужно принять короткие формы, например sff, поэтому он интерпретирует его как 00000sff. Я хотел использовать boost::tokenizeroffset_separator, но он работает только с положительными смещениями, и я хотел бы, чтобы он работал в обратном порядке.

Хорошо, одна идея состоит в том, чтобы заполнить строку нулями слева, но, возможно, сообщество придумает что-то uber -smart. ;)

Редактировать:Дополнительные требования только что вступили в игру.

Основная потребность в более разумного решения в том, чтобы обрабатывать все случаи, как f, ssff, mssff и т.д., но и принимать более полное время обозначения, как HH:mm:ss:ff с его короткой стороны, формы, например s:ff или даже s: (этот должен интерпретироваться как s:00).

В случае, когда строка заканчивается на :, я могу, очевидно, поместить ее и с двумя нулями, а затем вычеркнуть все разделители, оставив только цифры и разобрать полученную строку духом.

Но кажется, что было бы немного проще, если бы был способ, с помощью которого токенизатор смещения возвращался из конца строки (смещения -2, -4, -6, -8) и лексически вводил числа до int s.

+0

«Одна идея состоит в том, чтобы набивать строку нулями слева», Простой, быстрый, работает. Зачем искать что-нибудь еще? – 2008-11-13 13:25:54

+0

Не означает, что вы являетесь производителем, но это решение включает в себя некоторое копирование строк (input - это const и std :: string). – macbirdie 2008-11-13 13:41:23

+0

не должно быть проблемой, std :: string обычно достаточно умна, чтобы копировать при записи, так что при добавлении фактически будет стоить только производительность. – 2008-11-13 14:00:11

ответ

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 

Edit: дополнительное ограничение

VerboseNotation = [ [ [ Hours ':' ] Minutes ':' ] Seconds ':' ] Fraction 
0

Регулярные выражения приходят на ум. Что-то вроде "^0*?(\\d?\\d?)(\\d?\\d?)(\\d?\\d?)(\\d?\\d?)$" с boost::regex. Подметки предоставят вам цифры. Не должно быть трудно принять в ваш другой формат двоеточие между номерами (см. Ответ sep61.myopenid.com). boost::regex является одним из самых быстрых парсеров регулярных выражений.

0

В ответ на комментарий «Не значит быть уродцем производительности, но это решение включает в себя некоторое строковое копирование (вход является константой & 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 почти такая же, как и копирование строки в буфер символов с заполнением, поэтому я не ожидал увидеть существенную разницу в производительности.Поэтому я фактически не рекомендую это решение в реальной жизни, как упражнение в преждевременной оптимизации.

Смежные вопросы