С++ отсортировать IP адреса в обратном лексикографическом порядке

Рейтинг: 0Ответов: 1Опубликовано: 06.07.2023

Мне нужно сравнить список ip-адресов и отсортировать их в обратном лексикографическом порядке.

Пример лексикографической сортировки (по первому байту, затем по второму и так далее):

  • 1.1.1.1
  • 1.2.1.1
  • 1.10.1.1

Соответственно, обратная:

  • 1.10.1.1
  • 1.2.1.1
  • 1.1.1.1

Как написать компаратор для сравнения адресов в таком порядке, если структура данных для хранения IP-адреса - обычный int, то есть октеты упакованы в int и хранятся в байтах целого числа:

using ip = int;
using ip_pool = std::vector<ip>;

ip make_ip(const std::vector<std::string>& splitted)
{
    validate_ip(splitted);

    int _3 = std::stoi(splitted[0]);
    int _2 = std::stoi(splitted[1]);
    int _1 = std::stoi(splitted[2]);
    int _0 = std::stoi(splitted[3]);

    return _3 << 24 | _2 << 16 | _1 << 8 | _0;
}

КОмпаратор у меня пока такой, но почему-то он сортирует адреса неправильно: весь пул адресов поделился на две части, каждая из которых отсортирована в обратном лексикографияеском порядке, но не являются последовательными. Почему так? Как сделать правильно?

void sort_lexicographically(ip_pool& pool)
{
    std::sort(pool.begin(), pool.end(), std::greater<int>());

    /*std::sort(pool.begin(), pool.end(), [](const int& lhs, const int& rhs) {
        return ((lhs >> 24 & 0xFF) > (rhs >> 24 & 0xFF) &&
                (lhs >> 16 & 0xFF) > (rhs >> 16 & 0xFF) &&
                (lhs >>  8 & 0xFF) > (rhs >>  8 & 0xFF) &&
                (lhs & 0xFF) > (rhs & 0xFF));
    });*/
}

Адреса разделились по такой линии

1.231.69.33
1.87.203.225
1.70.44.170
1.29.168.152
1.1.234.8
222.173.235.246
222.130.177.64
222.82.198.61
222.42.146.225
220.189.194.162

Ответы

▲ 2Принят
void out(const vector<unsigned int>& ips)
{
    for(unsigned int s: ips)
        cout
            << ((s>>24)&0xFF) << "."
            << ((s>>16)&0xFF) << "."
            << ((s>>8)&0xFF) << "."
            << (s&0xFF) << endl;
}

int main(int argc, char * argv[])
{
    random_device rd;
    mt19937 gen(rd());
    uniform_int_distribution<unsigned int> distrib(0,0xFFFFFFFF);
    vector<unsigned int> ips;
    for(int i = 0; i < 20; ++i) ips.push_back(distrib(gen));

    out(ips);
    cout << "--------------\n";
    sort(ips.begin(),ips.end(), greater<unsigned int>());
    out(ips);
}

См. https://gcc.godbolt.org/z/K5E9ff4Tf

Если у вас октеты в обратном порядке, допишите разворот, например, как тут...