Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions filter_helper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "filter_helper.h"
#include <cstring>
#include <algorithm>
#include <tuple>

namespace filtering {

std::string getIp(const std::vector<std::string> & input)
{
std::string rIpStr;

rIpStr.append(input.at(0));

for(std::vector<std::string>::const_iterator ip_part = input.cbegin() + 1; ip_part != input.cend(); ++ip_part)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Красивее сделать объявление ip_part через auto:
for(auto ip_part = input.cbegin() + 1; ip_part != input.cend(); ++ip_part)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

или через range for:
for (const auto& ip_part: input)

{
rIpStr.push_back('.');
rIpStr.append(*ip_part);
}

return rIpStr;
}

void showList(const addressList& input)
{
for (auto & ip: input)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь и далее правильнее и безопаснее пользоваться квалификатором const.
for (const auto & ip: input).

std::cout << getIp(ip) << std::endl;
}

std::vector<std::string> filter(const addressList& input, const char *byte1, const char *byte2)
{
std::vector<std::string> rVecStr;
for (auto & ip: input)
{
if(byte2)
{
if ((std::strcmp(ip.at(0).c_str(), byte1) != 0) || (std::strcmp(ip.at(1).c_str(), byte2) != 0))
continue;
}
else
{
if(std::strcmp(ip.at(0).c_str(), byte1) != 0)
continue;
}

std::string suitableIp = getIp(ip);
rVecStr.push_back(suitableIp);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь и далее код:

std::string suitableIp = getIp(ip);
rVecStr.push_back(suitableIp);

можно написать более оптимально:
rVecStr.emplace_back(getIp(ip));

}
return rVecStr;
}

std::vector<std::string> filter_any(const addressList& input, const char *byte1)
{
std::vector<std::string> rVecStr;
for (auto & ip: input)
{
bool isByteFounded = false;
for (auto& ip_part: ip)
{
if (std::strcmp(ip_part.c_str(), byte1) == 0) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

хранить и сравнивать строки очень неэффективно, когда речь идёт о простых числах.
стоило рассмотреть хранение октетов в integral типе

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

с другой стороны, если все же сравнивается std::string и const char *, то можно сравнить напрямую, без strcmp

isByteFounded = true;
break;
}
}

if (isByteFounded)
{
std::string foundedIp = getIp(ip);
rVecStr.push_back(foundedIp);
}
}
return rVecStr;
}

bool ip_compare(const std::string& lhs, const std::string& rhs)
{
if(lhs.size() == rhs.size())
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

исп-е lexicompare - здорово

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

но что будет, если сравнить
1.111.1.1 и 1.11.111.1?

}
else
{
return lhs.size() < rhs.size();
}
}

void lexicographRevSort(addressList& input)
{
std::sort(input.rbegin(), input.rend(),[](const std::vector<std::string> & lhs,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Самописную лямбду можно заменить на std::greater<>.

const std::vector<std::string>& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), ip_compare);
});
}

}


14 changes: 14 additions & 0 deletions filter_helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <iostream>
#include <vector>
#include <string>

namespace filtering {

using addressList = std::vector<std::vector<std::string>>;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По тексту много где повторяется std::vectorstd::string
Предлагаю ввести алиас через using этого типа.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это общепринято. Если есть какой-то алиас на типы из STL, то при чтении кода можно увидеть какой-нибудь vector и придется идти и разбираться что это за вектор, стандартный или нет.

void lexicographRevSort(addressList& input);
std::string getIp(const std::vector<std::string> & input);
void showList(const addressList& input);
std::vector<std::string> filter(const addressList& input, const char* byte1, const char* byte2 = nullptr);
std::vector<std::string> filter_any(const addressList& input, const char* byte1);
}
131 changes: 131 additions & 0 deletions ip_filter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// lesson_3.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <tuple>
#include <stdexcept>
#include "filter_helper.h"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лишние инклуды

// ("", '.') -> [""]
// ("11", '.') -> ["11"]
// ("..", '.') -> ["", "", ""]
// ("11.", '.') -> ["11", ""]
// (".11", '.') -> ["", "11"]
// ("11.22", '.') -> ["11", "22"]
std::vector<std::string> split(const std::string &str, char d)
{
std::vector<std::string> r;

std::string::size_type start = 0;
std::string::size_type stop = str.find_first_of(d);
while (stop != std::string::npos)
{
r.push_back(str.substr(start, stop - start));

start = stop + 1;
stop = str.find_first_of(d, start);
}

r.push_back(str.substr(start));

return r;
}

