diff --git a/01_week/tasks/addition/addition.cpp b/01_week/tasks/addition/addition.cpp index 92872802..f8fd582d 100644 --- a/01_week/tasks/addition/addition.cpp +++ b/01_week/tasks/addition/addition.cpp @@ -1,7 +1,8 @@ #include #include - int64_t Addition(int a, int b) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + int64_t a_64 = static_cast(a); + int64_t b_64 = static_cast(b); + return a_64 + b_64; +} diff --git a/01_week/tasks/char_changer/char_changer.cpp b/01_week/tasks/char_changer/char_changer.cpp index 3a7344d9..e8ce4172 100644 --- a/01_week/tasks/char_changer/char_changer.cpp +++ b/01_week/tasks/char_changer/char_changer.cpp @@ -1,7 +1,72 @@ #include #include +#include +const char a = 'a'; +const char A = 'A'; +const char dif_letters = static_cast(a) - static_cast(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 (static_cast(std::isdigit(array[i]))) { + array[i] = '*'; + } + else if (static_cast(std::islower(array[i]))) { + array[i] -= dif_letters; + } + else if (static_cast(std::ispunct(array[i]))) { + array[i] = '_'; + } + else if (static_cast(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..374b3ff7 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,45 @@ 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 = "["; + + 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..d2cc348d 100644 --- a/01_week/tasks/length_lit/length_lit.cpp +++ b/01_week/tasks/length_lit/length_lit.cpp @@ -0,0 +1,68 @@ +constexpr long double operator""_m_to_in(long double m) { + return m / 0.0254; +} + +constexpr long double operator""_m_to_ft(long double m) { + return m / 0.3048; +} + +constexpr long double operator""_m_to_m(long double m) { + return m; +} + +constexpr long double operator""_m_to_cm(long double m) { + return m * 100; +} + +// foots +constexpr long double operator""_ft_to_in(long double ft) { + return ft * (0.3048 / 0.0254); +} + +constexpr long double operator""_ft_to_ft(long double ft) { + return ft; +} + +constexpr long double operator""_ft_to_m(long double ft) { + return ft * 0.3048; +} + +constexpr long double operator""_ft_to_cm(long double ft) { + return ft * 30.48; +} + + +// 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 * (0.0254 / 0.3048); +} + +constexpr long double operator""_in_to_m(long double in) { + return in * 0.0254; +} + +constexpr long double operator""_in_to_cm(long double in) { + return in * 2.54; +} + + +// cm +constexpr long double operator""_cm_to_in(long double cm) { + return cm / 2.54; +} + +constexpr long double operator""_cm_to_ft(long double cm) { + return cm / 30.48; +} + +constexpr long double operator""_cm_to_m(long double cm) { + return cm / 100; +} + +constexpr long double operator""_cm_to_cm(long double cm) { + return cm; +} diff --git a/01_week/tasks/print_bits/print_bits.cpp b/01_week/tasks/print_bits/print_bits.cpp index a48a43c1..94c521fd 100644 --- a/01_week/tasks/print_bits/print_bits.cpp +++ b/01_week/tasks/print_bits/print_bits.cpp @@ -1,7 +1,25 @@ -#include -#include - +#include +#include void PrintBits(long long value, size_t bytes) { - throw std::runtime_error{"Not implemented"}; + std::string str_bset = ""; + + auto bits = bytes * 8; + + for (size_t i = 0; i < bits; ++i) { + auto b_i = (value >> i) & 1u; + + if (static_cast(b_i)) str_bset += "1"; + else str_bset += "0"; + + if (i % 4 == 3 && i != bits - 1) { + str_bset += '\''; + } + } + + str_bset += "b0"; + + std::reverse(str_bset.begin(), str_bset.end()); + + std::cout << str_bset << "\n"; } diff --git a/01_week/tasks/quadratic/quadratic.cpp b/01_week/tasks/quadratic/quadratic.cpp index abf7d632..ce61fff2 100644 --- a/01_week/tasks/quadratic/quadratic.cpp +++ b/01_week/tasks/quadratic/quadratic.cpp @@ -1,6 +1,91 @@ #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 ? true : false); + bool b_is_Zero = (b == 0 ? true : false); + bool c_is_Zero = (c == 0 ? true : false); + + std::cout << std::setprecision(6); + + if (a_is_Zero) { + if (b_is_Zero) { + if (c_is_Zero) { + std::cout << "infinite solutions"; + } + else { + std::cout << "no solutions"; + } + } + else { + if (c_is_Zero){ + std::cout << c; + } + else{ + x_1 = static_cast(-c) / static_cast(b); + std::cout << x_1; + } + } + + return; + } + else { + if (b_is_Zero){ + if (c_is_Zero) { + std::cout << c; + } + else { + if (a * c < 0) { + x_1 = std::sqrt(static_cast(-c) / static_cast(a)); + x_2 = -x_1; + + if (x_1 > x_2) std::swap(x_1, x_2); + + std::cout << x_1 << " " << x_2; + } + else std::cout << "no solutions"; + } + return; + } + else if (c_is_Zero) { + x_1 = static_cast(0); + x_2 = static_cast(-b) / static_cast(a); + + if (x_1 > x_2) std::swap(x_1, x_2); + + std::cout << x_1 << " " << x_2; + + return; + } + } + + double b_d = static_cast(b); + double a_d = static_cast(a); + double c_d = static_cast(c); + + double D_2 = b_d * b_d - 4 * a_d * c_d; + double eps = 1e-14; + + if (D_2 < 0) { + std::cout << "no solutions"; + return; + } + else if (D_2 < eps) { + x_1 = -b_d / (2 * a_d); + std::cout << x_1; + } + else { + double D = static_cast(std::sqrt(D_2)); + + x_1 = (-b_d + D) / (2 * a_d); + x_2 = (-b_d - D) / (2 * a_d); + + if (x_1 > x_2) std::swap(x_1, x_2); + + std::cout << x_1 << " " << x_2; + } +} diff --git a/01_week/tasks/rms/rms.cpp b/01_week/tasks/rms/rms.cpp index 6882f0a9..78aa8968 100644 --- a/01_week/tasks/rms/rms.cpp +++ b/01_week/tasks/rms/rms.cpp @@ -1,7 +1,17 @@ -#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 == NULL) return static_cast(0.0); + + if (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 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..e0cbe294 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(double a, double b, + double (**operations)(double, 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..7e56cd7f 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,16 @@ #include - -/* return_type */ FindLastElement(/* ptr_type */ begin, /* ptr_type */ end, /* func_type */ predicate) { - throw std::runtime_error{"Not implemented"}; +int* FindLastElement(const int* begin, const int* end, bool(*predicate)(int)) { + + if (predicate == nullptr || + begin == nullptr || + end == nullptr || + std::distance(begin, end) < 0) + return const_cast(end); + + for(int* it = const_cast(end - 1); it != begin - 1; --it){ + if (predicate(*it)) return it; + } + + return const_cast(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..19b767fb 100644 --- a/02_week/tasks/little_big/little_big.cpp +++ b/02_week/tasks/little_big/little_big.cpp @@ -1,10 +1,87 @@ #include +#include +#include +void PrintMemory(int num, bool flag_rvrs = false) { + void* address_num = # + char* num_ptr_char = static_cast(address_num); -void PrintMemory(int /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; + std::string byteset = ""; + int size_int = sizeof(int); + for (int j = 0; j < size_int; ++j) { + unsigned char temp = *(num_ptr_char + j); + size_t count_hex_in_byte = 2; + std::string byte = ""; + + for (size_t i = 0; i < count_hex_in_byte; ++i) { + auto power = static_cast(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.append(1, hex_conv); + } + byteset.append(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, static_cast("0x")); + std::cout << byteset << "\n"; } -void PrintMemory(double /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +void PrintMemory(double num, bool flag_rvrs = false) { + void* address_num = # + char* num_ptr_char = static_cast(address_num); + + std::string byteset = ""; + int size_double = sizeof(double); + for (int j = 0; j < size_double; ++j) { + unsigned char temp = *(num_ptr_char + j); + size_t count_hex_in_byte = 2; + std::string byte = ""; + + for (size_t i = 0; i < count_hex_in_byte; ++i) { + auto power = static_cast(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.append(1, hex_conv); + } + byteset.append(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, static_cast("0x")); + std::cout << byteset << "\n"; } \ No newline at end of file diff --git a/02_week/tasks/longest/longest.cpp b/02_week/tasks/longest/longest.cpp index 04b3c354..b23df42d 100644 --- a/02_week/tasks/longest/longest.cpp +++ b/02_week/tasks/longest/longest.cpp @@ -1,6 +1,35 @@ #include +char* FindLongestSubsequence(const char* begin, const char* end, size_t& count) { + + if (begin == nullptr || + end == nullptr || + std::distance(begin, end) <= 0){ + count = 0; + return nullptr; + } + + auto res_ind = const_cast(begin); + auto it = const_cast(begin); + + size_t curr_count = 1; + count = 1; + + for (; it != end - 1; ++it){ + if (*it == *(it + 1)) ++curr_count; + else { + if (count < curr_count) { + count = curr_count; + res_ind = it - (curr_count - 1); + } + curr_count = 1; + } + } + + if (count < curr_count) { + count = curr_count; + res_ind = const_cast(end - curr_count); + } -/* return_type */ FindLongestSubsequence(/* ptr_type */ begin, /* ptr_type */ end, /* type */ count) { - throw std::runtime_error{"Not implemented"}; + 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..7fb62f70 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 = const_cast(begin); + auto _end = const_cast(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..591ca54e 100644 --- a/03_week/tasks/data_stats/data_stats.cpp +++ b/03_week/tasks/data_stats/data_stats.cpp @@ -1,11 +1,33 @@ #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]) * + static_cast(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..aa1b435f 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,88 @@ struct StudentInfo { int score; unsigned course; Date birth_date; -}; \ No newline at end of file +}; + +bool operator>(const Date& date1, const Date& date2) { + if (date1.year > date2.year) return true; + else if (date1.year == date2.year){ + if (date1.month > date2.month) return true; + else if (date1.month == date2.month) { + if (date1.day > date2.day) return true; + } + } + return false; +} + +bool operator<(const Date& date1, const Date& date2) { + if (date1.year < date2.year) return true; + else if (date1.year == date2.year){ + if (date1.month < date2.month) return true; + else if (date1.month == date2.month) { + if (date1.day < date2.day) return true; + } + } + return false; +} + +bool operator>=(const Date& date1, const Date& date2) { +if (date1.year > date2.year) return true; + else if (date1.year == date2.year){ + if (date1.month > date2.month) return true; + else if (date1.month == date2.month) { + if (date1.day >= date2.day) return true; + } + } + return false; +} + +bool operator<=(const Date& date1, const Date& date2) { + if (date1.year < date2.year) return true; + else if (date1.year == date2.year){ + if (date1.month < date2.month) return true; + else if (date1.month == date2.month) { + if (date1.day <= date2.day) return true; + } + } + return false; +} + +bool operator==(const Date& date1, const Date& date2) { + return date1.year == date2.year && + date1.month == date2.month && + date1.day == date2.day; +} + +bool operator!=(const Date& date1, const Date& date2) { + return date1.year != date2.year || + date1.month != date2.month || + date1.day != date2.day; +} + +bool operator<(const StudentInfo& s1, const StudentInfo& s2) { + if (std::tie(s1.mark) > std::tie(s2.mark)) return true; + else if (std::tie(s1.mark) == std::tie(s2.mark)) { + if (s1.score < s2.score) return true; + else if (s1.score == s2.score) { + if (s1.course > s2.course) return true; + else if (s1.course == s2.course) { + if (s1.birth_date < s2.birth_date) return true; + } + } + } + return false; +} + +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) { + if (std::tie(s1.mark) != std::tie(s2.mark) || + s1.score != s2.score || + s1.course != s2.course || + s1.birth_date != s2.birth_date) + return true; + return false; +} + 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..86ae77a2 100644 --- a/03_week/tasks/filter/filter.cpp +++ b/03_week/tasks/filter/filter.cpp @@ -1,6 +1,17 @@ #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)) { + auto temp = *it; + *it = *last_correct_it; + *last_correct_it = temp; + ++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..f9ca7aa9 100644 --- a/03_week/tasks/minmax/minmax.cpp +++ b/03_week/tasks/minmax/minmax.cpp @@ -1,6 +1,23 @@ #include +#include +typedef std::vector vec_i_t; +typedef std::vector::const_iterator cit_t; -/* return_type */ MinMax(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::pair MinMax(const vec_i_t& 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..22f2c218 100644 --- a/03_week/tasks/range/range.cpp +++ b/03_week/tasks/range/range.cpp @@ -1,7 +1,20 @@ #include #include - -std::vector Range(int from, int to, int step) { - throw std::runtime_error{"Not implemented"}; -} +std::vector Range(int from, int to, int step = 1) { + if ((to == from) || + ((to > from) && (step <= 0)) || + ((from > to) && (step >= 0))) + 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 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..dd785440 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 = this->Real() + other.Real(); + double imag = this->Imag() + other.Imag(); + return Phasor(real, imag, AlgTag()); +} + +Phasor Phasor::operator-(const Phasor& other) const { + double real = this->Real() - other.Real(); + double imag = this->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 = this->Real() + other.Real(); + double imag = this->Imag() + other.Imag(); + this->SetCartesian(real, imag); + return *this; +} + +Phasor& Phasor::operator-=(const Phasor& other) { + double real = this->Real() - other.Real(); + double imag = this->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 = this->Real(); + double imag = -this->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..41da26ff 100644 --- a/04_week/tasks/queue/queue.cpp +++ b/04_week/tasks/queue/queue.cpp @@ -1,6 +1,211 @@ #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 int sizeQueue); +public: + void Push(const int& num); + bool Pop(); + + int& Front(); + int& Back(); + 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(); + friend void SwapVecs(std::vector& v1, std::vector& v2, size_t min_size); + + 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(static_cast>(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 int sizeQueue) { + m_in_vec.reserve(sizeQueue); +} + +void Queue::UpdateOutVecQueue() { + size_t size = m_in_vec.size(); + if (size == 0) return; + for (size_t i = 0; i < size; ++i) { + m_out_vec.push_back(m_in_vec[m_in_vec.size() - 1]); + 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.size() != 0) { + m_out_vec.pop_back(); + return true; + } + else { + UpdateOutVecQueue(); + if (m_out_vec.size() == 0) return false; + m_out_vec.pop_back(); + return true; + } +} + +int& Queue::Front() { + if (m_out_vec.size() != 0) return m_out_vec[m_out_vec.size() - 1]; + else if (m_in_vec.size() != 0) return m_in_vec[0]; + else { + int trash = std::rand(); + int& ref_trash = trash; + return ref_trash; + } +} + +int Queue::Front() const { + if (m_out_vec.size() != 0) return m_out_vec[m_out_vec.size() - 1]; + else if (m_in_vec.size() != 0) return m_in_vec[0]; + return 0; +} + +int& Queue::Back() { + if (m_in_vec.size() != 0) return m_in_vec[m_in_vec.size() - 1]; + else if (m_out_vec.size() != 0) return m_out_vec[0]; + else { + int trash = std::rand(); + int& ref_trash = trash; + return ref_trash; + } +} + +int Queue::Back() const { + if (m_in_vec.size() != 0) return m_in_vec[m_in_vec.size() - 1]; + else if (m_out_vec.size() != 0) return m_out_vec[0]; + return 0; +} + +int Queue::Size() const { + return m_in_vec.size() + m_out_vec.size(); +} + +void SwapVecs(std::vector& v1, std::vector& v2, size_t min_size) { + v2.resize(v1.size()); + for (size_t i = 0; i < v1.size(); ++i) { + std::swap(v1[i], v2[i]); + } + v1.resize(min_size); + v1.shrink_to_fit(); +} + +void Queue::Swap(Queue& other) { + if (this == &other) return; + + size_t min_size_in = m_in_vec.size(); + size_t min_size_out = m_out_vec.size(); + + if (min_size_in >= other.m_in_vec.size()) { + min_size_in = other.m_in_vec.size(); + SwapVecs(m_in_vec, other.m_in_vec, min_size_in); + } + else { + SwapVecs(other.m_in_vec, m_in_vec, min_size_in);; + } + + if (min_size_out >= other.m_out_vec.size()) { + min_size_out = other.m_out_vec.size(); + SwapVecs(m_out_vec, other.m_out_vec, min_size_out); + } + else { + SwapVecs(other.m_out_vec, m_out_vec, min_size_out);; + } +} + +void Queue::Clear() { + m_in_vec.resize(0); + m_out_vec.resize(0); +} + +bool Queue::Empty() const { + return (m_in_vec.size() == 0 && + m_out_vec.size() == 0); +} + +bool Queue::operator==(const Queue& other) const { + if (this == &other) return true; + + std::vector queue_this(m_in_vec.size() + m_out_vec.size()); + std::vector queue_other(other.m_in_vec.size() + other.m_out_vec.size()); + + if (queue_this.size() != queue_other.size()) return false; + + 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 { + if (this == &other) return false; + + std::vector queue_this(m_in_vec.size() + m_out_vec.size()); + std::vector queue_other(other.m_in_vec.size() + other.m_out_vec.size()); + + if (queue_this.size() != queue_other.size()) return true; + + 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 true; + } + return false; +} \ 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..1cfbd7e1 100644 --- a/04_week/tasks/ring_buffer/ring_buffer.cpp +++ b/04_week/tasks/ring_buffer/ring_buffer.cpp @@ -1,6 +1,260 @@ #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(int 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; + this->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 = this->Back(); + this->Pop(); + return true; +} + +void RingBuffer::Resize(int new_capacity) { + if (new_capacity <= 0) new_capacity = 1; + std::vector new_buf; + + if (m_size <= static_cast(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 < static_cast(new_capacity); ++i) { + new_buf.push_back((*this)[i + off]); + } + m_size = static_cast(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; +} \ No newline at end of file diff --git a/04_week/tasks/stack/stack.cpp b/04_week/tasks/stack/stack.cpp index 222e4ffc..6f378395 100644 --- a/04_week/tasks/stack/stack.cpp +++ b/04_week/tasks/stack/stack.cpp @@ -1,6 +1,114 @@ #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: + friend void SwapVecs(std::vector& v1, std::vector& v2, size_t min_size); + + std::vector stack; }; + +void Stack::Push(const int& num) { + stack.push_back(num); +} + +bool Stack::Pop() { + if (stack.size() != 0) { + stack.pop_back(); + return true; + } + return false; +} + +int& Stack::Top() { + if (stack.size() != 0) return stack[stack.size() - 1]; + else { + int trash = std::rand(); + int& ref_trash = trash; + return ref_trash; + } +} + +int Stack::Top() const { + if (stack.size() != 0) return stack[stack.size() - 1]; + else { + int trash = std::rand(); + int& ref_trash = trash; + return ref_trash; + } +} + +void Stack::Clear() { + stack.resize(0); + stack.shrink_to_fit(); +} + +int Stack::Size() const { + return stack.size(); +} + +void SwapVecs(std::vector& v1, std::vector& v2, size_t min_size) { + v2.resize(v1.size()); + for (size_t i = 0; i < v1.size(); ++i) { + std::swap(v1[i], v2[i]); + } + v1.resize(min_size); + v1.shrink_to_fit(); +} + +void Stack::Swap(Stack& other) { + if (this == &other) return; + + size_t min_size = stack.size(); + + if (min_size >= other.stack.size()) { + min_size = other.stack.size(); + SwapVecs(stack, other.stack, min_size); + } + else { + SwapVecs(other.stack, stack, min_size); + } +} + +bool Stack::Empty() const { + return stack.size() == 0; +} + +bool Stack::operator==(const Stack& other) const { + if (this == &other) return true; + + if (stack.size() != other.stack.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 { + if (this == &other) return false; + + if (stack.size() != other.stack.size()) return true; + for (size_t i = 0; i < stack.size(); ++i) { + if (stack[i] != other.stack[i]) return true; + } + return false; +} + + +