kutuzzzov

Исключения и пространство имен 2

Nov 5th, 2025 (edited)
834
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 20.60 KB | None | 0 0
  1. ## **Часть 1: Исключения**
  2.  
  3. ---
  4.  
  5. ### **Задача 1: Обработка неправильного формата даты**
  6.  
  7. **Описание:** Напишите программу, которая принимает строку в формате "DD/MM/YYYY" и проверяет, является ли она корректной датой (например, 30/02/2023 — некорректно). Если формат неверен или дата невозможна, выбросите исключение.
  8.  
  9. **Решение:**
  10.  
  11. ```cpp
  12. #include <iostream>
  13. #include <string>
  14. #include <stdexcept>
  15. #include <sstream>
  16.  
  17. void validateDate(const std::string& dateStr) {
  18.     if (dateStr.size() != 10 || dateStr[2] != '/' || dateStr[5] != '/') {
  19.         throw std::invalid_argument("Неверный формат даты. Используйте DD/MM/YYYY.");
  20.     }
  21.  
  22.     int day, month, year;
  23.     char sep1, sep2;
  24.     std::istringstream iss(dateStr);
  25.     iss >> day >> sep1 >> month >> sep2 >> year;
  26.  
  27.     if (iss.fail() || day < 1 || day > 31 || month < 1 || month > 12) {
  28.         throw std::invalid_argument("Некорректные значения дня или месяца.");
  29.     }
  30.  
  31.     // Простая проверка: февраль не может иметь 30 дней
  32.     if (month == 2 && day > 29) {
  33.         throw std::invalid_argument("Февраль не может иметь более 29 дней.");
  34.     }
  35.     std::cout << "Дата корректна: " << dateStr << std::endl;
  36. }
  37.  
  38. int main() {
  39.     std::string input;
  40.     std::cout << "Введите дату в формате DD/MM/YYYY: ";
  41.     std::getline(std::cin, input);
  42.  
  43.     try {
  44.         validateDate(input);
  45.     } catch (const std::invalid_argument& e) {
  46.         std::cerr << "Ошибка: " << e.what() << std::endl;
  47.     }
  48.     return 0;
  49. }
  50. ```
  51.  
  52. ---
  53.  
  54. ### **Задача 2: Проверка корректности email**
  55.  
  56. **Описание:** Напишите функцию, которая проверяет, является ли строка корректным email адресом (должен содержать `@` и точку после `@`). Обработайте некорректный формат.
  57.  
  58. **Решение:**
  59.  
  60. ```cpp
  61. #include <iostream>
  62. #include <string>
  63. #include <stdexcept>
  64.  
  65. void validateEmail(const std::string& email) {
  66.     size_t atPos = email.find('@');
  67.     if (atPos == std::string::npos) {
  68.         throw std::invalid_argument("Email не содержит символ '@'.");
  69.     }
  70.     if (email.find('.', atPos) == std::string::npos) {
  71.         throw std::invalid_argument("Email не содержит доменное имя (точка после '@').");
  72.     }
  73.     std::cout << "Email корректен: " << email << std::endl;
  74. }
  75.  
  76. int main() {
  77.     std::string email;
  78.     std::cout << "Введите email: ";
  79.     std::getline(std::cin, email);
  80.  
  81.     try {
  82.         validateEmail(email);
  83.     } catch (const std::invalid_argument& e) {
  84.         std::cerr << "Ошибка: " << e.what() << std::endl;
  85.     }
  86.     return 0;
  87. }
  88. ```
  89.  
  90. ---
  91.  
  92. ### **Задача 3: Обработка ошибки при чтении числа из строки**
  93.  
  94. **Описание:** Напишите программу, которая читает строку и пытается извлечь из неё **два** числа, разделённых пробелом. Обработайте случаи, когда строка не содержит чисел или содержит лишние символы.
  95.  
  96. **Решение:**
  97.  
  98. ```cpp
  99. #include <iostream>
  100. #include <string>
  101. #include <sstream>
  102. #include <stdexcept>
  103.  
  104. std::pair<int, int> parseTwoNumbers(const std::string& input) {
  105.     std::istringstream iss(input);
  106.     int a, b;
  107.     char extra;
  108.     if (!(iss >> a >> b) || iss >> extra) {
  109.         throw std::invalid_argument("Ожидается два целых числа, разделённых пробелом.");
  110.     }
  111.     return {a, b};
  112. }
  113.  
  114. int main() {
  115.     std::string input;
  116.     std::cout << "Введите два числа через пробел: ";
  117.     std::getline(std::cin, input);
  118.  
  119.     try {
  120.         auto [num1, num2] = parseTwoNumbers(input);
  121.         std::cout << "Числа: " << num1 << ", " << num2 << std::endl;
  122.     } catch (const std::invalid_argument& e) {
  123.         std::cerr << "Ошибка: " << e.what() << std::endl;
  124.     }
  125.     return 0;
  126. }
  127. ```
  128.  
  129. ---
  130.  
  131. ### **Задача 4: Обработка ошибки при создании вектора с отрицательным размером**
  132.  
  133. **Описание:** Напишите функцию, создающую вектор заданного размера. Обработайте попытку создания вектора с отрицательным размером.
  134.  
  135. **Решение:**
  136.  
  137. ```cpp
  138. #include <iostream>
  139. #include <vector>
  140. #include <stdexcept>
  141.  
  142. std::vector<int> createVector(int size) {
  143.     if (size < 0) {
  144.         throw std::domain_error("Размер вектора не может быть отрицательным.");
  145.     }
  146.     return std::vector<int>(size);
  147. }
  148.  
  149. int main() {
  150.     int size;
  151.     std::cout << "Введите размер вектора: ";
  152.     std::cin >> size;
  153.  
  154.     try {
  155.         auto vec = createVector(size);
  156.         std::cout << "Вектор успешно создан размером " << vec.size() << std::endl;
  157.     } catch (const std::domain_error& e) {
  158.         std::cerr << "Ошибка: " << e.what() << std::endl;
  159.     }
  160.     return 0;
  161. }
  162. ```
  163.  
  164. ---
  165.  
  166. ### **Задача 5: Исключение при работе с библиотекой (условно)**
  167.  
  168. **Описание:** Представьте, что вы работаете с условной "библиотекой" для работы с изображениями. Функция `loadImage` может выбросить исключение, если формат не поддерживается. Имитируйте это поведение.
  169.  
  170. **Решение:**
  171.  
  172. ```cpp
  173. #include <iostream>
  174. #include <string>
  175. #include <stdexcept>
  176.  
  177. void loadImage(const std::string& filename) {
  178.     std::string ext = filename.substr(filename.find_last_of(".") + 1);
  179.     if (ext != "jpg" && ext != "png") {
  180.         throw std::runtime_error("Формат изображения не поддерживается: " + ext);
  181.     }
  182.     std::cout << "Изображение '" << filename << "' загружено." << std::endl;
  183. }
  184.  
  185. int main() {
  186.     std::string file;
  187.     std::cout << "Введите имя файла изображения (jpg/png): ";
  188.     std::getline(std::cin, file);
  189.  
  190.     try {
  191.         loadImage(file);
  192.     } catch (const std::runtime_error& e) {
  193.         std::cerr << "Ошибка загрузки: " << e.what() << std::endl;
  194.     }
  195.     return 0;
  196. }
  197. ```
  198.  
  199. ---
  200.  
  201. ### **Задача 6: Исключение при попытке доступа к защищённым данным**
  202.  
  203. **Описание:** Напишите класс `SecureData`, который имеет приватные данные. Доступ к ним возможен только при предоставлении правильного "ключа". Если ключ неверен, выбросьте исключение.
  204.  
  205. **Решение:**
  206.  
  207. ```cpp
  208. #include <iostream>
  209. #include <stdexcept>
  210. #include <string>
  211.  
  212. class SecureData {
  213.     std::string data = "Секретные данные";
  214.     std::string key = "12345";
  215. public:
  216.     std::string getData(const std::string& inputKey) {
  217.         if (inputKey != key) {
  218.             throw std::runtime_error("Неверный ключ доступа.");
  219.         }
  220.         return data;
  221.     }
  222. };
  223.  
  224. int main() {
  225.     SecureData sd;
  226.     std::string input;
  227.     std::cout << "Введите ключ: ";
  228.     std::getline(std::cin, input);
  229.  
  230.     try {
  231.         std::cout << "Данные: " << sd.getData(input) << std::endl;
  232.     } catch (const std::runtime_error& e) {
  233.         std::cerr << "Ошибка: " << e.what() << std::endl;
  234.     }
  235.     return 0;
  236. }
  237. ```
  238.  
  239. ---
  240.  
  241. ### **Задача 7: Обработка ошибки при конвертации валюты**
  242.  
  243. **Описание:** Напишите функцию `convertCurrency`, которая принимает сумму и код валюты. Если код валюты неизвестен, выбросьте исключение.
  244.  
  245. **Решение:**
  246.  
  247. ```cpp
  248. #include <iostream>
  249. #include <stdexcept>
  250. #include <string>
  251.  
  252. double convertCurrency(double amount, const std::string& currency) {
  253.     if (currency == "USD") return amount * 1.0;
  254.     if (currency == "EUR") return amount * 0.85;
  255.     if (currency == "RUB") return amount * 90.0;
  256.     throw std::invalid_argument("Неизвестный код валюты: " + currency);
  257. }
  258.  
  259. int main() {
  260.     double amount;
  261.     std::string currency;
  262.     std::cout << "Введите сумму: ";
  263.     std::cin >> amount;
  264.     std::cout << "Введите код валюты (USD, EUR, RUB): ";
  265.     std::cin >> currency;
  266.  
  267.     try {
  268.         double result = convertCurrency(amount, currency);
  269.         std::cout << "Результат: " << result << " USD" << std::endl;
  270.     } catch (const std::invalid_argument& e) {
  271.         std::cerr << "Ошибка: " << e.what() << std::endl;
  272.     }
  273.     return 0;
  274. }
  275. ```
  276.  
  277. ---
  278.  
  279. ### **Задача 8: Исключение при работе с базой данных (условно)**
  280.  
  281. **Описание:** Имитируйте подключение к базе данных. Если строка подключения некорректна (например, отсутствует хост), выбросьте исключение.
  282.  
  283. **Решение:**
  284.  
  285. ```cpp
  286. #include <iostream>
  287. #include <string>
  288. #include <stdexcept>
  289.  
  290. void connectToDatabase(const std::string& connStr) {
  291.     if (connStr.find("host=") == std::string::npos) {
  292.         throw std::runtime_error("Строка подключения не содержит 'host'.");
  293.     }
  294.     std::cout << "Подключение к базе данных установлено." << std::endl;
  295. }
  296.  
  297. int main() {
  298.     std::string conn;
  299.     std::cout << "Введите строку подключения (например, host=localhost): ";
  300.     std::getline(std::cin, conn);
  301.  
  302.     try {
  303.         connectToDatabase(conn);
  304.     } catch (const std::runtime_error& e) {
  305.         std::cerr << "Ошибка подключения: " << e.what() << std::endl;
  306.     }
  307.     return 0;
  308. }
  309. ```
  310.  
  311. ---
  312.  
  313. ### **Задача 9: Обработка ошибки при вычислении факториала**
  314.  
  315. **Описание:** Напишите функцию `factorial`, которая вычисляет факториал числа. Обработайте отрицательные числа и числа, превышающие разумный предел (например, 20).
  316.  
  317. **Решение:**
  318.  
  319. ```cpp
  320. #include <iostream>
  321. #include <stdexcept>
  322.  
  323. long long factorial(int n) {
  324.     if (n < 0) {
  325.         throw std::domain_error("Факториал отрицательного числа не определён.");
  326.     }
  327.     if (n > 20) {
  328.         throw std::overflow_error("Факториал числа слишком велик для вычисления.");
  329.     }
  330.     long long result = 1;
  331.     for (int i = 2; i <= n; ++i) {
  332.         result *= i;
  333.     }
  334.     return result;
  335. }
  336.  
  337. int main() {
  338.     int num;
  339.     std::cout << "Введите число для вычисления факториала: ";
  340.     std::cin >> num;
  341.  
  342.     try {
  343.         long long result = factorial(num);
  344.         std::cout << "Факториал " << num << " = " << result << std::endl;
  345.     } catch (const std::domain_error& e) {
  346.         std::cerr << "Ошибка: " << e.what() << std::endl;
  347.     } catch (const std::overflow_error& e) {
  348.         std::cerr << "Ошибка: " << e.what() << std::endl;
  349.     }
  350.     return 0;
  351. }
  352. ```
  353.  
  354. ---
  355.  
  356. ### **Задача 10: Обработка исключения при логировании**
  357.  
  358. **Описание:** Напишите простую функцию логирования в файл. Если файл не удаётся открыть, выбросьте исключение.
  359.  
  360. **Решение:**
  361.  
  362. ```cpp
  363. #include <iostream>
  364. #include <fstream>
  365. #include <stdexcept>
  366. #include <string>
  367.  
  368. void logToFile(const std::string& message, const std::string& filename) {
  369.     std::ofstream file(filename, std::ios::app);
  370.     if (!file.is_open()) {
  371.         throw std::runtime_error("Не удалось открыть файл для логирования: " + filename);
  372.     }
  373.     file << message << std::endl;
  374.     file.close();
  375.     std::cout << "Сообщение записано в лог." << std::endl;
  376. }
  377.  
  378. int main() {
  379.     std::string msg, file;
  380.     std::cout << "Введите сообщение для лога: ";
  381.     std::getline(std::cin, msg);
  382.     std::cout << "Введите имя файла лога: ";
  383.     std::getline(std::cin, file);
  384.  
  385.     try {
  386.         logToFile(msg, file);
  387.     } catch (const std::runtime_error& e) {
  388.         std::cerr << "Ошибка логирования: " << e.what() << std::endl;
  389.     }
  390.     return 0;
  391. }
  392. ```
  393.  
  394. ---
  395.  
  396. ## **Часть 2: Пространство имён**
  397.  
  398. ---
  399.  
  400. ### **Задача 1: Организация функций ввода-вывода**
  401.  
  402. **Описание:** Создайте пространство имён `IO` с функциями `readInt()` и `writeInt()`, которые обертывают `std::cin` и `std::cout`.
  403.  
  404. **Решение:**
  405.  
  406. ```cpp
  407. #include <iostream>
  408.  
  409. namespace IO {
  410.     int readInt() {
  411.         int val;
  412.         std::cin >> val;
  413.         return val;
  414.     }
  415.  
  416.     void writeInt(int val) {
  417.         std::cout << val << std::endl;
  418.     }
  419. }
  420.  
  421. int main() {
  422.     std::cout << "Введите число: ";
  423.     int num = IO::readInt();
  424.     std::cout << "Вы ввели: ";
  425.     IO::writeInt(num);
  426.     return 0;
  427. }
  428. ```
  429.  
  430. ---
  431.  
  432. ### **Задача 2: Пространство имён для констант физических величин**
  433.  
  434. **Описание:** Создайте пространство имён `Physics` с константами, такими как `SPEED_OF_LIGHT`, `GRAVITY`.
  435.  
  436. **Решение:**
  437.  
  438. ```cpp
  439. #include <iostream>
  440.  
  441. namespace Physics {
  442.     const double SPEED_OF_LIGHT = 299792458.0; // м/с
  443.     const double GRAVITY = 9.81; // м/с^2
  444. }
  445.  
  446. int main() {
  447.     std::cout << "Скорость света: " << Physics::SPEED_OF_LIGHT << " м/с" << std::endl;
  448.     std::cout << "Ускорение свободного падения: " << Physics::GRAVITY << " м/с^2" << std::endl;
  449.     return 0;
  450. }
  451. ```
  452.  
  453. ---
  454.  
  455. ### **Задача 3: Пространство имён для математических функций**
  456.  
  457. **Описание:** Создайте пространство имён `MathUtils` с функцией `power`, которая возводит число в степень.
  458.  
  459. **Решение:**
  460.  
  461. ```cpp
  462. #include <iostream>
  463.  
  464. namespace MathUtils {
  465.     double power(double base, int exp) {
  466.         double result = 1.0;
  467.         for (int i = 0; i < exp; ++i) {
  468.             result *= base;
  469.         }
  470.         return result;
  471.     }
  472. }
  473.  
  474. int main() {
  475.     double base = 2.0;
  476.     int exp = 3;
  477.     std::cout << base << "^" << exp << " = " << MathUtils::power(base, exp) << std::endl;
  478.     return 0;
  479. }
  480. ```
  481.  
  482. ---
  483.  
  484. ### **Задача 4: Использование `using` для сокращения кода**
  485.  
  486. **Описание:** В `main` используйте `using` для импорта конкретной функции из пространства `MathUtils` и вызовите её.
  487.  
  488. **Решение:**
  489.  
  490. ```cpp
  491. #include <iostream>
  492.  
  493. namespace MathUtils {
  494.     double power(double base, int exp) {
  495.         double result = 1.0;
  496.         for (int i = 0; i < exp; ++i) {
  497.             result *= base;
  498.         }
  499.         return result;
  500.     }
  501. }
  502.  
  503. int main() {
  504.     using MathUtils::power;
  505.     std::cout << "2^4 = " << power(2, 4) << std::endl;
  506.     return 0;
  507. }
  508. ```
  509.  
  510. ---
  511.  
  512. ### **Задача 5: Пространство имён для работы с геометрией**
  513.  
  514. **Описание:** Создайте пространство имён `Shapes` с классом `Rectangle`, который имеет метод `area`.
  515.  
  516. **Решение:**
  517.  
  518. ```cpp
  519. #include <iostream>
  520.  
  521. namespace Shapes {
  522.     class Rectangle {
  523.         double width, height;
  524.     public:
  525.         Rectangle(double w, double h) : width(w), height(h) {}
  526.         double area() const {
  527.             return width * height;
  528.         }
  529.     };
  530. }
  531.  
  532. int main() {
  533.     Shapes::Rectangle rect(5.0, 3.0);
  534.     std::cout << "Площадь прямоугольника: " << rect.area() << std::endl;
  535.     return 0;
  536. }
  537. ```
  538.  
  539. ---
  540.  
  541. ### **Задача 6: Вложенные пространства имён для библиотеки**
  542.  
  543. **Описание:** Создайте вложенное пространство имён `Graphics::2D` с функцией `drawLine`.
  544.  
  545. **Решение:**
  546.  
  547. ```cpp
  548. #include <iostream>
  549.  
  550. namespace Graphics {
  551.     namespace _2D {
  552.         void drawLine(int x1, int y1, int x2, int y2) {
  553.             std::cout << "Рисуем линию от (" << x1 << "," << y1 << ") до (" << x2 << "," << y2 << ")" << std::endl;
  554.         }
  555.     }
  556. }
  557.  
  558. int main() {
  559.     Graphics::_2D::drawLine(0, 0, 10, 10);
  560.     return 0;
  561. }
  562. ```
  563.  
  564. ---
  565.  
  566. ### **Задача 7: Повторное объявление пространства имён с классом и функцией**
  567.  
  568. **Описание:** Объявите пространство `Game` дважды: в первом — класс `Player`, во втором — функцию `resetGame`.
  569.  
  570. **Решение:**
  571.  
  572. ```cpp
  573. #include <iostream>
  574.  
  575. namespace Game {
  576.     class Player {
  577.     public:
  578.         std::string name;
  579.         Player(const std::string& n) : name(n) {}
  580.     };
  581. }
  582.  
  583. namespace Game {
  584.     void resetGame() {
  585.         std::cout << "Игра сброшена." << std::endl;
  586.     }
  587. }
  588.  
  589. int main() {
  590.     Game::Player p("Alice");
  591.     std::cout << "Игрок: " << p.name << std::endl;
  592.     Game::resetGame();
  593.     return 0;
  594. }
  595. ```
  596.  
  597. ---
  598.  
  599. ### **Задача 8: Пространство имён для настроек приложения**
  600.  
  601. **Описание:** Создайте пространство имён `AppConfig` с переменными `windowWidth`, `windowHeight`.
  602.  
  603. **Решение:**
  604.  
  605. ```cpp
  606. #include <iostream>
  607.  
  608. namespace AppConfig {
  609.     int windowWidth = 800;
  610.     int windowHeight = 600;
  611. }
  612.  
  613. int main() {
  614.     std::cout << "Размер окна: " << AppConfig::windowWidth << "x" << AppConfig::windowHeight << std::endl;
  615.     return 0;
  616. }
  617. ```
  618.  
  619. ---
  620.  
  621. ### **Задача 9: Пространство имён для вспомогательных утилит**
  622.  
  623. **Описание:** Создайте пространство `Utils` с функцией `trim`, которая удаляет пробелы в начале и в конце строки.
  624.  
  625. **Решение:**
  626.  
  627. ```cpp
  628. #include <iostream>
  629. #include <string>
  630.  
  631. namespace Utils {
  632.     std::string trim(const std::string& str) {
  633.         size_t start = str.find_first_not_of(" \t\n\r");
  634.         if (start == std::string::npos) return "";
  635.         size_t end = str.find_last_not_of(" \t\n\r");
  636.         return str.substr(start, end - start + 1);
  637.     }
  638. }
  639.  
  640. int main() {
  641.     std::string input = "  hello world  ";
  642.     std::cout << "До: [" << input << "]" << std::endl;
  643.     std::cout << "После: [" << Utils::trim(input) << "]" << std::endl;
  644.     return 0;
  645. }
  646. ```
  647.  
  648. ---
  649.  
  650. ### **Задача 10: Анонимное пространство имён для локальной утилиты**
  651.  
  652. **Описание:** Создайте анонимное пространство имён с функцией `isEven`, которая используется только внутри текущего файла.
  653.  
  654. **Решение:**
  655.  
  656. ```cpp
  657. #include <iostream>
  658.  
  659. namespace {
  660.     bool isEven(int n) {
  661.         return n % 2 == 0;
  662.     }
  663. }
  664.  
  665. int main() {
  666.     int num = 42;
  667.     if (isEven(num)) {
  668.         std::cout << num << " - чётное." << std::endl;
  669.     } else {
  670.         std::cout << num << " - нечётное." << std::endl;
  671.     }
  672.     return 0;
  673. }
  674. ```
  675.  
  676. ---
  677.  
  678. Эти задачи показывают, как исключения и пространства имён применяются на практике для повышения надёжности, читаемости и структурированности кода.
Advertisement
Add Comment
Please, Sign In to add comment