int main(int argc, char const *argv[])
{
try
{
std::vector<std::vector<std::string> > ip_pool;

for (std::string line; std::getline(std::cin, line);)
{
std::vector<std::string> v = split(line, '\t');
ip_pool.push_back(split(v.at(0), '.'));
}

//reverse lexicographically sort
filtering::lexicographRevSort(ip_pool);
filtering::showList(ip_pool);

// filter by first byte and output
for(auto& ip: filtering::filter(ip_pool, "1"))
std::cout << ip << std::endl;

// TODO filter by first and second bytes and output
for(auto& ip: filtering::filter(ip_pool, "46", "70"))
std::cout << ip << std::endl;

// TODO filter by any byte and output
for(auto& ip: filtering::filter_any(ip_pool, "46"))
std::cout << ip << std::endl;

// 222.173.235.246
// 222.130.177.64
// 222.82.198.61
// ...
// 1.70.44.170
// 1.29.168.152
// 1.1.234.8


// ip = filter(1)

// 1.231.69.33
// 1.87.203.225
// 1.70.44.170
// 1.29.168.152
// 1.1.234.8

// TODO filter by first and second bytes and output
// ip = filter(46, 70)

// 46.70.225.39
// 46.70.147.26
// 46.70.113.73
// 46.70.29.76

// TODO filter by any byte and output
// ip = filter_any(46)

// 186.204.34.46
// 186.46.222.194
// 185.46.87.231
// 185.46.86.132
// 185.46.86.131
// 185.46.86.131
// 185.46.86.22
// 185.46.85.204
// 185.46.85.78
// 68.46.218.208
// 46.251.197.23
// 46.223.254.56
// 46.223.254.56
// 46.182.19.219
// 46.161.63.66
// 46.161.61.51
// 46.161.60.92
// 46.161.60.35
// 46.161.58.202
// 46.161.56.241
// 46.161.56.203
// 46.161.56.174
// 46.161.56.106
// 46.161.56.106
// 46.101.163.119
// 46.101.127.145
// 46.70.225.39
// 46.70.147.26
// 46.70.113.73
// 46.70.29.76
// 46.55.46.98
// 46.49.43.85
// 39.46.86.85
// 5.189.203.46
}
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
55 changes: 55 additions & 0 deletions ip_filter_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "filter_helper.h"

#define BOOST_TEST_MODULE test_main

#include <boost/test/unit_test.hpp>

using namespace filtering;
BOOST_AUTO_TEST_SUITE(test_suite_main)
static std::vector<std::vector<std::string> > ip_pool { { "1", "10", "2", "1" },
{ "1", "2", "3", "4" },
{ "1", "2", "6", "1" },
{ "70", "2", "6", "1" },
{ "46", "70", "6", "1" },
{ "46", "128", "6", "1" },
{ "168", "56", "46", "1" }};
BOOST_AUTO_TEST_CASE(check_proper_sorting)
{
lexicographRevSort(ip_pool);

BOOST_CHECK_MESSAGE( getIp(ip_pool.at(0)) == "168.56.46.1", "actual value: " << getIp(ip_pool.at(0)) );
BOOST_CHECK_MESSAGE( getIp(ip_pool.at(1)) == "70.2.6.1", "actual value: " << getIp(ip_pool.at(1)) );
BOOST_CHECK_MESSAGE( getIp(ip_pool.at(2)) == "46.128.6.1", "actual value: " << getIp(ip_pool.at(2)) );
BOOST_CHECK_MESSAGE( getIp(ip_pool.at(3)) == "46.70.6.1", "actual value: " << getIp(ip_pool.at(3)) );
BOOST_CHECK_MESSAGE( getIp(ip_pool.at(4)) == "1.10.2.1", "actual value: " << getIp(ip_pool.at(4)) );
BOOST_CHECK_MESSAGE( getIp(ip_pool.at(5)) == "1.2.6.1", "actual value: " << getIp(ip_pool.at(5)) );
BOOST_CHECK_MESSAGE( getIp(ip_pool.at(6)) == "1.2.3.4", "actual value: " << getIp(ip_pool.at(6)) );
}

BOOST_AUTO_TEST_CASE(check_filter_valid)
{
std::vector<std::string> result = filter(ip_pool, "1");

BOOST_CHECK_MESSAGE( result.size() == 3, "result.size(): " << result.size());
BOOST_CHECK_MESSAGE( result.at(0) == "1.10.2.1", "result.at(0):" << result.at(0));
BOOST_CHECK_MESSAGE( result.at(1) == "1.2.6.1", "result.at(1):" << result.at(1));
BOOST_CHECK_MESSAGE( result.at(2) == "1.2.3.4", "result.at(2):" << result.at(2));

result.clear();
result = filter(ip_pool, "46", "70");

BOOST_CHECK_MESSAGE( result.size() == 1, "result.size(): " << result.size());
BOOST_CHECK_MESSAGE( result.at(0) == "46.70.6.1", "result.at(0):" << result.at(0));
}

BOOST_AUTO_TEST_CASE(check_filter_any_valid)
{
std::vector<std::string> result = filter_any(ip_pool, "46");

BOOST_CHECK_MESSAGE( result.size() == 3, "result.size(): " << result.size());
BOOST_CHECK_MESSAGE( result.at(0) == "168.56.46.1", "result.at(0):" << result.at(0));
BOOST_CHECK_MESSAGE( result.at(1) == "46.128.6.1", "result.at(1):" << result.at(1));
BOOST_CHECK_MESSAGE( result.at(2) == "46.70.6.1", "result.at(2):" << result.at(2));
}

BOOST_AUTO_TEST_SUITE_END()