Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  

Показать сообщение отдельно
pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Можно сделать угадывалку (по типу угадывалки кодировки в Total Commander) примерно так:
Код: Выделить весь код
#include <vector>
using namespace std;

class GuessDateFormat
{
public:
    enum state_t {
        state_ready, // угадал
        state_not_enough, // есть неоднозначности, не хватает примеров
        state_umbiguity // противоречивые примеры
    };

    GuessDateFormat();
    void add_sample(const char* date_str);
    state_t state() const;
    bool convert(const char* from, time_t& to);

private:
    enum {
            like_nothing = 0x0000,  // битовые поля "похоже на..."
            like_year = 0x0001,
            like_mon  = 0x0002,
            like_mday = 0x0004,
            like_wday = 0x0008,
            like_hour = 0x0010,
            like_min  = 0x0020,
            like_sec  = 0x0040,
            like_pm   = 0x0080,    // pm/am
            like_amon = 0x0100,    // месяц прописью
            like_date = like_year|like_mon|like_mday|like_amon,
            like_time = like_hour|like_min|like_sec,
            like_alpha = like_amon|like_pm,
            like_everything = 0x01ff,

            got_pm          = 0x01,
            got_year2000    = 0x02,
            got_amon        = 0x04
    };

    vector<short> _like_what; // каждый элемент показывает, на что похоже содержимое позиции
    short _its_clear, _expecting; // какие элементы точно выяснены

    void _suspecting_one(int);
    void _suspecting_pair(int);
};

bool GuessDateFormat::convert(const char* from, time_t& to)
{
    typedef struct tm tm_t;
    tm_t tm1 = {};

    vector<short>::iterator first=_like_what.begin(), last=_like_what.end();

    while ( *from && first!=last)
    {
        // найти первый подходящий символ
        while (!isalnum(*from) && *++from) {}

        if (*from)
        {
            switch ( *first)
            {
                case like_year :
                    tm1.tm_year = atoi(from);
                    break;

                case like_mon :
                    tm1.tm_mday = atoi(from)-1;
                    break;

                case like_mday :
                    tm1.tm_mday = atoi(from);
                    break;

                case like_hour :
                    tm1.tm_hour = atoi(from);
                    break;

                case like_min :
                    tm1.tm_min = atoi(from);
                    break;

                case like_sec :
                    tm1.tm_sec = atoi(from);
                    break;

                case like_pm :
                    // думаем что PM после времени пишется.
                    if (*from=='P') tm1.tm_hour += 12;
                    break;

                case like_amon :
                    // выбрать месяц из справочника
                    break;
            }
        }

        while (isalnum(*from) && *++from) {}
    }

    to = mktime(&tm1);
    return true;
}

GuessDateFormat::state_t GuessDateFormat::state() const
{
    for (vector<short>::iterator first=_like_what.begin(),
            last=_like_what.end(); first!=last; ++first)
    {
        short n = *first;
        if (!n) return state_umbiguity;
        while ( !(n & 1)) n>>=1;
        if (n & (~1)) return state_not_enough;
    }

    return state_ready;
}

void GuessDateFormat::_suspecting_one(int bitset)
{
    _like_what.push_back(bitset & _expecting);
    _expecting = like_everything;
}

void GuessDateFormat::_suspecting_pair(int bitset)
{
    if (!_like_what.empty()) *(_like_what.end()-1) &= bitset;
    _expecting = bitset;
}

bool GuessDateFormat::add_sample(const char* date_str)
{
    // отмели простейший случай
    if (!date_str || !*date_str) return false;

    _expecting = like_everything;
    _its_clear = 0;

    do
    {
        short suspecting = _expecting;

        // пропустили пробелы
        while (*date_str && isspace(*date_str)) ++date_str;
        if ( !*date_str) break;

        if (isalpha(*date_str))
        {
            suspecting &= like_alpha;

            if (date_str[1]=='M' && (date_str[0]=='A' || date_str[0]=='P'))
            {
                suspecting &= like_pm;
                _its_clear |= got_pm;
            }
            else {
                suspecting &= ~like_pm;
                _its_clear |= got_amon;
            }

            _suspecting_one(suspecting);
        }
        else if (isdigit(*date_str))
        {
            suspecting &= ~like_alpha;

            // проверяем границы
            int value = atoi(date_str);
            do {++date_str;} while (*date_str && isdigit(*date_str));

            if (12 < value)
            {
                suspecting &= ~like_mon;
                if (_its_clear & got_am) suspecting &= ~like_hour;

                if (23 < value)
                {
                    suspecting &= ~like_hour;

                    if (31 < value)
                    {
                        suspecting &= ~(like_mon|like_mday);

                        if (59 < value)
                        {
                            suspecting &= like_year;
                            _its_clear |= got_year2000;
                        }
                    }
                }
            }

            if ( (_its_clear & got_year2000) && value < 60)
            {
                suspecting &= ~like_year;
            }

            if (_its_clear & got_amon)
            {
                suspecting &= ~like_mon;
            }

            _suspecting_one(suspecting);
        }
        else
        {
            switch (*date_str)
            {
                case '/' :
                case '.' :
                case '-' :
                    _suspecting_pair(like_date);
                    break;

                case ':' :
                    _suspecting_pair(like_time);
                    break;
            }
        }
    }
    while (*date_str);
}
//----------------------------------------
как пользоваться:
1) создали
GuessDateFormat guess_format;
2) скидали в него все даты, какие есть
for(...) guess_format.add_sample(date[n].c_str());
3) проверили, угадался ли формат
if (guess_format.state()==GuessDateFormat::state_ready)
4) переводим даты
time_t t1;
for(...) guess_format.convert(date[n].c_str(), t1);

чего в коде нет:
1) таблицы соответсвия месяц-номер месяца (на всех языках, со всеми сокращениями)
2) не может отличить минуты от секунд. Чтобы это обойти, надо внутри добавить код: пробежаться по вектору с подозрениями и если встретится элемент времени, то последовательно обозначить час, минута, секунда.
Это сообщение посчитали полезным следующие участники:

Отправлено: 20:35, 20-07-2010 | #2