diff --git a/01_week/tasks/addition/addition.cpp b/01_week/tasks/addition/addition.cpp index 92872802..c89d7ce9 100644 --- a/01_week/tasks/addition/addition.cpp +++ b/01_week/tasks/addition/addition.cpp @@ -1,7 +1,6 @@ #include #include - int64_t Addition(int a, int b) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + return static_cast(a) + b; +} diff --git a/01_week/tasks/char_changer/char_changer.cpp b/01_week/tasks/char_changer/char_changer.cpp index 3a7344d9..9629f341 100644 --- a/01_week/tasks/char_changer/char_changer.cpp +++ b/01_week/tasks/char_changer/char_changer.cpp @@ -1,7 +1,65 @@ #include #include +#include +const char dif_letters = 'a' - 'A'; size_t CharChanger(char array[], size_t size, char delimiter = ' ') { - throw std::runtime_error{"Not implemented"}; + size_t count = 1, last_ind = size - 1; + size_t start_rep_ind, end_rep_ind; + + for (size_t i = 0; i < size; ++i) { + if (i == size - 1) { + return last_ind; + } + + if (array[i] == array[i + 1]) { + if (count == 1) start_rep_ind = i; + count++; + + if (array[i] == ' ') continue; + } + else if (count != 1) { + end_rep_ind = i + 1; + i = start_rep_ind; + + size_t ind_next_simbol = i + 2; + last_ind -= count - 2; + + if (array[i] != ' ') { + if (count >= 10) array[++i] = '0'; + else array[++i] = static_cast(static_cast('0') + count); + } + else { + --ind_next_simbol; + --last_ind; + array[i] = delimiter; + } + + for (size_t j = end_rep_ind; j < size; ++j) { + std::swap(array[ind_next_simbol], array[j]); + ++ind_next_simbol; + } + + size_t reduct_size = end_rep_ind - start_rep_ind; + size -= reduct_size - 2; + count = 1; + continue; + } + + if (std::isdigit(array[i])) { + array[i] = '*'; + } + else if (std::islower(array[i])) { + array[i] -= dif_letters; + } + else if (std::ispunct(array[i])) { + array[i] = '_'; + } + else if (std::isspace(array[i])) { + array[i] = delimiter; + } + } + + return last_ind; } diff --git a/01_week/tasks/check_flags/check_flags.cpp b/01_week/tasks/check_flags/check_flags.cpp index 75e7c652..8553bad6 100644 --- a/01_week/tasks/check_flags/check_flags.cpp +++ b/01_week/tasks/check_flags/check_flags.cpp @@ -1,5 +1,6 @@ #include #include +#include enum class CheckFlags : uint8_t { @@ -14,5 +15,54 @@ enum class CheckFlags : uint8_t { }; void PrintCheckFlags(CheckFlags flags) { - throw std::runtime_error{"Not implemented"}; + if (flags > CheckFlags::ALL) { + std::cout << ""; + return; + } + + bool the_first = true; + std::string str_flags = "["; + + size_t max_value_flag = 32; + for (size_t i = 0; i < max_value_flag; i >>= 1) { + auto b_i = static_cast(flags) >> i & 1u; + if (b_i) { + + + } + } + + if (static_cast(flags) & + static_cast(CheckFlags::TIME)) { + str_flags += "TIME"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::DATE)) { + the_first ? str_flags += "DATE" : str_flags += ",DATE"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::USER) ) { + the_first ? str_flags += "USER" : str_flags += ",USER"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::CERT)) { + the_first ? str_flags += "CERT" : str_flags += ",CERT"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::KEYS)) { + the_first ? str_flags += "KEYS" : str_flags += ",KEYS"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::DEST)) { + the_first ? str_flags += "DEST" : str_flags += ",DEST"; + the_first = false; + } + + str_flags += "]"; + std::cout << str_flags; } diff --git a/01_week/tasks/length_lit/length_lit.cpp b/01_week/tasks/length_lit/length_lit.cpp index e69de29b..cc980a86 100644 --- a/01_week/tasks/length_lit/length_lit.cpp +++ b/01_week/tasks/length_lit/length_lit.cpp @@ -0,0 +1,65 @@ +namespace { + const double m_in_inch = 0.0254; + const double m_in_foot = 0.3048; + const double m_in_cm = 0.01; +} + + +// m +constexpr long double operator""_m_to_m(long double m) { + return m; +} +constexpr long double operator""_m_to_in(long double m) { + return m / m_in_inch; +} +constexpr long double operator""_m_to_ft(long double m) { + return m / m_in_foot; +} +constexpr long double operator""_m_to_cm(long double m) { + return m / m_in_cm; +} + + +// cm +constexpr long double operator""_cm_to_cm(long double cm) { + return cm; +} +constexpr long double operator""_cm_to_in(long double cm) { + return cm / (m_in_inch / m_in_cm); +} +constexpr long double operator""_cm_to_ft(long double cm) { + return cm / (m_in_foot / m_in_cm); +} +constexpr long double operator""_cm_to_m(long double cm) { + return cm / m_in_cm; +} + + +// foot +constexpr long double operator""_ft_to_ft(long double ft) { + return ft; +} +constexpr long double operator""_ft_to_in(long double ft) { + return ft * (m_in_foot / m_in_inch); +} +constexpr long double operator""_ft_to_m(long double ft) { + return ft * m_in_foot; +} +constexpr long double operator""_ft_to_cm(long double ft) { + return ft * (m_in_foot / m_in_cm); +} + + +// inch +constexpr long double operator""_in_to_in(long double in) { + return in; +} +constexpr long double operator""_in_to_ft(long double in) { + return in * (m_in_inch / m_in_foot); +} +constexpr long double operator""_in_to_m(long double in) { + return in * m_in_inch; +} +constexpr long double operator""_in_to_cm(long double in) { + return in * (m_in_inch / m_in_cm); +} \ No newline at end of file diff --git a/01_week/tasks/print_bits/print_bits.cpp b/01_week/tasks/print_bits/print_bits.cpp index a48a43c1..5d5e3c5d 100644 --- a/01_week/tasks/print_bits/print_bits.cpp +++ b/01_week/tasks/print_bits/print_bits.cpp @@ -1,7 +1,17 @@ -#include -#include - +#include +#include void PrintBits(long long value, size_t bytes) { - throw std::runtime_error{"Not implemented"}; + auto count_bits = bytes * 8; + std::string str_bset = "0b"; + + for (size_t i = count_bits; i > 0; --i) { + auto b_i = (value >> (i - 1)) & 1u; + b_i ? str_bset += "1" : str_bset += "0"; + + if ((i - 1) % 4 == 0 && i != count_bits && i != 1) { + str_bset += '\''; + } + } + std::cout << str_bset << "\n"; } diff --git a/01_week/tasks/quadratic/quadratic.cpp b/01_week/tasks/quadratic/quadratic.cpp index abf7d632..b6f680e4 100644 --- a/01_week/tasks/quadratic/quadratic.cpp +++ b/01_week/tasks/quadratic/quadratic.cpp @@ -1,6 +1,68 @@ #include - +#include +#include +#include +#include void SolveQuadratic(int a, int b, int c) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + double x_1, x_2; + bool a_is_zero = a == 0; + bool b_is_zero = b == 0; + bool c_is_zero = c == 0; + + std::cout << std::setprecision(6); + + if (a_is_zero && b_is_zero && c_is_zero) { + std::cout << "infinite solutions"; + return; + } else if (a_is_zero && b_is_zero && !c_is_zero) { + std::cout << "no solutions"; + return; + } else if (a_is_zero && !b_is_zero && c_is_zero) { + std::cout << c; + return; + } else if (a_is_zero && !b_is_zero && !c_is_zero) { + x_1 = static_cast(-c) / static_cast(b); + std::cout << x_1; + return; + } else if (!a_is_zero && b_is_zero && c_is_zero) { + std::cout << "0"; + return; + } else if (!a_is_zero && b_is_zero && !c_is_zero) { + if (a * c > 0) { + std::cout << "no solutions"; + return; + } + x_2 = std::sqrt(static_cast(-c) / static_cast(a)); + x_1 = -x_2; + std::cout << x_1 << " " << x_2; + return; + } else if (!a_is_zero && !b_is_zero && c_is_zero) { + x_1 = 0.; + x_2 = static_cast(-b) / a; + if (x_1 > x_2) std::swap(x_1, x_2); + std::cout << x_1 << " " << x_2; + return; + } + + double D_2 = b * b - 4.0 * a * c; + double eps = 1e-14; + + if (D_2 < 0) { + std::cout << "no solutions"; + return; + } + else if (D_2 < eps) { + x_1 = static_cast(-b) / (2 * a); + std::cout << x_1; + return; + } + else { + double D = std::sqrt(D_2); + x_1 = (-b + D) / (2 * a); + x_2 = (-b - D) / (2 * a); + if (x_1 > x_2) std::swap(x_1, x_2); + std::cout << x_1 << " " << x_2; + return; + } +} diff --git a/01_week/tasks/rms/rms.cpp b/01_week/tasks/rms/rms.cpp index 6882f0a9..046ef895 100644 --- a/01_week/tasks/rms/rms.cpp +++ b/01_week/tasks/rms/rms.cpp @@ -1,7 +1,11 @@ -#include -#include - +#include +#include double CalculateRMS(double values[], size_t size) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + if (values == nullptr || size == 0) return static_cast(0.0); + double sum = 0.0; + for (size_t i = 0; i < size; ++i) { + sum += values[i] * values[i]; + } + return std::sqrt(sum / size); +} diff --git a/02_week/tasks/func_array/func_array.cpp b/02_week/tasks/func_array/func_array.cpp index b327e68d..94f6f157 100644 --- a/02_week/tasks/func_array/func_array.cpp +++ b/02_week/tasks/func_array/func_array.cpp @@ -1,6 +1,12 @@ #include -double ApplyOperations(double a, double b /* other arguments */) { - throw std::runtime_error{"Not implemented"}; +double ApplyOperations(const double a, const double b, + double (*operations[])(const double, const double), size_t countOperations) +{ + double res = 0.0; + for (size_t i = 0; i < countOperations; ++i){ + if (operations[i] != nullptr) res += operations[i](a, b); + } + return res; } \ No newline at end of file diff --git a/02_week/tasks/last_of_us/last_of_us.cpp b/02_week/tasks/last_of_us/last_of_us.cpp index c7bf1a25..60dbd9f9 100644 --- a/02_week/tasks/last_of_us/last_of_us.cpp +++ b/02_week/tasks/last_of_us/last_of_us.cpp @@ -1,6 +1,14 @@ #include +const int* FindLastElement(const int* begin, const int* end, + bool(*predicate)(int)) { + + if (!predicate || !begin || !end || std::distance(begin, end) < 0) + return end; + + for(const int* it = end - 1; it != begin - 1; --it) { + if (predicate(*it)) return it; + } -/* return_type */ FindLastElement(/* ptr_type */ begin, /* ptr_type */ end, /* func_type */ predicate) { - throw std::runtime_error{"Not implemented"}; + return end; } \ No newline at end of file diff --git a/02_week/tasks/little_big/little_big.cpp b/02_week/tasks/little_big/little_big.cpp index abe24379..acab9842 100644 --- a/02_week/tasks/little_big/little_big.cpp +++ b/02_week/tasks/little_big/little_big.cpp @@ -1,10 +1,54 @@ #include +#include +#include +void PrintMemoryBodyTemplate(char* num_ptr_char, size_t size, bool flag_rvrs) { + std::string byteset = ""; + for (size_t j = 0; j < size; ++j) { + unsigned char temp = *(num_ptr_char + j); + size_t count_hex_in_byte = 2; + std::string byte = ""; -void PrintMemory(int /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; + for (size_t i = 0; i < count_hex_in_byte; ++i) { + auto power = static_cast(std::pow(16, 1 - i)); + size_t remain = static_cast(temp / power); + if (power == temp || remain != 0) { + temp -= remain * power; + } + + char hex_conv; + if (remain < 10) hex_conv = static_cast(remain + '0'); + else hex_conv = static_cast(remain - 10 + 'A'); + byte += hex_conv; + } + byteset += byte; + } + + if (flag_rvrs) { + for (size_t i = 0; i < byteset.size() / 2; ++i) { + if (i % 2 == 0) { + std::swap(byteset[i], byteset[byteset.size() - 1 - (i + 1)]); + } + else { + std::swap(byteset[i], byteset[byteset.size() - 1 - (i - 1)]); + } + } + } + + byteset.insert(0, "0x"); + std::cout << byteset << "\n"; } -void PrintMemory(double /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +void PrintMemory(int num, bool flag_rvrs = false) { + char* num_ptr_char = reinterpret_cast(&num); + + size_t size_int = sizeof(int); + PrintMemoryBodyTemplate(num_ptr_char, size_int, flag_rvrs); +} + +void PrintMemory(double num, bool flag_rvrs = false) { + char* num_ptr_char = reinterpret_cast(&num); + + size_t size_double = sizeof(double); + PrintMemoryBodyTemplate(num_ptr_char, size_double, flag_rvrs); } \ No newline at end of file diff --git a/02_week/tasks/longest/longest.cpp b/02_week/tasks/longest/longest.cpp index 04b3c354..58f60b46 100644 --- a/02_week/tasks/longest/longest.cpp +++ b/02_week/tasks/longest/longest.cpp @@ -1,6 +1,33 @@ #include +const char* FindLongestSubsequence(const char* begin, const char* end, + size_t& count) { + + if (!begin || !end || std::distance(begin, end) <= 0) { + count = 0; + return nullptr; + } + + auto res_ind = begin; + size_t curr_count = 1; + count = 1; + + for (auto it = begin; it != end - 1; ++it){ + if (*it == *(it + 1)) { + ++curr_count; + continue; + } + if (count < curr_count) { + count = curr_count; + res_ind = it - (curr_count - 1); + } + curr_count = 1; + } -/* return_type */ FindLongestSubsequence(/* ptr_type */ begin, /* ptr_type */ end, /* type */ count) { - throw std::runtime_error{"Not implemented"}; + if (count < curr_count) { + count = curr_count; + res_ind = end - curr_count; + } + + return res_ind; } diff --git a/02_week/tasks/pretty_array/pretty_array.cpp b/02_week/tasks/pretty_array/pretty_array.cpp index 48eab341..742c0078 100644 --- a/02_week/tasks/pretty_array/pretty_array.cpp +++ b/02_week/tasks/pretty_array/pretty_array.cpp @@ -1,6 +1,28 @@ #include +#include - -void PrintArray(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +void PrintArray(const int* begin, const int* end, size_t limit = 0) { + auto _start = begin; + auto _end = end; + auto inc = 1; + if (std::distance(begin, end) < 0) { + inc = -1; + } + + std::cout << "["; + size_t count = 0; + for (auto it = _start; it != _end; it += inc) { + if (limit != 0 && count == limit) { + std::cout << "...\n "; + count = 1; + } + else ++count; + + std::cout << *it; + if ((inc == 1 && it != _end - 1) || + (inc == -1 && it != _end + 1)){ + std::cout << ", "; + } + } + std::cout << "]\n"; } \ No newline at end of file diff --git a/02_week/tasks/swap_ptr/swap_ptr.cpp b/02_week/tasks/swap_ptr/swap_ptr.cpp index 93db625d..2c7cf0bd 100644 --- a/02_week/tasks/swap_ptr/swap_ptr.cpp +++ b/02_week/tasks/swap_ptr/swap_ptr.cpp @@ -1,6 +1,8 @@ #include - -void SwapPtr(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +template +void SwapPtr(T*& p1, T*& p2) { + T* temp_p = p1; + p1 = p2; + p2 = temp_p; } \ No newline at end of file diff --git a/03_week/tasks/data_stats/data_stats.cpp b/03_week/tasks/data_stats/data_stats.cpp index b941c211..92d13f68 100644 --- a/03_week/tasks/data_stats/data_stats.cpp +++ b/03_week/tasks/data_stats/data_stats.cpp @@ -1,11 +1,32 @@ #include - +#include +#include struct DataStats { double avg = 0.0; double sd = 0.0; }; -/* return_type */ CalculateDataStats(/* args */) { - throw std::runtime_error{"Not implemented"}; -} + DataStats CalculateDataStats(const std::vector& vec) { + DataStats data; + + size_t v_size = vec.size(); + + if (v_size == 0) return data; + long long sum_sq = 0; + long long mid_memb = 0; + double avg = 0.; + + for (size_t i = 0; i < v_size; ++i) { + sum_sq += static_cast(vec[i]) * vec[i]; + avg += static_cast(vec[i]); + mid_memb += 2 * static_cast(vec[i]); + } + + avg /= v_size; + double num = sum_sq - mid_memb * avg + avg * avg * v_size; + data.sd = std::sqrt(num / v_size); + data.avg = avg; + + return data; + } diff --git a/03_week/tasks/easy_compare/easy_compare.cpp b/03_week/tasks/easy_compare/easy_compare.cpp index dd5cb7f6..e8923817 100644 --- a/03_week/tasks/easy_compare/easy_compare.cpp +++ b/03_week/tasks/easy_compare/easy_compare.cpp @@ -1,10 +1,10 @@ #include - +#include struct Date { - unsigned year; - unsigned month; - unsigned day; + unsigned year = 0u; + unsigned month = 0u; + unsigned day = 0u; }; struct StudentInfo { @@ -13,4 +13,41 @@ struct StudentInfo { int score; unsigned course; Date birth_date; -}; \ No newline at end of file +}; + +bool operator<(const Date& date1, const Date& date2) { + return std::tie(date1.year, date1.month, date1.day) < std::tie(date2.year, date2.month, date2.day); +} + +bool operator==(const Date& date1, const Date& date2) { + return std::tie(date1.year, date1.month, date1.day) == std::tie(date2.year, date2.month, date2.day); +} + +bool operator>(const Date& date1, const Date& date2) { + return !(date1 < date2) && !(date1 == date2); +} + +bool operator>=(const Date& date1, const Date& date2) { + return !(date1 < date2) || (date1 == date2); +} + +bool operator<=(const Date& date1, const Date& date2) { + return (date1 < date2) || (date1 == date2); +} + +bool operator!=(const Date& date1, const Date& date2) { + return !(date1 == date2); +} + +bool operator<(const StudentInfo& s1, const StudentInfo& s2) { + return std::tie(s1.mark, s2.score, s1.course, s2.birth_date) > std::tie(s2.mark, s1.score, s2.course, s1.birth_date); +} + +bool operator==(const StudentInfo& s1, const StudentInfo& s2) { + return std::tie(s1.mark, s1.score) == std::tie(s2.mark, s2.score); +} + +bool operator!=(const StudentInfo& s1, const StudentInfo& s2) { + return !(s1 == s2); +} + diff --git a/03_week/tasks/enum_operators/enum_operators.cpp b/03_week/tasks/enum_operators/enum_operators.cpp index a539be38..ca664296 100644 --- a/03_week/tasks/enum_operators/enum_operators.cpp +++ b/03_week/tasks/enum_operators/enum_operators.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include enum class CheckFlags : uint8_t { NONE = 0, @@ -12,22 +14,93 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; -/* return_type */ operator|(/* args */) { - throw std::runtime_error{"Not implemented"}; +const size_t max_count_flags = 6; + +CheckFlags operator|(const CheckFlags& f1, const CheckFlags f2) { + uint8_t res = 0; + for (size_t i = 0; i < max_count_flags; ++i) { + uint8_t b_1 = (static_cast(f1) >> i) & 1u; + uint8_t b_2 = (static_cast(f2) >> i) & 1u; + if ((b_1 | b_2) == 1) res |= (1u << i); + } + return static_cast(res); } -/* return_type */ operator&(/* args */) { - throw std::runtime_error{"Not implemented"}; +bool operator&(const CheckFlags& f1, const CheckFlags& f2) { + if (f1 == CheckFlags::NONE || f2 == CheckFlags::NONE) return false; + + bool flag1 = true; + bool flag2 = true; + uint8_t res = 0; + for (size_t i = 0; i < max_count_flags; ++i) { + uint8_t b_1 = (static_cast(f1) >> i) & 1u; + uint8_t b_2 = (static_cast(f2) >> i) & 1u; + res |= ((b_1 & b_2) << i); + if (flag1 && b_1 == 0 && b_2 == 1) flag1 = false; + if (flag2 && b_1 == 1 && b_2 == 0) flag2 = false; + } + if ((static_cast(res) == CheckFlags::NONE) || (!flag1 && !flag2)) { + return false; + } + return true; } -/* return_type */ operator^(/* args */) { - throw std::runtime_error{"Not implemented"}; +CheckFlags operator^(const CheckFlags& f1, const CheckFlags& f2) { + uint8_t res = 0; + for (size_t i = 0; i < max_count_flags; ++i) { + uint8_t b_1 = (static_cast(f1) >> i) & 1u; + uint8_t b_2 = (static_cast(f2) >> i) & 1u; + if ((b_1 & b_2) == 0 && (b_1 | b_2) == 1) res |= (1u << i); + } + return static_cast(res); } -/* return_type */ operator~(/* args */) { - throw std::runtime_error{"Not implemented"}; +CheckFlags operator~(const CheckFlags& f) { + int8_t res = 0; + for (size_t i = 0; i < max_count_flags; ++i) { + uint8_t b = (static_cast(f) >> i) & 1u; + if (b == 0) res |= (1u << i); + } + return static_cast(res); } -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::ostream& operator<<(std::ostream& os, const CheckFlags& flags) { + bool the_first = true; + std::string str_flags = ""; + + if (static_cast(flags) & + static_cast(CheckFlags::TIME)) { + str_flags += "TIME"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::DATE)) { + the_first ? str_flags += "DATE" : str_flags += ", DATE"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::USER) ) { + the_first ? str_flags += "USER" : str_flags += ", USER"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::CERT)) { + the_first ? str_flags += "CERT" : str_flags += ", CERT"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::KEYS)) { + the_first ? str_flags += "KEYS" : str_flags += ", KEYS"; + the_first = false; + } + if (static_cast(flags) & + static_cast(CheckFlags::DEST)) { + the_first ? str_flags += "DEST" : str_flags += ", DEST"; + the_first = false; + } + if (str_flags.length() == 0) str_flags += "NONE"; + + os << str_flags; + + return os; } diff --git a/03_week/tasks/filter/filter.cpp b/03_week/tasks/filter/filter.cpp index 6648cb39..2cb7537d 100644 --- a/03_week/tasks/filter/filter.cpp +++ b/03_week/tasks/filter/filter.cpp @@ -1,6 +1,15 @@ #include +#include +void Filter(std::vector& vec, bool (*func)(int)) { + if (vec.size() == 0 || func == nullptr) return; -/* return_type */ Filter(/* args */) { - throw std::runtime_error{"Not implemented"}; + auto last_correct_it = vec.begin(); + for(auto it = vec.begin(); it != vec.end(); ++it) { + if (func(*it)) { + std::swap(*it, *last_correct_it); + ++last_correct_it; + } + } + vec.erase(last_correct_it, vec.end()); } \ No newline at end of file diff --git a/03_week/tasks/find_all/find_all.cpp b/03_week/tasks/find_all/find_all.cpp index 74f393b2..528adbcd 100644 --- a/03_week/tasks/find_all/find_all.cpp +++ b/03_week/tasks/find_all/find_all.cpp @@ -1,6 +1,25 @@ #include +#include +std::vector FindAll(const std::vector& vec, bool (*func)(int)) { + if (vec.size() == 0 || func == nullptr) return std::vector(0); -/* return_type */ FindAll(/* args */) { - throw std::runtime_error{"Not implemented"}; + std::vector res(vec.size() / 2); + size_t res_ind = 0; + + for(size_t i = 0; i < vec.size(); ++i) { + if (res.size() == res_ind) + res.resize(res_ind * 2); + + if (func(vec[i])) { + if (res.empty()) res.push_back(i); + else res[res_ind] = i; + ++res_ind; + } + } + + res.erase(res.begin() + res_ind, res.end()); + res.shrink_to_fit(); + + return res; } \ No newline at end of file diff --git a/03_week/tasks/minmax/minmax.cpp b/03_week/tasks/minmax/minmax.cpp index c2869799..f85c590a 100644 --- a/03_week/tasks/minmax/minmax.cpp +++ b/03_week/tasks/minmax/minmax.cpp @@ -1,6 +1,15 @@ #include +#include +using cit_t = std::vector::const_iterator ; -/* return_type */ MinMax(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::pair MinMax(const std::vector& vec) { + if (vec.size() == 0) return std::make_pair(vec.cend(), vec.cend()); + auto it_min = vec.cbegin(); + auto it_max = vec.cbegin(); + for (auto it = vec.cbegin(); it != vec.cend(); ++it) { + if (*it_min > *it) it_min = it; + if (*it_max <= *it) it_max = it; + } + return std::make_pair(it_min, it_max); } diff --git a/03_week/tasks/os_overload/os_overload.cpp b/03_week/tasks/os_overload/os_overload.cpp index e473418d..44d5a04d 100644 --- a/03_week/tasks/os_overload/os_overload.cpp +++ b/03_week/tasks/os_overload/os_overload.cpp @@ -1,21 +1,53 @@ #include #include #include - +#include +#include struct Coord2D { - int x; - int y; + int x = 0; + int y = 0; }; struct Circle { Coord2D coord; - unsigned radius; + unsigned radius = 1; }; using CircleRegion = std::pair; using CircleRegionList = std::vector; -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::ostream& operator<<(std::ostream& os, const Coord2D& coords) { + os << "(" + std::to_string(coords.x) + ", " + std::to_string(coords.y) + ")"; + return os; +} + +std::ostream& operator<<(std::ostream& os, const Circle& circle) { + if (circle.radius == 0) os << "circle[]"; + else { + os << "circle[" << circle.coord << ", " + << "r = " << std::to_string(circle.radius) << "]"; + } + return os; +} + +std::ostream& operator<<(std::ostream& os, const CircleRegion& creg) { + if (creg.second) os << "+"; + else os << "-"; + os << creg.first; + return os; +} + +std::ostream& operator<<(std::ostream& os, const CircleRegionList& list) { + if (list.size() == 0) os << "{}"; + else { + os << "{"; + for(size_t i = 0; i < list.size(); ++i) { + os << "\n\t" << list[i]; + if (i != list.size() - 1) os << ","; + } + os << "\n}"; + } + return os; } + diff --git a/03_week/tasks/range/range.cpp b/03_week/tasks/range/range.cpp index d2085495..78416e9b 100644 --- a/03_week/tasks/range/range.cpp +++ b/03_week/tasks/range/range.cpp @@ -1,7 +1,18 @@ #include #include +std::vector Range(int from, int to, int step = 1) { + if ((to == from) || (step <= 0 ? to > from : from > to)) + return std::vector(); + + size_t num = std::abs(to - from); + size_t div = std::abs(step); + size_t size = num / div; + if (num % div > 0) ++size; -std::vector Range(int from, int to, int step) { - throw std::runtime_error{"Not implemented"}; -} + std::vector res(size); + for (size_t i = 0; i < size; ++i) { + res[i] = from + step * i; + } + return res; +} \ No newline at end of file diff --git a/03_week/tasks/unique/unique.cpp b/03_week/tasks/unique/unique.cpp index 9d2545bb..df00f563 100644 --- a/03_week/tasks/unique/unique.cpp +++ b/03_week/tasks/unique/unique.cpp @@ -1,6 +1,27 @@ #include #include -/* return_type */ Unique(/* args */) { - throw std::runtime_error{"Not implemented"}; -} +std::vector Unique(const std::vector& vec) { + if (vec.size() == 0) return std::vector(); + + std::vector unique_vec(vec.size() / 2); + size_t unique_ind = 0; + bool the_first_elem = true; + + for (size_t i = 0; i < vec.size(); ++i) { + if (unique_vec.size() == unique_ind) + unique_vec.resize(unique_vec.size() * 2); + + if (the_first_elem || vec[i] != vec[i - 1]) { + if (unique_vec.empty()) unique_vec.push_back(vec[i]); + else unique_vec[unique_ind] = vec[i]; + ++unique_ind; + the_first_elem = false; + } + } + + unique_vec.erase(unique_vec.begin() + unique_ind, unique_vec.end()); + unique_vec.shrink_to_fit(); + + return unique_vec; +} \ No newline at end of file diff --git a/04_week/04_class.md b/04_week/04_class.md deleted file mode 100644 index 46e00076..00000000 --- a/04_week/04_class.md +++ /dev/null @@ -1,902 +0,0 @@ -# Лекция 4. ООП. Класс - -1. [ООП](#oop) - - [Инкапсуляция](#encapsulation) - - [Наследование](#inheritance) - - [Полиморфизм](#polymorphism) - - [Абстракция](#abstraction) -1. [Класс](#class) - - [Спецификаторы доступа](#access_specifiers) - - [Отличие класса и структуры](#class_struct_diff) - - [Пустой класс](#class_empty) - - [Поля класса](#class_fields) - - [Инициализация полей значением по умолчанию](#field_default_init) - - [Конструктор](#ctor) - - [Список инициализации полей класса](#member_initializer_list) - - [Параметризованный конструктор](#parameterized_ctor) - - [Конструктор по умолчанию](#default_ctor) - - [Конструктор копирования](#copy_ctor) - - [Указатель на себя `this`](#this_ptr) - - [Копирующий оператор присваивания](#copy_assignment) - - [Деструктор](#dtor) - - [Конструктор преобразования](#converting_ctor) - - [Ключевое слово `explicit`](#explicit) - - [Конструктор от `std::initializer_list`(_C++11_)](#ctor_std_initializer_list) - - [Делегирующий конструктор (_C++11_)](#delegating_ctor) - - [Ключевое слово `default` (_С++11_)](#keyword_default) - - [Ключевое слово `delete` (_С++11_)](#keyword_delete) - - [Методы](#methods) - - [Определение методов вне класса](#methods_definition_outside) - - [CV-квалификация методов ](#cv_for_methods) - - [Оператор преобразования](#conversion_operator) - - [Перегрузка операторов внутри класса](#class_operator_overloading_inside) - - [Перегрузка операторов вне класса](#class_operator_overloading_outside) - - [Ключевое слово `friend`](#keyword_friend) - - [Ключевое слово `mutable`](#keyword_mutable) - - -## ООП - -Объектно-ориентированное программирование - парадигма программирования, которая -основывается на представление в коде программы различных объектов, взаимодействующих -друг с другом. - -Класс - пользовательский тип данных, шаблон (макет) для создания объектов и описания -их характеристик, функций. - -Объект - экземпляр класса. Объект включает данные (поля) и методы (функции). -Что позволяет хранить характеристики объекта, изменять их и взаимодействовать с -другими объектами. - -Основные принципы ООП: - -- Инкапсуляция -- Наследование -- Полиморфизм -- Абстракция - -### Инкапсуляция - -Инкапсуляция - объединение данных и методов для работы с данными внутри класса. -Сокрытие деталей реализации класса. - -```c++ -class Budget { -public: - void increase_balance(double value) { - budget_ += value; - } -private: - double budget_; -}; -``` - -### Наследование - -Наследование - механизм создания новых классов на основе существующих. Позволяет -строить иерархию классов и переиспользовать код классов родителей внутри -классов наследников. - -```c++ -class Animal { /* common data */}; -class Cat : public Animal {}; -class Dog : public Animal {}; -``` - -### Полиморфизм - -Полиморфизм - возможность различного поведения сущностей C++. - -Виды полиморфизма: - -- статический (на этапе компиляции, шаблоны, перегрузка функций) -- динамический (во время выполнения программы, виртуальные методы) - -```c++ -class Shape { -public: - virtual void draw() = 0; -}; -class Circle : public Shape { - void draw() override { /* рисуем круг */ } -}; -``` - -### Абстракция - -Абстракция - упрощение сложных вещей через выделение основных характеристик. - -## Класс - -Класс - пользовательский тип данных, который объединяет в себе данные (поля класса) -и функции для работы с данными (методы класса), представляет собой макет для -создания объектов (экземпляров) данного типа. - -Синтаксис: `class {};` - -- `` - имя класса, пользовательского типа данных -- `` - тело класса, включающее поля, методы, конструкторы и деструктор - -### Спецификаторы доступа - -Для ограничения видимости полей и методов внутри класса используются -спецификаторы доступа, весь код после спецификатора имеет соответствующий тип -доступа: - -- `public` - публичный доступ, поле или метод класса доступны извне -- `protected` - защищенный доступ, поля и методы доступны наследникам класса - и внутри класса -- `private` - приватный доступ, поля и методы доступны только внутри класса. - -Синтаксис внутри класса или структуры: `:` - -Указывать спецификаторы доступа можно произвольное число раз. - -```c++ -class User { -public: - /* some data and functions for everyone */ -protected: - /* some data and functions for children classes */ -private: - /* some data and functions inside class */ -}; -``` - -Приватные поля и методы будут недоступны снаружи, то есть **НЕЛЬЗЯ** к ним -обратится или вызвать через экземляр класс, используя операторы `.`, `->`. - -Всё содержимое класса по умолчанию имеет спецификатор доступа `private`, -несмотря на это часто принято явно указывать данный спецификатор, даже при -определении полей класса в самом начале тела класса. - -### Отличие класса и структуры - -Структура `struct` и класс `class` имеют одинаковые возможности в C++. - -Отличие заключается, что содержимое структуры по умолчанию имеет публичный -доступ `public`, а содержимое класса приватный `private` - -Структура нужна для взаимодействия с `legacy` кодом на языке C, а также для -публичных классов. - -Несмотря на одинаковые возможности, принято разделять структуру и класс -семантически. Так, структуру используют только с публичными полями, а класс -с приватными. Создавать классы и структуры со смешанным типом полей не -рекомендуется, так как это может быть не очевидно и не понятно программистам, -читающим код. - -### Пустой класс - -Пустой класс имеет размер 1 байт, поскольку объект такого класса можно создать -и необходимо иметь адресс данного объекта, чтобы иметь адресс, необходимо что-то -положить в память по определенному адресу. - -Чаще используется пустая структура. Такая структура может понадобитсья в качестве -именнованного тега. Пока будем просто считать, что иногда надо. - -### Поля класса - -Поля класса представляют собой внутренние переменные произвольного типа. -К полям класса внутри класса можно обращаться по имени. В качестве поля можно -использовать указатели и ссылки. - -В случае ссылок необходимо их инициализировоать при создании объекта. Например, -можно проинициализирвоать адресом объекта из глобальной области видимости. А еще -это можно сделать в списке инициализации при конструировании объекта. - -Существуют разные стили кода к именованию полей класса. Часто встречается: - -- `m_` - добавляют `m_` в качестве префикса к перименной (`m` - `member`) -- `_` - добавляют `_` в качестве постфикса к переменной. - -```c++ -// inside class -int m_value; -int value_; -``` - -Поля класса хранятся в классе и инициализируются в порядке их объявления. - -Поля уникальны для каждого экземпляра класса. - -### Инициализация полей значением по умолчанию - -Аналогично структурам рекомендуется всегда инициализировать поля внутри класса. - -```c++ -class Time { -private: - int hour_ = 0; - int minute_{0}; // uniform -}; -``` - -Иначе в полях класса также может лежать мусор. - -### Конструктор - -Конструктор это особый метод класса, который используется для конструирования -объекта. - -Синтаксис: `() {}` - -- `` - имя конструктора должно совпадать с именем класса -- `` - аргументы конструктора. -- `` - тело конструктора. - -В зависимости от аргументов конструктора выделяют различные типы конструктора. -Основные способы конструирования объекта: - -- Параметризованный конструктор -- Конструктор по умолчанию -- Конструктор копирования -- Копирующий оператор присваивания -- Конструктор перемещения -- Перемещающий оператор присваивания - -Важно понимать, что если конструкторы не определены, то компилятор самостоятельно -сгенерирует конструкторы. Но если определен, хотя бы один конструктор, то -компилятор скорее всего этого не сделает. - -Важно понимать, что при входе в тело конструктора все поля уже проинициализированы -и в теле может происходить только присваивание новых значений полям класса. -Следовательно, в теле уже нельзя изменить константное поле или инициализировать -ссылку. - -Проинициализировать константу и ссылку можно не только значением по -умолчанию или значением (адресом) переменной из глобальной области видимости. -Для этого в синтаксисе конструктора предусмотрен список инициализации. - -### Список инициализации полей класса - -Список инициализации полей (_member initializer list_) позволяет инициализировать -поля в момент создания объекта. В списке инициализации доступны аргументы -конструктора и имена полей класса. Список инициализации указывается между сигнатурой -и телом конструктора, и выглядит как перечисление после символа `:` через запятую -полей класса и внутри `()` или `{}` их инициализирующих значений. - -Синтаксис: `() : {}` - -- `` - список инициализации = `(), {}` - -```c++ -class InitList { -public: - InitList(int val) : a_(val), b_(val), c_(val) {} -public: - int a_; int b_; int c_; -}; -``` - -Причем имена полей класса и имена параметров могут полностью совпадать, конфликта -имен не будет, поскольку компилятор понимает, что нужно инициализировать поля. - -```c++ -class InitSameName { -public: - InitSameName(int a, int b, int c) : a(a), b(b), c(c) {} -public: - int a; int b; int c; -}; -``` - -Также, следует отметить, что в качестве инициализирующего значения, может использоваться -не только переменная или константа, но также выражение (_expression_) и результат -вызова функции. - -**ВАЖНО**, что инициализация происходит в порядке полей класса, и не зависит от -порядка в списке инициализации. Поэтому важно самостоятельно отслеживать -правильный порядок инициализации. - -```c++ -class BadOrderInit { -public: - BadOrderInit(int val) : c(val), b(c + 1), a(10) {} -public: - int a; int b; int c; -}; -``` -- `c` используется неинициализированной при инициализации `b` (**UB**) - -Если поля класса объявлены со значением по умолчанию, то они будут проигнорированы -для полей в списке инициализации. - -```c++ -class BadOrderInit { -public: - BadOrderInit(int val) : c(val), b(c + 1), a(10) {} -public: - int a = 7; int b = 7; int c = 7; -}; -``` -- значение `7` будет проигнорированно, по-прежнему **UB** - -Списки инициализации могут быть неполными. Тогда недостающие поля будут -сконструированы со значениями по умолчанию, а при их отсутствии инициализируются -мусором. - -```c++ -class BadOrderInitNoAB { -public: - BadOrderInitNoAB(int val) : c(val) {} -public: - int a; int b = 7; int c = 7; -}; -``` -- в поле `b` будет значение `7`, в `a` будет мусор - -Список инициализации позволяет сконструировать константное поле и поле ссылку извне: - -```c++ -class RefConst { -public: - RefConst(int value, int& ref, const double& cref) - : id_(value), ref_(ref), const_ref_(cref) {} -private: - const int id_; - int& ref_; - const double& const_ref_; -}; -``` - -### Параметризованный конструктор - -Конструктор, который имеет параметры (аргументы) называют параметризованным -конструктором (конструктором с параметрами). Аргументов может быть несколько -и они могут иметь значения по умолчанию, Таким образом, конструктор может -быть перегружен. - -```c++ -class Time { -public: - Time(int hour, int minute, int second) - : hour_(hour), minute_(minute), second_(second) {} -private: - int hour_, minute_, second_; -}; -``` - -Если конструктор имеет у всех аргументов значение по умолчанию, то такой -конструктор перегружает конструктор по умолчанию. - -```c++ -class Time { -public: - Time(int hour = 0, int minute = 0, int second = 0) - : hour_(hour), minute_(minute), second_(second) {} -private: - int hour_, minute_, second_; -}; -``` - -Для создания объекта класса необходим вызов конструктора. Синтаксис вызова констуктора: - -```c++ -Time t1(1, 1, 1); -Time t2{1, 1, 1}; -Time t3 = {1, 1, 1} -Time t4 = Time{1, 1, 1}; -Time t5 = Time(1, 1, 1); -``` - -Аналогично для всех его вариантов перегрузки. - -### Конструктор по умолчанию - -Конструктор по умолчанию представляет собой конструктор без аргументов. -Часто для простых класов конструктор имеет пустое тело. Удобно использовать -значение по умолчанию для инициализации. - -Синтаксис: `() {}` - -Часто имеет пустое тело для тривиальных случаев. - -Если не определен ни один конструктор, то компилятор самостоятельно сгенерирует -данный конструктор. - -```c++ -class DefaultCtor { -public: - DefaultCtor() {} -private: - int value = 0; -}; -``` - -Вызов конструктора: - -```c++ -DefaultCtor obj; -DefaultCtor obj2{}; -DefaultCtor obj3 = {}; -DefaultCtor obj4 = DefaultCtor{}; -DefaultCtor obj5 = DefaultCtor(); -``` -- во всех этих случаях вызовется только конструктор по умолчанию один раз - -### Конструктор копирования - -Конструктор копирования необходим для создания копии объекта из объекта того -же типа. Представляет собой конструктор, принимающий в качестве аргументов -константную ссылку того же типа, что и сам класс. - -Синтаксис: `(const & ) {}` - -```c++ -class Time { -public: - Time(const Time& other) - : hour_(other.hour_), minute_(other.minute_), second_(other.second_) {} -private: - int hour_, minute_, second_; -}; -``` - -Поля другого объекта того же класса доступны внутри методов класса даже если они -приватные. - -Вызывается конструктор копирования: - -- при передаче в функцию по значению -- при возврате объекта соответствующего значения по значению -- при конструировании одного объекта из другого - -```c++ -Time t; -Time t1 = t; // copy ctor -Time t2(t); // copy ctor -Time t3{t}; // copy ctor -``` - -### Указатель на себя `this` - -Внутри класса, в методах, в том числе конструкторах, можно получить указатель на -себя (объект класса, который вызывает данный метод) с помощью ключевого слова `this`. - -Можно использовать `this`, как в качестве значения по умолчанию, так и в списке -инициализации. - -```c++ -class Self { -public: - Self() : self(this) {}; - Self* GetPtr() { return self; } - Self& GetRef() { return *this; } -private: - Self* self = this; -}; -``` - -Можно считать что указатель на себя передается первым неявным аргументом в конструкторы, -методы и операторы класса. - -Через указатель можно явно обращаться к полям класса, но как правило, так не делают - -```c++ -// inside methods -this->self; -``` - -### Копирующий оператор присваивания - -Оператор присвания необходим при присваивании одного созданного объекта другому. -Если один из объектов не создан, то он не будет вызываться, а будет вызываться -конструктор копирования, даже если в инструкции есть `=`. - -Как правило, оператор возвращает ссылку на себя (экземпляр текущего класса), что -позволяет испоьзовать цепочку из операторов `=`. Для этого необходимо вернуть из -оператора разыменованный указатель на себя `return *this;`. - -Синтаксис: `& operator=(const & ) {}` - -Поскольку язык не запрещает присвоить объект самому себе, как правило, в копирующем -операторе присваивания выполняют проверку на самоприсваивание. Особенно это -критично для классов владеющих ресурсами (выделяющих память), что может привести -к **UB** - -```c++ -class Time { -public: - Time& operator=(const Time& other) { - if (this == &other) { - return *this; - } - hour_ = other.hour_; - minute_ = other.minute_; - second_ = other.second_; - return *this; - } -private: - int hour_, minute_, second_; -}; -``` - -Вызов оператора: - -```c++ -Time t1, t2, t3; -t1 = t2; // copy assignment -t1 = t1; // copy assignment -t1 = t2 = t3; // copy assignment -auto t4 = t1; // copy ctor (not a copy assignment!) -``` - -### Деструктор - -Особый метод, вызываемый перед разрушением объекта, когда заканчивается время -жизни объекта. - -Синтаксис: `~() {}` - -Если в конструкторе выполнялось ручное выделение ресурсов, то в деструкторе -необходимо обязательно освободить ресурсы. Иначе деструктор остается тривиальным -и генерируется компилятором по умолчанию. - -Деструкторы вызываются в обратном порядке по отношению к конструируемым объектам -при выходе из области видимости. Последний сконструированный объект, будет разрушен -первым. - -### Конструктор преобразования - -Конструктором преобразования называется конструктор, принимающий один аргумент -другого произвольного типа. Данный конструктор разрешает неявное преобразование -из указанного типа в тип класса. - -```c++ -class Integer { -private: - int value; -public: - Integer(int v) : value(v) {} - Integer(char c) : value(static_cast(c)) {} -}; -``` - -Таким образом, если функция принимает пользовательский класс, а класс имеет -конструктор преобразования от другого типа, то в функцию можно передать -непосредственно этот другой тип, произойдет неявное преобразование с помощью -соответствующего конструктора: - -```c++ -int DoSomething(Integer i) {} - -int main() { - Integer i{3}; - int value = 5; - char c = 'I'; - DoSomething(i); // OK - DoSomething(value); // OK - DoSomething(5); // OK - DoSomething(c); // OK - DoSomething('i'); // OK -} -``` - -**ВАЖНО** понимать, что при наличии конструктора присваивания из другого типа, -компилятор **НЕ** будет генеировать оператор присваивания из данного типа, его -необходимо определять самостоятельно. - -### Ключевое слово `explicit` - -Ключевое слово `explicit` используется как спецификатор перед именем конструктора -и позволяет запретить неявное преобразование и сообщает компилятору, что данный -конструктор можно вызывать только явно. - -```c++ -class Integer { -private: - int value; -public: - Integer(int v) : value(v) {} - Integer(char c) : value(static_cast(c)) {} - explicit Integer(double d) : value(static_cast(d)) {} -}; -``` - -Неявно такой конструктор вызвать нельзя: - -```c++ -//Integer i2 = 3.14; // compile error -Integer i3 = Integer{3.14}; // OK - -int DoSomething(Integer i) {} - -int main() { - double d = 3.14; - //DoSomething(d); // compile error - //DoSomething(3.14); // compile error - DoSomething(Integer{3.14}); // OK - DoSomething(Integer(3.14)); // OK -} -``` - -Также спецификатор `explicit` можно использовать с оператором преобразования, об этом -после знакомства с методами. - -### Конструктор от `std::initializer_list`(_C++11_) - -В C++11 появился контейнер список инициализации `std::initializer_list`, который -позволяет инициализировать класс набором элементов. Что вызывает неоднозначность -при наличии параметризированных конструкторов какой конструктор вызывать. - -Конструктор по умолчанию имеет приоритет перед конструктором от списка инициализации. - -Список инициализации имеет приоритет перед параметризированными конструкторами при -использовании `{}`. - -```c++ -class Vector { -public: - Vector() {}; - Vector(size_t count); - Vector(int a, int b); - Vector(std::initializer_list list); -private: - std::vector data; -}; -``` - -Вызов конструкторов: - -```c++ -Vector v = {1, 2, 3, 4, 5}; // ctor std::initializer_list -Vector v2{1, 2, 3}; // ctor std::initializer_list -Vector v3(10); // ctor Vector(size_t) -Vector v4{10}; // ctor std::initializer_list -Vector v5 = {10}; // ctor std::initializer_list -Vector v6(10, 20); // ctor Vector(int a, int b) -Vector v7{10, 20}; // ctor std::initializer_list -Vector v8 = {10, 20}; // ctor std::initializer_list -Vector v9 = 10; // ctor Vector(size_t) implicit cast -Vector v10; // default ctor -Vector v11{}; // default ctor -Vector v12 = {}; // default ctor -``` - -### Делегирующий конструктор (_C++11_) - -Делегирующий конструктор - конструктор, который на месте списка инициализации -использует другой конструктор данного класса. В таком случае можно указать только -один целевой конструктор, дополнительно списки инициализации указать нельзя. - -```c++ -class Time { -public: - Time(int hour, int minute, int second) - : hour_(hour), minute_(minute), second_(second) {} - Time(int hour) : Time(hour, 0, 0) {} -private: - int hour_, minute_, second_; -}; -``` - -Делегирующий конструктор **НЕ** может быть рекурсивным. - -### Ключевое слово `default` (_С++11_) - -С помощью ключевого слова `default` можно явно попросить компилятор сгенерировать -конструктор (деструктор), указав после сигнатуры `= default`. Это более выразительно, -чем писать `{}` для конструктора по умолчанию. Рекомендуется к использованию. - -```c++ -class Value { -public: - Value(int x) : x_(x) {} - Value() = default; - Value(const Value& other) = default; - Value(Value&& other) = default; - Value& operator=(const Value& other) = default; - Value& operator=(Value&& other) = default; - ~Value() = default; -private: - int x = 0; -}; -``` - -### Ключевое слово `delete` (_С++11_) - -С помощью ключевого слова `delete` можно явно попросить компилятор удалить функцию -(запретить её использование), указав после сигнатуры `= delete`. Это более выразительно, -чем прятать конструкторы в приватную область класса. Рекомендуется к использованию. - -Можно использовать не только для конструкторов, деструкторов, но и для любых методов, -операторов, шаблонных функций, функций вне классов. - -```c++ -class Value { -public: - Value(int x) : x_(x) {} - Value() = delete; - Value(const Value&) = delete; - Value& operator=(const Value&) = delete; -private: - int x = 0; -}; -``` - -Например, если класс не подразумевает сравнения на равенство или других операторов -можно явно указать для них `delete`. - -### Методы - -Внутри класса можно определять функции, которые могут работать с полями класса, в том -числе закрытыми. Данные функции называются методы. - -Синтаксис аналогичен определению обычным функциям. - -Публичный метод можно вызвать через операторы `.` для экземпляра и `->` для указателяю. - -Приватные методы, можно вызывать внутри класса. - -Можно вызывать методы в списках инициализации. Например, метод, который будет -контролировать допустимость значения или выполнять дополнительные преобразования. - -### Определение методов вне класса - -Методы можно объявить внутри класса, а определить снаружи класса. Содержимое -класса имеет свою область видимости. Для определения снаружи класса перед именем -конструктора, метода, оператора используется имя класса и оператор разрешения области -видимости `::` - -```c++ -class Time { -public: - Time(); - Time(int hours, int minutes, int seconds = 0); - int GetHours(); - void SetHours(int hours); -private: - int hours_ = 0; - int minutes_ = 0; - int seconds_ = 0; -}; - -Time::Time() = default; -Time::Time(int hours, int minutes, int seconds) - : hours_(hours), minutes_(minutes), seconds_(seconds) {} - -int Time::GetHours() { return hours; } -void Time::SetHours(int hours) { hours_ += hours; } -``` - -Аргументы методов, имеющие значения по умолчанию указываются только при объявлении, -при определении нельзя указать значения по умолчанию - -### CV-квалификация методов - -Методы могут иметь CV-квалификацию. Методы, которые не изменяют полей класса, а только -предоставляют информацию о них следует помечать квалификатором `const` после сигнатуры -и перед телом метода: - -```c++ -class Size { -public: - size_t GetSize() const { return size; }; - void AddSize(size_t size) { size_ += size; }; -private: - size_t size_ = 0; -}; -``` - -Методы помеченные квалификатором `const` можно вызывать у константных объектов класса. -Компилятор отслеживает, что в данном методе нет измененеий полей класса. - -Методы можно перегрузить только по квалификатору `const`. - -Не изменяет поля класса и может быть вызван для константного объекта: - -```c++ -int Class::foo() const; -``` - -Может изменять поля класса и может быть вызван для `volatile` объекта: - -```c++ -int Class::foo() volatile; -``` - -Может быть вызван как для `const`, так и для `volatile` объекта, так и для -`const volatile` объекта: - -```c++ -int Class::foo() const volatile; -``` - -### Оператор преобразования - -В классе возможно определить оператор преобразования, который позволяет преобразовывать -пользовательский класс в другой тип. - -Синтаксис: ` operator () const {}` - -- `` - можно запретить неявное преобразование -- `` - тип к которому выполняется приведение - -Рекомендуется помечать `const` поскольку данный оператор не должен менять полей класса -и вызываться от констант данного класса. - -Как правило рекомендуется запрещать неявное преобразование к типу (использовать -`explicit`), поскольку можно обнаружить много неожиданных мест в коде, где неявно -произведено преобразование. - -Исключением обычно является оператор `bool` для удобства использования в условиях. - -### Перегрузка операторов внутри класса - -Поскольку первым аргументом неявно передается ключевое слово `this`, то перегрузка -бинарных операторов внутри класса имеет один аргумент: - -```c++ -Class& operator+=(const Class& other); -Class& operator-=(const Class& other); -Class& operator*=(const Class& other); -Class& operator/=(const Class& other); -``` - -Операторы арифмесстических операций часто переопределяют на основе работы присваивающих -операторов: - -```c++ -Class operator+(const Class& other) const { - Class result = *this; // copy ctor - result += other; // operator += - return result; -} -``` - -Операторы префиксного и постфиксного инкремента/декремента переопределяются -следующим образом: - -```c++ -Class& operator++(); // ++obj -Class operator++(int); // obj++ -Class& operator--(); // --obj -Class operator--(int); // obj-- -``` -- постфиксный оператор возвращает копию, поэтому у возвращаемого значения нет `&` - -### Перегрузка операторов вне класса - -Операторы можно перегрузить вне класса, тогда сигнатура перегружаемого оператора -пишется в привычной манере. Но для реализации таких операторов у класса должны быть -методы задающие и считывающие значение полей (геттеры и сеттеры). Бывает, что их нет, -тогда перегрузить класс не получится или получится на основе определенных операторов -составного присваивания внутри класса. - -Перегрузка инкремента и декремента вне класса: - -```c++ -Class& operator++(const Class& obj); // ++obj -Class operator++(const Class& obj, int); // obj++ -Class& operator--(const Class& obj); // --obj -Class operator--(const Class& obj, int); // obj-- -``` - -### Ключевое слово `friend` - -Внутри класса с помощью ключевого слова `friend` (_friend declaration_) можно -объявить дружественную функцию, класс или дружественный метод другого класса. - -Сущности объявленные дружественными будут иметь доступ к `private` и `protected` -полям класса. - -Дружественность работает в одностороннем порядке. - -```c++ -friend void SomeMethod(int); -friend struct SomeStruct; -friend class SomeClass; -friend OtherClass; // C++11 -friend int OtherClass::Method(); -``` - -### Ключевое слово `mutable` - -Спецификатор типа `mutable` разрешает изменять поле класса, объявленное с ним, -даже в константных методах и для константных объектов. - -Например, это может быть поле представляющее собой счетчик операций и необходимо его -изменять даже в константном методе. - -Также может использоваться в лямбда-выражениях \ No newline at end of file diff --git a/04_week/04_class.pdf b/04_week/04_class.pdf deleted file mode 100644 index 50a488d9..00000000 Binary files a/04_week/04_class.pdf and /dev/null differ diff --git a/04_week/tasks/phasor/phasor.cpp b/04_week/tasks/phasor/phasor.cpp index 3ec1b9ad..f1bc37ff 100644 --- a/04_week/tasks/phasor/phasor.cpp +++ b/04_week/tasks/phasor/phasor.cpp @@ -1,10 +1,271 @@ +#include +#include +#include +#include +constexpr double eps_ = 1e-12; +constexpr double pi_ = std::numbers::pi; struct ExpTag {}; struct DegTag {}; struct AlgTag {}; - class Phasor { +public: + Phasor() = default; + Phasor(double A, double phi); + Phasor(double A, double phi, struct ExpTag); + Phasor(double A, double phi_deg, struct DegTag); + Phasor(double real, double imag, struct AlgTag); + Phasor(const Phasor& p); + Phasor(double real); + +public: + void SetPolar(double r, double phi); + void SetCartesian(double x, double y); + + double Magnitude() const; + double Phase() const; + double PhaseDeg() const; + + double Abs() const; + double Angle() const; + double AngleDeg() const; + + double Real() const; + double Imag() const; + + Phasor Conj() const; + Phasor Inv() const; + + Phasor operator+(const Phasor& other) const; + Phasor operator-(const Phasor& other) const; + Phasor operator*(const Phasor& other) const; + Phasor operator/(const Phasor& other) const; + + Phasor operator-() const; + + Phasor& operator+=(const Phasor& other); + Phasor& operator-=(const Phasor& other); + Phasor& operator*=(const Phasor& other); + Phasor& operator/=(const Phasor& other); + + bool operator==(const Phasor& other) const; + bool operator!=(const Phasor& other) const; + + Phasor& operator=(const Phasor& other); + + friend std::ostream& operator<<(std::ostream& os, const Phasor& p); + + friend Phasor const operator+(const double& real, const Phasor& p); + friend Phasor const operator-(const double& real, const Phasor& p); + friend Phasor const operator*(const double& real, const Phasor& p); + friend Phasor const operator/(const double& real, const Phasor& p); + +private: + double m_A = 0.; + double m_phi = 0.; +}; +Phasor::Phasor(double A, double phi) + : m_A(A), m_phi(phi) { + if (m_A < eps_) { + m_A = -m_A; + if (m_phi <= eps_) m_phi += pi_; + else m_phi -= pi_; + } + if (m_phi > pi_ || m_phi < -pi_) { + while(m_phi > pi_) { + m_phi -= 2 * pi_; + } + while (m_phi < -pi_) { + m_phi += 2 * pi_; + } + } + if (std::abs(m_phi + pi_) < eps_) m_phi *= -1; }; + +Phasor::Phasor(double A, double phi, struct ExpTag) + : Phasor(A, phi) {}; + +Phasor::Phasor(double A, double phi_deg, struct DegTag) + : Phasor(A, phi_deg * (pi_ / 180)) {}; + +Phasor::Phasor(double real, double imag, struct AlgTag) { + m_A = std::sqrt(real * real + imag * imag); + m_phi = std::atan(imag / real); + if (real < 0 && imag < 0) m_phi -= pi_; + else if (real < 0 && imag > 0) m_phi += pi_; +}; + +Phasor::Phasor(double real) : m_A(real) { + if (m_A < eps_) m_A = -m_A; +}; + +Phasor::Phasor(const Phasor& p) { + m_A = p.m_A; + m_phi = p.m_phi; +} + +Phasor Phasor::operator+(const Phasor& other) const { + double real = Real() + other.Real(); + double imag = Imag() + other.Imag(); + return Phasor(real, imag, AlgTag()); +} + +Phasor Phasor::operator-(const Phasor& other) const { + double real = Real() - other.Real(); + double imag = Imag() - other.Imag(); + return Phasor(real, imag, AlgTag()); +} + +Phasor Phasor::operator*(const Phasor& other) const { + Phasor res = *this; + res.m_A *= other.m_A; + res.m_phi += other.m_phi; + return res; +} + +Phasor Phasor::operator/(const Phasor& other) const { + Phasor res = *this; + res.m_A /= other.m_A; + res.m_phi -= other.m_phi; + return res; +} + +Phasor Phasor::operator-() const { + if (m_phi > 0) return Phasor(m_A, m_phi - std::numbers::pi, ExpTag()); + else return Phasor(m_A, m_phi + std::numbers::pi, ExpTag()); +} + +Phasor& Phasor::operator+=(const Phasor& other) { + double real = Real() + other.Real(); + double imag = Imag() + other.Imag(); + this->SetCartesian(real, imag); + return *this; +} + +Phasor& Phasor::operator-=(const Phasor& other) { + double real = Real() - other.Real(); + double imag = Imag() - other.Imag(); + this->SetCartesian(real, imag); + return *this; +} + +Phasor& Phasor::operator*=(const Phasor& other) { + m_A *= other.m_A; + m_phi += other.m_phi; + return *this; +} + +Phasor& Phasor::operator/=(const Phasor& other) { + m_A /= other.m_A; + m_phi -= other.m_phi; + return *this; +} + +bool Phasor::operator==(const Phasor& other) const { + if (std::abs(m_A - other.m_A) < eps_ && + std::abs(m_phi - other.m_phi) < eps_) return true; + return false; +} + +bool Phasor::operator!=(const Phasor& other) const { + if (std::abs(m_A - other.m_A) > eps_ || + std::abs(m_phi - other.m_phi) > eps_) return true; + return false; +} + +Phasor& Phasor::operator=(const Phasor& other) { + if (this == &other) return *this; + + m_A = other.m_A; + m_phi = other.m_phi; + return *this; +} + +void Phasor::SetPolar(double r, double phi) { + m_A = r; + m_phi = phi; +} + +void Phasor::SetCartesian(double x, double y) { + m_A = std::sqrt(x * x + y * y); + m_phi = std::atan(y / x); +} + +double Phasor::Magnitude() const { + return m_A; +} + +double Phasor::Phase() const { + return m_phi; +} + +double Phasor::PhaseDeg() const { + return m_phi * (180 / pi_); +} + +double Phasor::Abs() const { + return Magnitude(); +} + +double Phasor::Angle() const { + return Phase(); +} + +double Phasor::AngleDeg() const { + return PhaseDeg(); +} + +double Phasor::Real() const { + return m_A * cos(m_phi); +} + +double Phasor::Imag() const { + return m_A * sin(m_phi); +} + +Phasor Phasor::Conj() const { + double real = Real(); + double imag = -Imag(); + return Phasor(real, imag, AlgTag()); +} + +Phasor Phasor::Inv() const { + return Phasor(1 / m_A, -m_phi, ExpTag()); +} + +Phasor MakePhasorCartesian(double x, double y) { + return Phasor(x, y, AlgTag()); +} + +Phasor MakePhasorPolar(double r, double phi) { + return Phasor(r, phi, ExpTag()); +} + +Phasor MakePhasorPolarDeg(double r, double phi_deg) { + return Phasor(r, phi_deg, DegTag()); +} + +Phasor const operator+(const double& real, const Phasor& p) { + return Phasor(p.Real() + real, p.Imag(), AlgTag()); +} + +Phasor const operator-(const double& real, const Phasor& p) { + return Phasor(real - p.Real(), -p.Imag(), AlgTag()); +} + +Phasor const operator*(const double& real, const Phasor& p) { + return Phasor(p.m_A * real, p.m_phi, ExpTag()); +} + +Phasor const operator/(const double& real, const Phasor& p) { + return Phasor(real / p.m_A, -p.m_phi, ExpTag()); +} + +std::ostream& operator<<(std::ostream& os, const Phasor& p) { + os << std::showpoint << std::setprecision(5) << p.Magnitude() << "*e(j*" << p.PhaseDeg() << ") [" + << p.Real() << " + j*" << p.Imag() << "]"; + return os; +} diff --git a/04_week/tasks/queue/queue.cpp b/04_week/tasks/queue/queue.cpp index 2a9f8493..4beebd72 100644 --- a/04_week/tasks/queue/queue.cpp +++ b/04_week/tasks/queue/queue.cpp @@ -1,6 +1,145 @@ #include - +#include +#include class Queue { +public: + Queue(); + Queue(const std::vector& input_vec); + Queue(const std::initializer_list& input_list); + Queue(std::stack input_stack); + Queue(const size_t sizeQueue); + +public: + void Push(const int& num); + bool Pop(); + + int& Front(); + int& Back(); + const int& Front() const; + int Back() const; + + int Size() const; + void Clear(); + bool Empty() const; + void Swap(Queue& other); + + bool operator==(const Queue& other) const; + bool operator!=(const Queue& other) const; + +private: + void UpdateOutVecQueue(); + + std::vector m_in_vec = {}; + std::vector m_out_vec = {}; }; + +Queue::Queue() = default; + +Queue::Queue(const std::vector& input_vec) : m_in_vec(input_vec) {}; + +Queue::Queue(const std::initializer_list& input_list) + : m_in_vec(std::vector(input_list)) { +}; + +Queue::Queue(std::stack input_stack) { + m_in_vec.resize(input_stack.size()); + for (size_t i = m_in_vec.size(); i >= 1; --i) { + m_in_vec[i - 1] = input_stack.top(); + input_stack.pop(); + } +}; + +Queue::Queue(const size_t sizeQueue) { + m_in_vec.reserve(sizeQueue); +} + +void Queue::UpdateOutVecQueue() { + while(!m_in_vec.empty()) { + m_out_vec.push_back(m_in_vec.back()); + m_in_vec.pop_back(); + } + m_in_vec.shrink_to_fit(); +} + +void Queue::Push(const int& num) { + m_in_vec.push_back(num); +} + +bool Queue::Pop() { + if (!m_out_vec.empty()) { + m_out_vec.pop_back(); + return true; + } + + UpdateOutVecQueue(); + if (m_out_vec.empty()) return false; + m_out_vec.pop_back(); + return true; +} + +int& Queue::Front() { + if (!m_out_vec.empty()) return m_out_vec.back(); + return m_in_vec.front(); +} + +const int& Queue::Front() const { + if (!m_out_vec.empty()) return m_out_vec.back(); + return m_in_vec.front(); +} + +int& Queue::Back() { + if (!m_in_vec.empty()) return m_in_vec.back(); + return m_out_vec.front(); +} + +int Queue::Back() const { + if (!m_in_vec.empty()) return m_in_vec.back(); + return m_out_vec.front(); +} + +int Queue::Size() const { + return m_in_vec.size() + m_out_vec.size(); +} + +void Queue::Swap(Queue& other) { + if (this == &other) return; + + std::swap(m_in_vec, other.m_in_vec); + std::swap(m_out_vec, other.m_out_vec); +} + +void Queue::Clear() { + m_in_vec.resize(0); + m_out_vec.resize(0); +} + +bool Queue::Empty() const { + return (m_in_vec.empty() && m_out_vec.empty()); +} + +bool Queue::operator==(const Queue& other) const { + if (this == &other) return true; + + if (Size() != other.Size()) return false; + std::vector queue_this(Size()); + std::vector queue_other(Size()); + + for (size_t i = 0; i < queue_this.size(); ++i) { + if (i < m_out_vec.size()) + queue_this[i] = m_out_vec[m_out_vec.size() - 1 - i]; + if (i < m_in_vec.size()) + queue_this[i + m_out_vec.size()] = m_in_vec[i]; + if (i < other.m_out_vec.size()) + queue_other[i] = other.m_out_vec[other.m_out_vec.size() - 1 - i]; + if (i < other.m_in_vec.size()) + queue_other[i + other.m_out_vec.size()] = other.m_in_vec[i]; + if (queue_this[i] != queue_other[i]) return false; + } + return true; +} + +bool Queue::operator!=(const Queue& other) const { + return !(*this == other); +} \ No newline at end of file diff --git a/04_week/tasks/ring_buffer/ring_buffer.cpp b/04_week/tasks/ring_buffer/ring_buffer.cpp index e2b57ba2..8c2a3aee 100644 --- a/04_week/tasks/ring_buffer/ring_buffer.cpp +++ b/04_week/tasks/ring_buffer/ring_buffer.cpp @@ -1,6 +1,266 @@ #include - +#include class RingBuffer { +public: + RingBuffer(); + RingBuffer(const int& capacity); + RingBuffer(const int& capacity, const int& num); + RingBuffer(const std::initializer_list& init_list); + RingBuffer(const RingBuffer& buf); + +public: + void Push(const int& num); + bool TryPush(const int& num); + + void Pop(); + bool TryPop(int& num); + + int Size() const; + int Capacity() const; + + int& Front(); + int& Back(); + int Front() const; + int Back() const; + + bool Empty() const; + bool Full() const; + void Clear(); + void Resize(size_t new_capacity); + + std::vector Vector() const; + + int& operator[](const size_t& ind); + int operator[](const size_t& ind) const; + + RingBuffer& operator=(const RingBuffer& other); + +private: + size_t m_size = 0; + std::vector m_buffer; + std::vector::iterator m_first_ind = m_buffer.begin(); + std::vector::iterator m_last_ind = m_buffer.begin(); }; + +RingBuffer::RingBuffer() = default; + +RingBuffer::RingBuffer(const int& capacity) { + if (capacity <= 0) m_buffer.reserve(1); + else m_buffer.reserve(capacity); + m_first_ind = m_buffer.begin(); + m_last_ind = m_buffer.begin(); +} + +RingBuffer::RingBuffer(const int& capacity, const int& num) { + if (capacity <= 0) m_buffer.resize(1, num); + else m_buffer.resize(capacity, num); + m_size = m_buffer.size(); + m_first_ind = m_buffer.begin(); + m_last_ind = m_buffer.end() - 1; +} + +RingBuffer::RingBuffer(const std::initializer_list& init_list) + : m_size(init_list.size()), m_buffer(init_list) { + if (m_size == 0) { + m_buffer.reserve(1); + m_last_ind = m_buffer.begin(); + } + else m_last_ind = m_buffer.end() - 1; + m_first_ind = m_buffer.begin(); +}; + +RingBuffer::RingBuffer(const RingBuffer& buf) + : m_size(buf.m_size) { + m_buffer.reserve(buf.m_buffer.capacity()); + m_buffer = buf.m_buffer; + size_t d2last = static_cast(buf.m_last_ind - buf.m_buffer.begin()); + size_t d2first = static_cast(buf.m_first_ind - buf.m_buffer.begin()); + m_first_ind = m_buffer.begin() + d2first; + m_last_ind = m_buffer.begin() + d2last; +}; + +int& RingBuffer::operator[](const size_t& ind) { + if (m_size == 0 || ind >= m_size || ind >= m_buffer.size()) { + int* n = nullptr; + return *n; + } + + if (m_first_ind < m_last_ind) return *(m_first_ind + ind); + + size_t dist = std::distance(m_first_ind, m_buffer.end()); + if (ind >= dist) return m_buffer[ind - dist]; + else return *(m_first_ind + ind); +} + +int RingBuffer::operator[](const size_t& ind) const { + if (m_size == 0 || ind >= m_size || ind >= m_buffer.size()) { + int* n = nullptr; + return *n; + } + + size_t dist = 0; + if (m_first_ind < m_last_ind) return *(m_first_ind + ind); + else dist = static_cast(m_buffer.end() - m_first_ind); + + if (ind >= dist) return m_buffer[ind - dist]; + return *(m_first_ind + ind); +} + +RingBuffer& RingBuffer::operator=(const RingBuffer& other) { + if (&other == this) return *this; + + m_buffer = other.m_buffer; + m_buffer.reserve(other.m_buffer.capacity()); + m_first_ind = other.m_first_ind; + m_last_ind = other.m_last_ind; + m_size = other.m_size; + return *this; +} + +void RingBuffer::Push(const int& num) { + if (m_size == 0) { + ++m_size; + if (m_buffer.size() == 0) m_buffer.push_back(num); + m_first_ind = m_buffer.begin(); + *m_last_ind = num; + } + else { + if (m_size < m_buffer.capacity()) { + if (m_last_ind + 1 == m_buffer.end()) { + if (m_buffer.size() != m_buffer.capacity()) { + m_buffer.push_back(num); + ++m_last_ind; + } + else { + m_last_ind = m_buffer.begin(); + *m_last_ind = num; + } + } + else *(++m_last_ind) = num; + ++m_size; + } + else { + *m_first_ind = num; + m_last_ind = m_first_ind; + ++m_first_ind; + if (m_first_ind == m_buffer.end()) m_first_ind = m_buffer.begin(); + } + } +} + +bool RingBuffer::TryPush(const int& num) { + if (m_size == m_buffer.capacity()) return false; + Push(num); + return true; +} + +void RingBuffer::Pop() { + if (m_size != 0) { + --m_size; + ++m_first_ind; + if (m_first_ind == m_buffer.end()) m_first_ind = m_buffer.begin(); + } +} + +bool RingBuffer::TryPop(int& num) { + if (m_size == 0) return false; + num = Back(); + Pop(); + return true; +} + +void RingBuffer::Resize(size_t new_capacity) { + if (new_capacity == 0) new_capacity = 1; + std::vector new_buf; + + if (m_size <= new_capacity) { + new_buf.reserve(m_size); + for (size_t i = 0; i < m_size; ++i) { + new_buf.push_back((*this)[i]); + } + } + else { + size_t off = m_size - new_capacity; + new_buf.reserve(new_capacity); + for (size_t i = 0; i < new_capacity; ++i) { + new_buf.push_back((*this)[i + off]); + } + m_size = new_capacity; + } + + m_buffer.clear(); + m_buffer.shrink_to_fit(); + m_buffer.reserve(new_capacity); + m_buffer = new_buf; + m_first_ind = m_buffer.begin(); + m_last_ind = m_first_ind + (m_size - 1); +} + +void RingBuffer::Clear() { + m_size = 0; + m_first_ind = m_buffer.begin(); + m_last_ind = m_buffer.begin(); +} + +int& RingBuffer::Front() { + if (m_size != 0) return *m_last_ind; + int* n = nullptr; + return *n; +} + +int& RingBuffer::Back() { + if (m_size != 0) return *m_first_ind; + int* n = nullptr; + return *n; +} + +int RingBuffer::Front() const { + if (m_size != 0) return *m_last_ind; + int* n = nullptr; + return *n; +} + +int RingBuffer::Back() const { + if (m_size != 0) return *m_first_ind; + int* n = nullptr; + return *n; +} + +bool RingBuffer::Full() const { + return m_size == m_buffer.capacity(); +} + +bool RingBuffer::Empty() const { + return m_size == 0; +} + +int RingBuffer::Size() const { + return m_size; +} + +int RingBuffer::Capacity() const{ + return m_buffer.capacity(); +} + +std::vector RingBuffer::Vector() const { + std::vector res; + res.reserve(m_buffer.size()); + auto it = m_first_ind; + size_t d2first = static_cast(m_first_ind - m_buffer.begin()); + for (size_t i = 0, j = 0; j < m_size; ++i, ++j) { + if ((it + i) == m_buffer.end()) { + it -= d2first; + i = 0; + } + res.push_back(*(it + i)); + } + return res; +} + +void func(double one, double two) { + for(int i=0;i<2;i++){ + + }; +} \ No newline at end of file diff --git a/04_week/tasks/stack/stack.cpp b/04_week/tasks/stack/stack.cpp index 222e4ffc..58348a4a 100644 --- a/04_week/tasks/stack/stack.cpp +++ b/04_week/tasks/stack/stack.cpp @@ -1,6 +1,77 @@ #include - +#include class Stack { +public: + void Push(const int& num); + bool Pop(); + + int& Top(); + int Top() const; + + int Size() const; + void Clear(); + bool Empty() const; + + void Swap(Stack& other); + bool operator==(const Stack& other) const; + bool operator!=(const Stack& other) const; + +private: + std::vector stack; }; + +void Stack::Push(const int& num) { + stack.push_back(num); +} + +bool Stack::Pop() { + if (!stack.empty()) { + stack.pop_back(); + return true; + } + return false; +} + +int& Stack::Top() { + if (!stack.empty()) return stack.back(); +} + +int Stack::Top() const { + if (!stack.empty()) return stack.back(); +} + +void Stack::Clear() { + stack.clear(); +} + +int Stack::Size() const { + return stack.size(); +} + +void Stack::Swap(Stack& other) { + if (this == &other) return; + std::swap(stack, other.stack); +} + +bool Stack::Empty() const { + return stack.empty(); +} + +bool Stack::operator==(const Stack& other) const { + if (this == &other) return true; + + if (Size() != other.Size()) return false; + for (size_t i = 0; i < stack.size(); ++i) { + if (stack[i] != other.stack[i]) return false; + } + return true; +} + +bool Stack::operator!=(const Stack& other) const { + return !(*this == other); +} + + + diff --git a/05_week/tasks.zip b/05_week/tasks.zip new file mode 100644 index 00000000..5debfe5c Binary files /dev/null and b/05_week/tasks.zip differ diff --git a/05_week/tasks/cow_string/cow_string.cpp b/05_week/tasks/cow_string/cow_string.cpp index 34d59738..6fa5a6b3 100644 --- a/05_week/tasks/cow_string/cow_string.cpp +++ b/05_week/tasks/cow_string/cow_string.cpp @@ -1,6 +1,193 @@ #include #include +struct _String { + inline static size_t ref_count = 1; + char* data = nullptr; + size_t size = 0; +}; + class CowString { +public: + inline static size_t npos = -1; + + CowString(); + CowString(const char* cstr); + CowString(const std::string& str); + CowString(const CowString& other); + CowString(CowString&& other) noexcept; + ~CowString(); + CowString& operator=(const CowString& other); + CowString& operator=(CowString&& other) noexcept; + + size_t Size() const noexcept; + const char* ToCstr() const noexcept; + std::string ToString() const noexcept; + bool Empty() const noexcept; + size_t Find(std::string sub) const; + size_t Find(char c) const; + const char& operator[](size_t idx) const; + operator const char*() const; + + char& operator[](size_t idx); + CowString& Append(const char* cstr); + CowString& Append(const std::string& str); + CowString Substr(size_t pos, size_t size); + void Clear(); + +private: + void DeepCopy() noexcept; + + _String str_; +}; +CowString::CowString() { + str_.data = new char[]{""}; }; + +CowString::CowString(const char* cstr) { + if (cstr != nullptr) { + str_.data = new char[strlen(cstr) + 1]; + str_.size = strlen(cstr); + std::memcpy(str_.data, cstr, str_.size + 1); + } +} + +CowString::CowString(const std::string& str) : + CowString(str.c_str()) {} + +CowString::CowString(const CowString& other) { + ++str_.ref_count; + str_.size = other.str_.size; + str_.data = other.str_.data; +} + +CowString::CowString(CowString&& other) noexcept { + str_.data = other.str_.data; + str_.size = other.str_.size; + other.str_.data = nullptr; + other.str_.size = 0; +} + +CowString::~CowString() { + --str_.ref_count; + if (str_.ref_count == 0) { + delete[] str_.data; + } + str_.data = nullptr; +} + +CowString& CowString::operator=(const CowString& other) { + if (this != &other) { + ++str_.ref_count; + str_.data = other.str_.data; + str_.size = other.str_.size; + } + return *this; +} + +CowString& CowString::operator=(CowString&& other) noexcept { + if (this != &other) { + str_.data = other.str_.data; + str_.size = other.str_.size; + other.str_.data = nullptr; + other.str_.size = 0; + } + return *this; +} + +size_t CowString::Size() const noexcept { + return str_.size; +} + +const char* CowString::ToCstr() const noexcept { + return Empty() ? "" : str_.data; +} + +std::string CowString::ToString() const noexcept { + return std::string(ToCstr()); +} + +bool CowString::Empty() const noexcept { + return str_.size == 0; +} + +size_t CowString::Find(std::string sub) const { + if (sub.empty()) return 0; + + for (size_t i = 0; i < str_.size; ++i) { + if (str_.data[i] == sub[0] && sub.size() <= str_.size - i) { + bool match = true; + for (size_t j = 1; j < sub.size(); ++j) { + if (str_.data[i + j] != sub[j]) { + match = false; + break; + } + } + if (match) return i; + } + } + return CowString::npos; +} + +size_t CowString::Find(char c) const { + for (size_t i = 0; i < str_.size; ++i) { + if (str_.data[i] == c) return i; + } + return CowString::npos; +} + +const char& CowString::operator[](size_t idx) const { + return *(str_.data + idx); +} + +CowString::operator const char *() const { + return const_cast(str_.data); +} + +void CowString::DeepCopy() noexcept { + --str_.ref_count; + char* new_address = new char[str_.size + 1]{}; + std::memcpy(new_address, str_.data, str_.size + 1); + str_.data = new_address; +} + +char& CowString::operator[](size_t idx) { + DeepCopy(); + return *(str_.data + idx); +} + +CowString& CowString::Append(const char* cstr) { + if (strlen(cstr) == 0) return *(this); + --str_.ref_count; + char* new_address = new char[str_.size + strlen(cstr) + 1]{}; + std::memcpy(new_address, str_.data, str_.size); + std::memcpy(new_address + str_.size, cstr, strlen(cstr) + 1); + str_.data = new_address; + str_.size = str_.size + strlen(cstr); + return *(this); +} + +CowString& CowString::Append(const std::string& str) { + return Append(str.c_str()); +} + +CowString CowString::Substr(size_t pos = 0, size_t size = CowString::npos) { + CowString t = *this; + t.DeepCopy(); + if (pos >= t.str_.size) { + t.str_.data = nullptr; + t.str_.size = 0; + } + else { + t.str_.data += pos; + size <= t.str_.size - pos ? t.str_.size = size : t.str_.size -= pos; + *(t.str_.data + t.str_.size) = '\0'; + } + return t; +} + +void CowString::Clear() { + DeepCopy(); + str_.size = 0; +} \ No newline at end of file diff --git a/05_week/tasks/simple_vector/simple_vector.cpp b/05_week/tasks/simple_vector/simple_vector.cpp index 9b2ea971..f7777278 100644 --- a/05_week/tasks/simple_vector/simple_vector.cpp +++ b/05_week/tasks/simple_vector/simple_vector.cpp @@ -1,5 +1,244 @@ - +#include +#include class SimpleVector { +public: + SimpleVector(); + SimpleVector(size_t size); + SimpleVector(size_t size, int num); + SimpleVector(const std::initializer_list& lst); + SimpleVector(const SimpleVector& other); + SimpleVector(SimpleVector&& other) noexcept; + ~SimpleVector(); + + int& operator[](size_t idx) const; + bool operator==(const SimpleVector& right) const noexcept; + bool operator!=(const SimpleVector& right) const noexcept; + SimpleVector& operator=(const SimpleVector& other); + SimpleVector& operator=(SimpleVector&& other) noexcept; + + void Swap(SimpleVector& right) noexcept; + size_t Size() const noexcept; + size_t Capacity() const noexcept; + bool Empty() const noexcept; + const int* Data() const noexcept; + void PushBack(int input); + void PopBack(); + void Clear() noexcept; + void Resize(size_t new_size, int num); + void Reserve(size_t new_cap); + int* Insert(size_t idx, int num); + int* Insert(const int* pos, int num); + int* Erase(size_t idx); + int* Erase(const int* pos); + + int* begin() const; + int* end() const; + +private: + size_t m_capacity; + size_t m_size; + int* m_data; +}; + +SimpleVector::SimpleVector() : + m_capacity(0), + m_size(0), + m_data(new int[]{}){} + +SimpleVector::SimpleVector(size_t size) : + m_capacity(size), + m_size(size), + m_data(new int[size]{}) {} + +SimpleVector::SimpleVector(size_t size, int num) : + SimpleVector(size) { + for (size_t i = 0; i < m_size; ++i) { + m_data[i] = num; + } +} + +SimpleVector::SimpleVector(const std::initializer_list& lst) : + m_capacity(lst.size()), + m_size(lst.size()), + m_data(new int[m_size]) { + for (size_t i = 0; i < m_size; ++i) { + m_data[i] = *(lst.begin() + i); + } +} + +SimpleVector::SimpleVector(const SimpleVector& other) : + m_capacity(other.m_capacity), + m_size(other.m_size), + m_data(new int[m_size]) { + std::memcpy(m_data, other.m_data, m_size * sizeof(int)); +} + +SimpleVector& SimpleVector::operator=(const SimpleVector& other) { + if (this != &other) { + m_capacity = other.m_capacity; + m_size = other.m_size; + delete[] m_data; + m_data = new int[m_size]; + std::memcpy(m_data, other.m_data, m_size * sizeof(int)); + } + return *this; +} + +SimpleVector::SimpleVector(SimpleVector&& other) noexcept : + m_capacity(other.m_capacity), + m_size(other.m_size), + m_data(other.m_data) { + other.m_capacity = 0; + other.m_size = 0; + other.m_data = nullptr; +} + +SimpleVector& SimpleVector::operator=(SimpleVector&& other) noexcept { + if (this != &other){ + m_capacity = other.m_capacity; + m_size = other.m_size; + delete[] m_data; + m_data = other.m_data; + other.m_capacity = 0; + other.m_size = 0; + other.m_data = nullptr; + } + return *this; +} + +SimpleVector::~SimpleVector() { + delete[] m_data; + m_data = nullptr; +} + +int& SimpleVector::operator[](size_t idx) const { + return *(m_data + idx); +} + +bool SimpleVector::operator==(const SimpleVector& right) const noexcept { + if (this == &right) return true; + + if (m_size == right.m_size) { + for (size_t i = 0; i < m_size; ++i) { + if ((*this)[i] != right[i]) return false; + } + return true; + } + return false; +} + +bool SimpleVector::operator!=(const SimpleVector& right) const noexcept { + return !(*this == right); +} + +void SimpleVector::Swap(SimpleVector& right) noexcept { + if (this != &right) { + std::swap(m_capacity, right.m_capacity); + std::swap(m_size, right.m_size); + std::swap(m_data, right.m_data); + } +} + +size_t SimpleVector::Size() const noexcept { + return m_size; +} + +size_t SimpleVector::Capacity() const noexcept { + return m_capacity; +} + +bool SimpleVector::Empty() const noexcept { + return m_size == 0; +} + +const int* SimpleVector::Data() const noexcept { + return m_data; +} + +void SimpleVector::PushBack(int num) { + if (m_capacity == m_size) { + size_t new_cap = 2 * m_capacity; + if (new_cap == 0) ++new_cap; + Reserve(new_cap); + } + m_data[m_size++] = num; +} + +void SimpleVector::PopBack() { + if (!Empty()) --m_size; +} + +void SimpleVector::Clear() noexcept { + m_size = 0; +} + +void SimpleVector::Reserve(size_t new_cap) { + if (new_cap > m_capacity) { + m_capacity = new_cap; + int* new_address = new int[m_capacity]; + if (m_data != nullptr) { + std::memcpy(new_address, m_data, m_size * sizeof(int)); + delete[] m_data; + } + m_data = new_address; + } +} + +void SimpleVector::Resize(size_t new_size, int num = 0) { + if (new_size > m_capacity) { + Reserve(new_size); + for(size_t i = m_size; i < new_size; ++i) { + m_data[i] = num; + } + } + m_size = new_size; +} + +int* SimpleVector::Insert(size_t idx, int num) { + if (idx > m_size) return &m_data[m_size]; + if (m_size == m_capacity) { + size_t new_cap = 2 * m_capacity; + if (new_cap == 0) ++new_cap; + Reserve(new_cap); + } + for (size_t i = m_size; i > idx; --i) { + m_data[i] = m_data[i - 1]; + } + m_data[idx] = num; + ++m_size; + return &m_data[idx]; +} + +int* SimpleVector::Insert(const int* pos, int num) { + size_t idx = std::distance(Data(), pos); + return Insert(idx, num); +} + +int* SimpleVector::Erase(size_t idx) { + if (idx >= m_size) return &m_data[m_size]; + for (size_t i = idx; i < m_size - 1; ++i) { + std::swap(m_data[i], m_data[i + 1]); + } + PopBack(); + return &m_data[idx]; +} + +int* SimpleVector::Erase(const int* pos) { + size_t idx = std::distance(Data(), pos); + return Erase(idx); +} + +int* SimpleVector::begin() const { + return m_data; +} + +int* SimpleVector::end() const { + return m_data + m_size; +} + +void swap(SimpleVector& lft, SimpleVector& rht) { + lft.Swap(rht); +} + -}; \ No newline at end of file diff --git a/05_week/tasks/string_view/string_view.cpp b/05_week/tasks/string_view/string_view.cpp index 438c4536..fbd10be5 100644 --- a/05_week/tasks/string_view/string_view.cpp +++ b/05_week/tasks/string_view/string_view.cpp @@ -1,7 +1,120 @@ #include #include - class StringView { +public: + inline static size_t npos = -1; + + StringView(); + StringView(const std::string& str, size_t pos_sub, size_t len_sub); + StringView(const char* cstr); + StringView(const char* cstr, size_t len); + + const char& operator[](size_t idx) const; + const char* Data() const noexcept; + const char& Front() const noexcept; + const char& Back() const noexcept; + size_t Size() const noexcept; + size_t Length() const noexcept; + bool Empty() const noexcept; + void RemovePrefix(size_t count); + void RemoveSuffix(size_t count); + StringView Substr(size_t pos, size_t count) const; + size_t Find(char c, size_t pos) const; + size_t Find(StringView sub, size_t pos) const; + std::string ToString() const noexcept; + +private: + const char* data_ = nullptr; + size_t size_ = 0; +}; + +StringView::StringView() = default; + +StringView::StringView(const std::string& str, size_t pos_sub = 0, size_t len_sub = StringView::npos) { + if (pos_sub >= str.length()) StringView(); + else { + data_ = str.data() + pos_sub; + len_sub > str.length() ? size_ = str.length() - pos_sub : size_ = len_sub; + } +} + +StringView::StringView(const char* cstr, size_t len) : + data_(cstr) { + if (cstr == nullptr) size_ = 0; + else len > strlen(cstr) ? size_ = strlen(cstr) : size_ = len; +} + +StringView::StringView(const char* cstr) : + data_(cstr) { + cstr != nullptr ? size_ = strlen(cstr) : size_ = 0; +} + +const char& StringView::operator[](size_t idx) const { + return *(data_ + idx); +} + +const char* StringView::Data() const noexcept { + return data_; +} + +const char& StringView::Front() const noexcept { + return *data_; +} + +const char& StringView::Back() const noexcept { + return *(data_ + size_ - 1); +} + +size_t StringView::Size() const noexcept { + return size_; +} + +size_t StringView::Length() const noexcept { + return size_; +} + +bool StringView::Empty() const noexcept { + return size_ == 0; +} + +void StringView::RemovePrefix(size_t count) { + count > size_ ? (data_ += size_, size_ = 0) : (data_ += count, size_ -= count); +} + +void StringView::RemoveSuffix(size_t count) { + count > size_ ? size_ = 0 : size_ -= count; +} + +std::string StringView::ToString() const noexcept { + return data_ != nullptr ? std::string(data_, size_) : std::string(""); +} + +StringView StringView::Substr(size_t pos, size_t count = StringView::npos) const { + return (pos < size_) ? StringView(data_ + pos, count) : StringView(); +} + +size_t StringView::Find(char c, size_t pos = 0) const { + for (auto i = pos; i < size_; ++i) { + if (data_[i] == c) return i; + } + return StringView::npos; +} -}; \ No newline at end of file +size_t StringView::Find(StringView sub, size_t pos = 0) const { + if (sub.Empty()) return 0; + + for (size_t i = pos; i < size_; ++i) { + if (data_[i] == sub[0] && sub.Size() <= size_ - i) { + bool match = true; + for (size_t j = 1; j < sub.Size(); ++j) { + if (data_[i + j] != sub[j]) { + match = false; + break; + } + } + if (match) return i; + } + } + return StringView::npos; +} \ No newline at end of file diff --git a/05_week/tasks/tracer/tracer.cpp b/05_week/tasks/tracer/tracer.cpp index 2ccfb417..ec52e524 100644 --- a/05_week/tasks/tracer/tracer.cpp +++ b/05_week/tasks/tracer/tracer.cpp @@ -2,5 +2,104 @@ class Tracer { +public: + inline static size_t count = 0; + inline static size_t default_ctor = 0; + inline static size_t str_ctor = 0; + inline static size_t copy_ctor = 0; + inline static size_t move_ctor = 0; + inline static size_t copy_assign = 0; + inline static size_t move_assign = 0; + inline static size_t dtor = 0; + inline static size_t alive = 0; -}; \ No newline at end of file + Tracer(); + Tracer(const std::string& name); + Tracer(const Tracer& orig); + Tracer(Tracer&& orig) noexcept; + ~Tracer(); + Tracer& operator=(const Tracer& orig); + Tracer& operator=(Tracer&& orig) noexcept; + + size_t Id() const noexcept; + const std::string& Name() const noexcept; + const char* Data() const noexcept; + static void ResetStats() noexcept; + +private: + size_t m_id; + std::string m_name; +}; + +Tracer::Tracer() : + m_id(++count), + m_name("obj_" + std::to_string(m_id)) { + ++default_ctor; + ++alive; +} + +Tracer::Tracer(const std::string& name) : + m_id(++count), + m_name(name + '_' + std::to_string(m_id)) { + ++str_ctor; + ++alive; +} + +Tracer::Tracer(const Tracer& orig) : + m_id(++count), + m_name(orig.m_name) { + ++copy_ctor; + ++alive; +} + +Tracer::Tracer(Tracer&& orig) noexcept : + m_id(++count), + m_name(std::move(orig.m_name)) { + ++move_ctor; + ++alive; +} + +Tracer::~Tracer() { + ++dtor; + --alive; +} + +Tracer& Tracer::operator=(const Tracer& orig) { + if (this != &orig) { + ++copy_assign; + m_name = orig.m_name; + } + return *this; +} + +Tracer& Tracer::operator=(Tracer&& orig) noexcept { + if (this != &orig) { + ++move_assign; + m_name = std::move(orig.m_name); + } + return *this; +} + +size_t Tracer::Id() const noexcept { + return m_id; +} + +const std::string& Tracer::Name() const noexcept { + return m_name; +} + +const char* Tracer::Data() const noexcept { + return m_name.data(); +} + +void Tracer::ResetStats() noexcept { + count = 0; + default_ctor = 0; + str_ctor = 0; + copy_ctor = 0; + move_ctor = 0; + copy_assign = 0; + move_assign = 0; + dtor = 0; + alive = 0; +} \ No newline at end of file