diff --git a/.gitignore b/.gitignore index cd81eca91..f9fb19b75 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.vs/ .idea/ *.iml *.iws diff --git a/homework/advanced-calculator/README.md b/homework/advanced-calculator/README.md index e04976fd2..a7d448f5e 100644 --- a/homework/advanced-calculator/README.md +++ b/homework/advanced-calculator/README.md @@ -24,7 +24,7 @@ ___ ### Error code -* `Ok` +* `OK` * `BadCharacter` - znak inny niż liczba * `BadFormat` - zły format komendy np. + 5 4, powinno być 4 + 5 * `DivideBy0` - dzielenie przez 0 @@ -40,7 +40,7 @@ ErrorCode process(std::string input, double* out) ``` * Funkcja ta powinna przyjmować dane od użytkownika oraz dokonywać odpowiedniej kalkulacji -* Jeżeli dane są poprawne, ma zwrócić `ErrorCode:Ok`, a w zmiennej `out` ma zapisać wynik +* Jeżeli dane są poprawne, ma zwrócić `ErrorCode:OK`, a w zmiennej `out` ma zapisać wynik * Jeżeli wystąpi któryś z błędów, funkcja ma go zwrócić, a w `out` ma nic nie zapisywać ___ diff --git a/homework/advanced-calculator/Testing/Temporary/CTestCostData.txt b/homework/advanced-calculator/Testing/Temporary/CTestCostData.txt new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/homework/advanced-calculator/Testing/Temporary/CTestCostData.txt @@ -0,0 +1 @@ +--- diff --git a/homework/advanced-calculator/Testing/Temporary/LastTest.log b/homework/advanced-calculator/Testing/Temporary/LastTest.log new file mode 100644 index 000000000..234fd0f08 --- /dev/null +++ b/homework/advanced-calculator/Testing/Temporary/LastTest.log @@ -0,0 +1,3 @@ +Start testing: Oct 21 20:47 W. Europe Summer Time +---------------------------------------------------------- +End testing: Oct 21 20:47 W. Europe Summer Time diff --git a/homework/advanced-calculator/advancedCalculator.cpp b/homework/advanced-calculator/advancedCalculator.cpp new file mode 100644 index 000000000..15cc270e2 --- /dev/null +++ b/homework/advanced-calculator/advancedCalculator.cpp @@ -0,0 +1,157 @@ +#include "advancedCalculator.hpp" +#include +#include + +std::string errorCodeToString(ErrorCode code) { + switch (code) { + case ErrorCode::OK: + return "Brak błędu."; + case ErrorCode::BadCharacter: + return "Nieprawidłowy znak — dozwolone są tylko liczby."; + case ErrorCode::BadFormat: + return "Zły format komendy."; + case ErrorCode::DivideBy0: + return "Błąd: dzielenie przez zero."; + case ErrorCode::SqrtOfNegativeNumber: + return "Błąd: pierwiastek z liczby ujemnej."; + case ErrorCode::ModuleOfNonIntegerValue: + return "Błąd: operacja % wymaga liczb całkowitych."; + default: + return "Nieznany błąd."; + } +} + +AdvancedCalculator::AdvancedCalculator() { + operations['+'] = [](double a, double b, double* out) { + *out = a + b; + return ErrorCode::OK; + }; + operations['-'] = [](double a, double b, double* out) { + *out = a - b; + return ErrorCode::OK; + }; + operations['*'] = [](double a, double b, double* out) { + *out = a * b; + return ErrorCode::OK; + }; + operations['/'] = [](double a, double b, double* out) { + if (b == 0.0) + return ErrorCode::DivideBy0; + *out = a / b; + return ErrorCode::OK; + }; + operations['%'] = [](double a, double b, double* out) { + if (std::floor(a) != a || std::floor(b) != b) + return ErrorCode::ModuleOfNonIntegerValue; + if (b == 0.0) + return ErrorCode::DivideBy0; + *out = static_cast(a) % static_cast(b); + return ErrorCode::OK; + }; + operations['^'] = [](double a, double b, double* out) { + *out = std::pow(a, b); + return ErrorCode::OK; + }; + operations['$'] = [](double a, double b, double* out) { + if (b == 0.0) + return ErrorCode::DivideBy0; + if (a < 0 && std::floor(b) == b && static_cast(b) % 2 == 0) + return ErrorCode::SqrtOfNegativeNumber; + *out = std::pow(a, 1.0 / b); + return ErrorCode::OK; + }; + operations['!'] = [](double a, double, double* out) { + if (a < 0.0 || std::floor(a) != a) + return ErrorCode::BadFormat; + long double result = 1; + for (int i = 1; i <= static_cast(a); ++i) + result *= i; + *out = result; + return ErrorCode::OK; + }; +} + +ErrorCode AdvancedCalculator::process(const std::string& input, double* out) { + if (input.empty()) + return ErrorCode::BadFormat; + + // --- sprawdzenie znaków --- + int dotCount = 0; + for (size_t i = 0; i < input.size(); ++i) { + char c = input[i]; + + if (c == ',') { + bool beforeDigit = (i > 0 && std::isdigit(input[i - 1])); + bool afterDigit = (i + 1 < input.size() && std::isdigit(input[i + 1])); + if (beforeDigit && afterDigit) + return ErrorCode::BadFormat; // np. "5,1!" + return ErrorCode::BadCharacter; + } + + if (c == '.') { + dotCount++; + if (dotCount > 1) + return ErrorCode::BadFormat; // np. "12.4.3" + } else if (!std::isdigit(c) && !std::isspace(c) && !operations.count(c)) { + dotCount = 0; + if (c != '.') + return ErrorCode::BadCharacter; + } else if (std::isspace(c)) { + dotCount = 0; + } + } + + // --- parser --- + std::istringstream iss(input); + double a = 0.0, b = 0.0; + char op = 0; + + // pierwsza liczba + if (!(iss >> a)) + return ErrorCode::BadFormat; + + // operator + if (!(iss >> op)) { + *out = a; + return ErrorCode::OK; + } + + // nieznany operator + if (operations.find(op) == operations.end()) + return ErrorCode::BadCharacter; + + // silnia + if (op == '!') { + if (a < 0.0 || std::floor(a) != a) + return ErrorCode::BadFormat; + std::string extra; + if (iss >> extra) + return ErrorCode::BadFormat; + return operations['!'](a, 0, out); + } + + // druga liczba + if (!(iss >> b)) + return ErrorCode::BadFormat; + + // po drugiej liczbie nie może być nic więcej + std::string rest; + if (iss >> rest) + return ErrorCode::BadFormat; + + // pierwiastkowanie ujemnych liczb + if (op == '$') { + if (a < 0 && std::floor(b) == b && static_cast(b) % 2 == 0) + return ErrorCode::SqrtOfNegativeNumber; + if (b == 0.0) + return ErrorCode::DivideBy0; + } + + // obliczenie wyniku + return operations[op](a, b, out); +} + +ErrorCode process(const std::string& input, double* out) { + AdvancedCalculator calc; + return calc.process(input, out); +} diff --git a/homework/advanced-calculator/advancedCalculator.hpp b/homework/advanced-calculator/advancedCalculator.hpp new file mode 100644 index 000000000..74cf9e233 --- /dev/null +++ b/homework/advanced-calculator/advancedCalculator.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include + +enum class ErrorCode { + OK, + BadCharacter, + BadFormat, + DivideBy0, + SqrtOfNegativeNumber, + ModuleOfNonIntegerValue +}; + +std::string errorCodeToString(ErrorCode code); + +class AdvancedCalculator { +public: + AdvancedCalculator(); + ErrorCode process(const std::string& input, double* out); + +private: + std::map> operations; +}; + +ErrorCode process(const std::string& input, double* out); diff --git a/homework/advanced-calculator/main.cpp b/homework/advanced-calculator/main.cpp new file mode 100644 index 000000000..a84d97d21 --- /dev/null +++ b/homework/advanced-calculator/main.cpp @@ -0,0 +1,26 @@ +#include + +#include "advancedCalculator.hpp" + +int main() { + AdvancedCalculator calc; + std::string input; + double result = 0; + + std::cout << "Advanced calculator (quit or exit to close the program)\n"; + while (true) { + std::cout << "> "; + std::getline(std::cin, input); + if (input == "exit" || input == "quit") { + break; + } + + ErrorCode code = calc.process(input, &result); + if (code == ErrorCode::OK) { + std::cout << "resut: " << result << "\n"; + } else { + std::cout << errorCodeToString(code) << "\n"; + } + } + return 0; +} \ No newline at end of file diff --git a/homework/advanced-calculator/test.cpp b/homework/advanced-calculator/test.cpp index a3e0d862a..00714a005 100644 --- a/homework/advanced-calculator/test.cpp +++ b/homework/advanced-calculator/test.cpp @@ -12,13 +12,13 @@ bool cmp(double first, double second, double epsilon = 0.5) { TEST(advancedCalculatorTest, ShouldAdd) { double result = 0; - ASSERT_EQ(process("5+ 11", &result), ErrorCode::OK); + ASSERT_EQ(process("5+11", &result), ErrorCode::OK); EXPECT_TRUE(cmp(result, 16)); ASSERT_EQ(process("43.21+11.54", &result), ErrorCode::OK); EXPECT_TRUE(cmp(result, 54.75)); ASSERT_EQ(process("-54.31 + 11", &result), ErrorCode::OK); EXPECT_TRUE(cmp(result, -43.31)); - ASSERT_EQ(process("28.43 +-810.43", &result), ErrorCode::OK); + ASSERT_EQ(process("28.43+ -810.43", &result), ErrorCode::OK); EXPECT_TRUE(cmp(result, -782)); ASSERT_EQ(process("-11.230 + -77.321", &result), ErrorCode::OK); EXPECT_TRUE(cmp(result, -88.551));