После сборки (выполнение команды make в терминале) можно запустить сервис omniNames1, затем сервер и клиент (рисунок 1).
Рисунок 1. Запуск omniNames, сервера и клиента
Response — ответ сервера на запрос клиента:
string HelloWorld(in string message) — клиент отправляет строку message и в ответ получает string (строку).
boolean Div(in long a, in long b, out long r) — клиент отправляет числа a и b, в ответ получает boolean (статус деления — есть ошибка или нет) и число r (результат деления).
void CaesarCipher(inout string str, in short k) — клиент отправляет строку str на редактирование и число k. Функция шифрует строку шифром Цезаря на k позиций.
1 omniNames — это служба именования omniORB для CORBA.
11
Второе задание
Файлы выписки плана нумерации ФАС имеют CSV-формат. Столбцы:
1.Код оператора: 3 цифры;
2.Стартовый номер абонента: 7 цифр;
3.Конечный номер абонента: 7 цифр;
4.Число номеров в диапазоне: целое число;
5.Оператор: строка;
6.Регион: строка.
Пример строки файла: 301;2110000;2129999;20000;ПАО
"Ростелеком";г. Улан-Удэ|Республика Бурятия.
Два наиболее производительных решения (по поиску диапазона по мобильному номеру):
1.Решение с двусторонней очередью и бинарным поиском, поиск за (log2( )), где — число диапазонов (результат тестирования производительности представлен на рисунке 2).
2.Решение с деревом цифр и минимальным масками диапазонов, поиск за ( ), где — количество цифр номера телефона (результат тестирования производительности представлен на рисунке 3).
Рисунок 2. Тестирование версии с двусторонней очередью и бинарным поиском
12
Рисунок 3. Тестирование версии с деревом цифр и минимальным масками диапазонов
Without check results — без проверки номера телефона на корректность.
With check results — с проверкой номера телефона на корректность.
Решение с двусторонней очередью и бинарным поиском состоит из 10
файлов, представленных в таблицах 11-20.
Таблица 11. Файл main.cpp
main.cpp
#include <string> #include <iostream> #include <fstream> #include <filesystem> #include <stdexcept>
#include "lib/mobile_numbers_data.h"
namespace fs = std::filesystem;
std::vector<fs::path> get_files_in_directory(const std::wstring &directory, std::wstring ext)
{
std::vector<fs::path> files_vector;
for (const auto &file : fs::directory_iterator(directory))
{
fs::path filepath = file.path();
if (fs::is_regular_file(filepath) && (ext.empty() || filepath.extension() == ext))
{
files_vector.emplace_back(filepath);
}
}
return files_vector;
}
std::wstring replace(const std::wstring &str, const std::wstring &substr,
const std::wstring &repl_substr)
{
size_t pos = str.find(substr); if (pos != std::wstring::npos)
13
main.cpp
{
return str.substr(0, pos) + repl_substr +
str.substr(pos + substr.size(), std::string::npos);
}
return str;
}
int main(int argc, char *argv[])
{
// set locale (required for wstring) std::locale::global(std::locale("C.UTF-8"));
//check args if (argc != 2)
{
std::wcout << "Use: ./main {mobile_number}" << std::endl; return 1;
}
//check mobile number
std::string mobile_number(argv[1]);
if (!MobileNumbersData::is_mobile_number(mobile_number))
{
std::wcout << "Invalid mobile number format." << std::endl; return 2;
}
// get csv files in current directory
std::vector<fs::path> files_vector = get_files_in_directory(L"./", L".csv"); if (files_vector.empty())
{
std::wcout << "CSV files not found." << std::endl; return 3;
}
try
{
MobileNumbersData mobile_numbers_data; for (const auto &file : files_vector)
{
std::wifstream wstream(file); if (!wstream.is_open())
{
std::wcout << "File \"" << file.wstring() << "\" skipped (open error)." << std::endl; continue;
}
mobile_numbers_data.add_data(wstream);
}
auto range = mobile_numbers_data.find_with_check(mobile_number); auto mobile_operator = range.operator_name();
auto region = range.region();
region = replace(region, L";", L", "); region = replace(region, L"|", L", ");
std::wcout << mobile_operator << ", " << region << std::endl;
}
catch (const std::exception &e)
{
std::wcout << e.what() << std::endl; return 4;
}
return 0;
}
Таблица 12. Файл test.cpp
test.cpp
#include <string> #include <iostream> #include <fstream> #include <filesystem> #include <stdexcept> #include <chrono>
#include "lib/mobile_numbers_data.h"
namespace fs = std::filesystem;
14
test.cpp
//Get the current time in seconds
//This function should be used only for measuring time
//(first call, algorithm, second call; then the difference between the values) #if defined(_WIN32)
#include <Windows.h> double get_proc_time()
{
FILETIME createTime, exitTime, kernelTime, userTime;
if (GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime) != -1) return (ULARGE_INTEGER{{userTime.dwLowDateTime, userTime.dwHighDateTime}}).QuadPart /
10000000.L; return 0;
}
#else
double get_proc_time()
{
return static_cast<double>(clock()) / CLOCKS_PER_SEC;
}
#endif
std::vector<fs::path> get_files_in_directory(const std::wstring &directory, std::wstring ext)
{
std::vector<fs::path> files_vector;
for (const auto &file : fs::directory_iterator(directory))
{
fs::path filepath = file.path();
if (fs::is_regular_file(filepath) && (ext.empty() || filepath.extension() == ext))
{
files_vector.emplace_back(filepath);
}
}
return files_vector;
}
std::wstring replace(const std::wstring &str,
const std::wstring &substr_from, const std::wstring &substr_to)
{
size_t pos = str.find(substr_from); if (pos != std::wstring::npos)
{
return str.substr(0, pos) + substr_to +
str.substr(pos + substr_from.size(), std::string::npos);
}
return str;
}
int main(int argc, char *argv[])
{
//set locale (required for wstring) std::locale::global(std::locale("C.UTF-8"));
//check args
if (argc != 2)
{
std::wcout << "Use: ./test {number of tests}" << std::endl; return 1;
}
int n_tests = 0; try
{
n_tests = std::atoi(argv[1]); if (n_tests <= 0)
{
throw std::invalid_argument("Arg {number of tests} is non-positive number.");
}
}
catch (const std::exception &e)
{
std::wcout << e.what() << std::endl; return 2;
}
15