Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Неделин Дмитрий - Лабораторная работа №3 #413

Merged
merged 11 commits into from
Dec 2, 2024
Merged
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
20 changes: 20 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Declare variables for binaries' names
get_filename_component(DIR_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
set(MODULE "${DIR_NAME}")
set(LIBRARY "lib_${MODULE}")
set(TESTS "test_${MODULE}")
set(APPLICATION "app_${MODULE}")

# Include directory with public headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# Add all submodules
add_subdirectory(src)
add_subdirectory(test)
add_subdirectory(application)

#############################################
##### Testing
#############################################

include("CTestTests.txt")
97 changes: 97 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/CTestTests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#############################################
##### Testing
#############################################

set(prefix "${MODULE}")

add_test(
NAME ${prefix}_convert_zero
COMMAND ${APPLICATION} "0"
)
set_tests_properties(${prefix}_convert_zero PROPERTIES
PASS_REGULAR_EXPRESSION "zero"
LABELS "${MODULE}"
)

add_test(
NAME ${prefix}_convert_one
COMMAND ${APPLICATION} "1"
)
set_tests_properties(${prefix}_convert_one PROPERTIES
PASS_REGULAR_EXPRESSION "one"
LABELS "${MODULE}"
)

add_test(
NAME ${prefix}_convert_negative
COMMAND ${APPLICATION} "-123"
)
set_tests_properties(${prefix}_convert_negative PROPERTIES
PASS_REGULAR_EXPRESSION "negative one hundred twenty three"
LABELS "${MODULE}"
)

add_test(
NAME ${prefix}_convert_large_number
COMMAND ${APPLICATION} "1000000"
)
set_tests_properties(${prefix}_convert_large_number PROPERTIES
PASS_REGULAR_EXPRESSION "one million"
LABELS "${MODULE}"
)

add_test(
NAME ${prefix}_convert_edge_case_twenty
COMMAND ${APPLICATION} "20"
)
set_tests_properties(${prefix}_convert_edge_case_twenty PROPERTIES
PASS_REGULAR_EXPRESSION "twenty"
LABELS "${MODULE}"
)

# Тесты для ошибок и невалидных вводов
add_test(
NAME ${prefix}_invalid_input
COMMAND ${APPLICATION} "abc"
)
set_tests_properties(${prefix}_invalid_input PROPERTIES
PASS_REGULAR_EXPRESSION "Invalid number format!"
LABELS "${MODULE}"
)

add_test(
NAME ${prefix}_missing_argument
COMMAND ${APPLICATION}
)
set_tests_properties(${prefix}_missing_argument PROPERTIES
PASS_REGULAR_EXPRESSION "Usage: number_to_words <number>"
LABELS "${MODULE}"
)

add_test(
NAME ${prefix}_extra_argument
COMMAND ${APPLICATION} "123" "456"
)
set_tests_properties(${prefix}_extra_argument PROPERTIES
PASS_REGULAR_EXPRESSION "Usage: number_to_words <number>"
LABELS "${MODULE}"
)

# Граничные значения
add_test(
NAME ${prefix}_convert_min_int
COMMAND ${APPLICATION} "-2147483648"
)
set_tests_properties(${prefix}_convert_min_int PROPERTIES
PASS_REGULAR_EXPRESSION "negative two billion one hundred forty seven million four hundred eighty three thousand six hundred forty eight"
LABELS "${MODULE}"
)

add_test(
NAME ${prefix}_convert_max_int
COMMAND ${APPLICATION} "2147483647"
)
set_tests_properties(${prefix}_convert_max_int PROPERTIES
PASS_REGULAR_EXPRESSION "two billion one hundred forty seven million four hundred eighty three thousand six hundred forty seven"
LABELS "${MODULE}"
)
14 changes: 14 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/application/Application.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2024 Nedelin Dmitry

#include <iostream>

#include "include/number_to_wordsApp.h"

int main(int argc, const char** argv) {
Application app;
auto output = app.runApp(argc, argv);
for (auto str : output) {
std::cout << str << std::endl;
}
return 0;
}
15 changes: 15 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/application/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
set(target ${APPLICATION})

file(GLOB srcs "*.cpp")
set_source_files_properties(${srcs} PROPERTIES
LABELS "${MODULE};Application")

add_executable(${target} ${srcs})
set_target_properties(${target} PROPERTIES
OUTPUT_NAME ${MODULE}
LABELS "${MODULE};Application")

target_link_libraries(${target} ${LIBRARY})
if (UNIX)
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
endif (UNIX)
16 changes: 16 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/include/number_to_words.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2024 Nedelin Dmitry

#ifndef MODULES_NEDELIN_D_NUMBER_TO_WORDS_LAB3_INCLUDE_NUMBER_TO_WORDS_H_
#define MODULES_NEDELIN_D_NUMBER_TO_WORDS_LAB3_INCLUDE_NUMBER_TO_WORDS_H_

#include <string>

class NumberToWords {
public:
std::string convert(int number);

private:
std::string convertLessThanOneThousand(int number);
};

#endif // MODULES_NEDELIN_D_NUMBER_TO_WORDS_LAB3_INCLUDE_NUMBER_TO_WORDS_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2024 Nedelin Dmitry

#ifndef MODULES_NEDELIN_D_NUMBER_TO_WORDS_LAB3_INCLUDE_NUMBER_TO_WORDSAPP_H_
#define MODULES_NEDELIN_D_NUMBER_TO_WORDS_LAB3_INCLUDE_NUMBER_TO_WORDSAPP_H_

#include <string>
#include <vector>

class Application{
public:
std::vector<std::string> runApp(int argc, const char** argv);

private:
std::string processNumber(const std::string& input);
};

#endif // MODULES_NEDELIN_D_NUMBER_TO_WORDS_LAB3_INCLUDE_NUMBER_TO_WORDSAPP_H_
18 changes: 18 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
set(target ${LIBRARY})

file(GLOB srcs "*.cpp")
file(GLOB hdrs "../include/*.h")
set_source_files_properties(${srcs} ${hdrs} PROPERTIES
LABELS "${MODULE};Library")

add_library(${target} STATIC ${srcs} ${hdrs})
set_target_properties(${target} PROPERTIES
OUTPUT_NAME ${MODULE}
LABELS "${MODULE};Library")

if (UNIX)
target_link_libraries(${target} ${CMAKE_THREAD_LIBS_INIT})
endif (UNIX)
target_link_libraries(${target} ${LIBRARY_DEPS})

set(LIBRARY_DEPS "${LIBRARY_DEPS};${target}" PARENT_SCOPE)
100 changes: 100 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/src/number_to_words.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2024 Nedelin Dmitry

#include "include/number_to_words.h"

#include <climits>
#include <sstream>
#include <array>

std::string trim(const std::string& str) {
std::string trimmed = str;
auto end = trimmed.find_last_not_of(' ');
if (end != std::string::npos) {
trimmed.erase(end + 1);
}
return trimmed;
}

std::string NumberToWords::convert(int number) {
if (number == 0) {
return "zero";
}
if (number == INT_MIN) {
return "negative two billion one hundred forty seven million four "
"hundred eighty three thousand six hundred forty eight";
}

std::stringstream ss;

if (number < 0) {
ss << "negative ";
number = -number;
}

static constexpr int BILLION = 1000000000;
static constexpr int MILLION = 1000000;
static constexpr int THOUSAND = 1000;

if (number >= BILLION) {
ss << convertLessThanOneThousand(number / BILLION) << " billion";
number %= BILLION;
if (number > 0) {
ss << " ";
}
}

if (number >= MILLION) {
ss << convertLessThanOneThousand(number / MILLION) << " million";
number %= MILLION;
if (number > 0) {
ss << " ";
}
}

if (number >= THOUSAND) {
ss << convertLessThanOneThousand(number / THOUSAND) << " thousand";
number %= THOUSAND;
if (number > 0) {
ss << " ";
}
}

if (number > 0) {
ss << convertLessThanOneThousand(number);
}

return trim(ss.str());
}

std::string NumberToWords::convertLessThanOneThousand(int number) {
static const std::array<std::string, 20> units{
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
"sixteen", "seventeen", "eighteen", "nineteen"
};
static const std::array<std::string, 10> tens{
"", "", "twenty", "thirty", "forty", "fifty", "sixty",
"seventy", "eighty", "ninety"
};

std::stringstream ss;
if (number >= 100) {
ss << units[number / 100] << " hundred";
number %= 100;
if (number > 0) {
ss << " ";
}
}
if (number >= 20) {
ss << tens[number / 10];
number %= 10;
if (number > 0) {
ss << " ";
}
}
if (number > 0) {
ss << units[number];
}

return ss.str();
}
39 changes: 39 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/src/number_to_wordsApp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2024 Nedelin Dmitry

#include "include/number_to_words.h"
#include "include/number_to_wordsApp.h"

#include <stdexcept>
#include <sstream>

std::vector<std::string> Application::runApp(int argc, const char** argv) {
std::vector<std::string> output;

if (argc != 2) {
output.push_back("Usage: number_to_words <number>");
return output;
}

std::string input = argv[1];
try {
output.push_back(processNumber(input));
}
catch (const std::invalid_argument&) {
output.push_back("Invalid number format!");
}

return output;
}

std::string Application::processNumber(const std::string& input) {
int number;
try {
number = std::stoi(input);
}
catch (...) {
throw std::invalid_argument("Invalid input");
}

NumberToWords converter;
return converter.convert(number);
}
27 changes: 27 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
set(target ${TESTS})

file(GLOB srcs "*.cpp")
set_source_files_properties(${srcs} PROPERTIES
LABELS "${MODULE};Test")

add_executable(${target} ${srcs} ${hdrs})
set_target_properties(${target} PROPERTIES
LABELS "${MODULE};Test")

if (UNIX)
target_link_libraries(${target} gtest ${CMAKE_THREAD_LIBS_INIT} pthread)
endif (UNIX)
target_link_libraries(${target} gtest ${LIBRARY})

# VS2012 doesn't support correctly the tuples yet,
# see http://code.google.com/p/googletest/issues/detail?id=412
if(MSVC)
target_compile_definitions(${target} PUBLIC _VARIADIC_MAX=10)
endif()

add_test(
NAME ${MODULE}_gtest
COMMAND ${target}
)
set_tests_properties (${MODULE}_gtest PROPERTIES
LABELS "${MODULE}")
9 changes: 9 additions & 0 deletions modules/nedelin_d_number_to_words_lab3/test/test_main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2024 Nedelin Dmitry

#include <gtest/gtest.h>
#include "include/number_to_wordsApp.h"

int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Loading