LINUX.ORG.RU

компаратор STL map c++


0

0

Посоветуйте плиз как правильно написать компаратор для такой структуры, что бы использовать ее в кач-ве ключа. Преобразование к строке и сравнивание строк работает, но медленно. Никак не могу придумать более быстрый вариант.


struct UNKNOWN{
public:
char date[30];
char time[30];
in_addr ip_from;
int port_from;
in_addr ip_to;
int port_to;
friend bool operator < ( UNKNOWN a, UNKNOWN b ){
char str1[70],str2[70];
sprintf(str1,"%s%s%d%d%d%d",a.date,a.time,a.ip_from.s_addr,a.port_fr om,a.ip_to.s_addr,a.port_to);
sprintf(str2,"%s%s%d%d%d%d",b.date,b.time,b.ip_from.s_addr,b.port_fr om,b.ip_to.s_addr,b.port_to);
return strcmp(str1,str2)<0;

};

struct UNKNOWN_TRAFFIC{
public:
unsigned int bytes;
unsigned int packets;
friend ostream& operator << ( ostream &s, UNKNOWN_TRAFFIC &r ){
s<<r.packets<<" "<<r.bytes;
return s;
}
};

int func(){
UNKNOWN unknown=R;
map.map_unknown[unknown].bytes+=R.bytes;
map.map_unknown[unknown].packets+=R.packets;
}


Ответ на: комментарий от anonymous

ИМХО я просил не критиковать, а помоч/объяснить.

HoBBuT
() автор топика

можно написать что-то вроде этого:
struct UNKOWN {
union {
struct {
unsigned long date;
unsigned long time;
unsigned long ip_from, ip_in;
unsigned long port_from, port_in;
} info;
unsigned long la[0x6];
} u;

friend bool operator < (const UNKOWN &a, const UNKOWN &b)
{
for(int i = 0; i < 6; i ++)
{
if (a.u.la[i] > b.u.la[i])
return false;
if (a.u.la[i] < b.u.la[i])
return true;
}
return false;
}
};

anonymous
()

bool operator < ( UNKNOWN a, UNKNOWN b )
{
  if( a.ip_from < b.ip_from ) return true;
  if( a.port_from < b.port_from ) return true;
  if( a.ip_to < b.ip_to ) return true;
  if( a.port_to < b.port_to ) return true;
  if( strcmp( a.date, b.date ) < 0 ) return true;
  if( strcmp( a.time, b.time ) < 0 ) return true;
  return false;
}

Другой порядок, нежели в приведенном в задании операторе, но за то
меньше сравнений строк. Даже если переставить условия для date и time в
начало, для сохранения заданного порядка сортировки, будет быстрее,
т.к. нет копирований, а тем более жутко медленного форматирования.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

ну так пробовал. правильно так:

friend bool operator < ( const UNKNOWN &a, const UNKNOWN &b){
                return memcmp(&a,&b,sizeof(UNKNOWN))<0;

либо

friend bool operator < ( const ACCOUNT_TIME_IP &a, const ACCOUNT_TIME_IP &b){
                if ( a.ip_from.s_addr < b.ip_from.s_addr )
                        return 1;
                if ( a.ip.from.s_addr > b.ip_from.s_addr )
                        return 0;
                if ( a.port_from < b.port_from )
                        return 1;
                if ( a.port_from > b.port_from )
                        return 0;
                if ( a.ip_to.s_addr < b.ip_to.s_addr )
                        return 1;
                if ( a.ip.to.s_addr > b.ip_to.s_addr )
                        return 0;
                if ( a.port_to < b.to_from )
                        return 1;
                if ( a.port_to > b.port_to )
                        return 0;
                if ( strcmp (a.date, b.date) < 0 )
                        return 1;
                if ( strcmp (a.date, b.date) > 0 )
                        return 0;
                if ( strcmp (a.time, b.time) < 0 )
                        return 1;
                return 0;
}

думаю всем понятно почему

HoBBuT
() автор топика
Ответ на: комментарий от HoBBuT

забыл сказать: по скорости примерно одинаково. но второй случай завиит от сортировки

HoBBuT
() автор топика
Ответ на: комментарий от HoBBuT

1. Зачем сравнения на ">"? Лишние такты процессора? :)

2. Вариант с memcmp будет работать в общем случае неправильно.

3. Возвращать 1/0 вместо true/false --- некрасиво.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

1. Затем что еcли первое поле уже больше, то возвращаем false. И дальше идем только при равенстве полей.
2. Согласен. но при правильно спроектированной структуре будет.
3. Зато 0/1 написать быстрее чем false/true

HoBBuT
() автор топика
Ответ на: комментарий от HoBBuT

> 1. Затем что еcли первое поле уже больше, то возвращаем false. И дальше идем только при равенстве полей.

Да, эт я что-то ступил.

> 2. Согласен. но при правильно спроектированной структуре будет.

Что такое "правильно спроектированная"? Packed что-ли?

> 3. Зато 0/1 написать быстрее чем false/true

Сомнительное преимущество.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

2. Что не будет мусора. если date[30] а используется только 11 '2006-11-01\0' то остальные 19 будет мусор. и работать не будет. Если date[11] и используеются 11 то все будет хорошо. но всеравно memcmp "грязный хак" и так лучше не делать.

3. Кто как привык

HoBBuT
() автор топика
Ответ на: комментарий от HoBBuT

> 1. Затем что еcли первое поле уже больше, то возвращаем false. И дальше идем только при равенстве полей.

Ну и будет у тебя для одних и тех же полей memcmp по два раза вызываться. Нафига?

ero-sennin ★★
()
Ответ на: комментарий от HoBBuT

> Твои предожения?

Переписать код таким образом, чтоб не вызывать memcmp по два раза. :P Или ты ждёшь, пока за тебя другие всё напишут и на блюдечке принесут? :)

ero-sennin ★★
()
Ответ на: комментарий от ero-sennin

Меня все так устраивает. и переписывать ничо не буду, т.к. скорости не добавит. Уже переписал и проверил

HoBBuT
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.