Здравствуйте, 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