Re: Наколенный вариант 8-летней давности
От: McSeem2 США http://www.antigrain.com
Дата: 20.09.06 18:06
Оценка: :)
Здравствуйте, Denis2005, Вы писали:

D>Компилятор: MS VC 8.0

D>Время работы: 20 секунд. (и это при полной оптимизации и отключенными проверками !?!)

D>Код на C#, .NET Framework:

D>Время работы: ~1 сек, при 10^7 итераций ~6 сек.


#include <stdio.h>
#include <string.h>
#include <time.h>

class tokenizer
{
public:
    enum sep_flag
    {
        single,
        multiple,
        whole_str
    };

    struct token
    {
        const char* ptr;
        unsigned    len;
    };

    tokenizer(const char* sep, 
              const char* trim=0,
              const char* quote="\"",
              char mask_chr='\\',
              sep_flag sf=multiple);

    void set_str(const char* str)
    {
        m_src_string = str; 
        m_start = 0;
    }

    token next_token();

private:
    
    // This function should actually be a template parameter
    static int check_chr(const char *str, char chr)
    {
        return chr == ' ';//int(strchr(str, chr));
    }

private:
    const char* m_src_string;
    int         m_start;
    const char* m_sep;
    const char* m_trim;
    const char* m_quote;
    char        m_mask_chr;
    unsigned    m_sep_len;
    sep_flag    m_sep_flag;
};

//-----------------------------------------------------------------------
tokenizer::tokenizer(const char* sep, 
                     const char* trim,
                     const char* quote,
                     char mask_chr,
                     sep_flag sf) :
    m_src_string(0),
    m_start(0),
    m_sep(sep),
    m_trim(trim),
    m_quote(quote),
    m_mask_chr(mask_chr),
    m_sep_len(sep ? strlen(sep) : 0),
    m_sep_flag(sep ? sf : single)
{
}


//-----------------------------------------------------------------------
tokenizer::token tokenizer::next_token()
{
    unsigned count = 0;
    char quote_chr = 0;
    token tok;

    tok.ptr = 0;
    tok.len = 0;
    if(m_src_string == 0 || m_start == -1) return tok;

    register const char *pstr = m_src_string + m_start;

    if(*pstr == 0) 
    {
        m_start = -1;
        return tok;
    }

    int sep_len = 1;
    if(m_sep_flag == whole_str) sep_len = m_sep_len;

    if(m_sep_flag == multiple)
    {
        while(*pstr && check_chr(m_sep, *pstr)) 
        {
            ++pstr;
            ++m_start;
        }
    }

    if(*pstr == 0) 
    {
        m_start = -1;
        return tok;
    }

    for(count = 0;; ++count) 
    {
        char c = *pstr;
        int found = 0;

        if(quote_chr == 0)
        {
            if(sep_len == 1)
            {
                found = check_chr(m_sep, c);
            }
            else
            {
                found = strncmp(m_sep, pstr, m_sep_len) == 0; 
            }
        }

        ++pstr;

        if(c == 0 || found) 
        {
            if(m_trim)
            {
                while(count && 
                        check_chr(m_trim, m_src_string[m_start]))
                {
                    ++m_start;
                    --count;
                }

                while(count && 
                        check_chr(m_trim, m_src_string[m_start + count - 1]))
                {
                    --count;
                }
            }

            tok.ptr = m_src_string + m_start;
            tok.len = count;

            m_start += count;
            if(c) 
            {
                m_start += sep_len;
                if(m_sep_flag == multiple)
                {
                    while(check_chr(m_sep, m_src_string[m_start])) 
                    {
                        ++m_start;
                    }
                }
            }
            break;
        }

        if(quote_chr == 0)
        {
            if(check_chr(m_quote, c)) 
            {
                quote_chr = c;
                continue;
            }
        }
        else
        {
            if(m_mask_chr && c == m_mask_chr)
            {
                if(*pstr) 
                {
                    ++count;
                    ++pstr;
                }
                continue; 
            }
            if(c == quote_chr) 
            {
                quote_chr = 0;
                continue;
            }
        }
    }
    return tok;
}


int main()
{
    tokenizer tokens(" ", "", "", 0, tokenizer::multiple);
    char dst[100];

    double tm1 = clock();
    for(int i = 0; i < 1000000; ++i)
    {
        tokens.set_str("123 345 asdf 23453 asdfas");
        for(;;)
        {
            tokenizer::token tok = tokens.next_token();
            if(tok.ptr == 0) break;
            if(tok.len)
            {
                // ATTN: DON'T DO THAT! Use std::vector<std::string> instead
                memcpy(dst, tok.ptr, tok.len); 
                dst[tok.len] = 0;
            }
        }
    }
    double tm2 = (clock() - tm1) / CLOCKS_PER_SEC;
    printf("%f\n", tm2);

    return 0;
}


Время: 0.328

IBM Thinkpad T43, Intel Centrino 2GHz
VC7.1
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.