Хорошо! Ниже представлены 10 задач с решениями на тему **"Исключения"** и 10 задач с решениями на тему **"Пространство имён"**, каждая из которых иллюстрирует практическое применение этих концепций в C++.

---

## **Часть 1: Исключения**

---

### **Задача 1: Обработка неправильного формата даты**

**Описание:** Напишите программу, которая принимает строку в формате "DD/MM/YYYY" и проверяет, является ли она корректной датой (например, 30/02/2023 — некорректно). Если формат неверен или дата невозможна, выбросите исключение.

**Решение:**

```cpp
#include <iostream>
#include <string>
#include <stdexcept>
#include <sstream>

void validateDate(const std::string& dateStr) {
    if (dateStr.size() != 10 || dateStr[2] != '/' || dateStr[5] != '/') {
        throw std::invalid_argument("Неверный формат даты. Используйте DD/MM/YYYY.");
    }

    int day, month, year;
    char sep1, sep2;
    std::istringstream iss(dateStr);
    iss >> day >> sep1 >> month >> sep2 >> year;

    if (iss.fail() || day < 1 || day > 31 || month < 1 || month > 12) {
        throw std::invalid_argument("Некорректные значения дня или месяца.");
    }

    // Простая проверка: февраль не может иметь 30 дней
    if (month == 2 && day > 29) {
        throw std::invalid_argument("Февраль не может иметь более 29 дней.");
    }
    std::cout << "Дата корректна: " << dateStr << std::endl;
}

int main() {
    std::string input;
    std::cout << "Введите дату в формате DD/MM/YYYY: ";
    std::getline(std::cin, input);

    try {
        validateDate(input);
    } catch (const std::invalid_argument& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 2: Проверка корректности email**

**Описание:** Напишите функцию, которая проверяет, является ли строка корректным email адресом (должен содержать `@` и точку после `@`). Обработайте некорректный формат.

**Решение:**

```cpp
#include <iostream>
#include <string>
#include <stdexcept>

void validateEmail(const std::string& email) {
    size_t atPos = email.find('@');
    if (atPos == std::string::npos) {
        throw std::invalid_argument("Email не содержит символ '@'.");
    }
    if (email.find('.', atPos) == std::string::npos) {
        throw std::invalid_argument("Email не содержит доменное имя (точка после '@').");
    }
    std::cout << "Email корректен: " << email << std::endl;
}

int main() {
    std::string email;
    std::cout << "Введите email: ";
    std::getline(std::cin, email);

    try {
        validateEmail(email);
    } catch (const std::invalid_argument& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 3: Обработка ошибки при чтении числа из строки**

**Описание:** Напишите программу, которая читает строку и пытается извлечь из неё **два** числа, разделённых пробелом. Обработайте случаи, когда строка не содержит чисел или содержит лишние символы.

**Решение:**

```cpp
#include <iostream>
#include <string>
#include <sstream>
#include <stdexcept>

std::pair<int, int> parseTwoNumbers(const std::string& input) {
    std::istringstream iss(input);
    int a, b;
    char extra;
    if (!(iss >> a >> b) || iss >> extra) {
        throw std::invalid_argument("Ожидается два целых числа, разделённых пробелом.");
    }
    return {a, b};
}

int main() {
    std::string input;
    std::cout << "Введите два числа через пробел: ";
    std::getline(std::cin, input);

    try {
        auto [num1, num2] = parseTwoNumbers(input);
        std::cout << "Числа: " << num1 << ", " << num2 << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 4: Обработка ошибки при создании вектора с отрицательным размером**

**Описание:** Напишите функцию, создающую вектор заданного размера. Обработайте попытку создания вектора с отрицательным размером.

**Решение:**

```cpp
#include <iostream>
#include <vector>
#include <stdexcept>

std::vector<int> createVector(int size) {
    if (size < 0) {
        throw std::domain_error("Размер вектора не может быть отрицательным.");
    }
    return std::vector<int>(size);
}

int main() {
    int size;
    std::cout << "Введите размер вектора: ";
    std::cin >> size;

    try {
        auto vec = createVector(size);
        std::cout << "Вектор успешно создан размером " << vec.size() << std::endl;
    } catch (const std::domain_error& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 5: Исключение при работе с библиотекой (условно)**

**Описание:** Представьте, что вы работаете с условной "библиотекой" для работы с изображениями. Функция `loadImage` может выбросить исключение, если формат не поддерживается. Имитируйте это поведение.

**Решение:**

```cpp
#include <iostream>
#include <string>
#include <stdexcept>

void loadImage(const std::string& filename) {
    std::string ext = filename.substr(filename.find_last_of(".") + 1);
    if (ext != "jpg" && ext != "png") {
        throw std::runtime_error("Формат изображения не поддерживается: " + ext);
    }
    std::cout << "Изображение '" << filename << "' загружено." << std::endl;
}

int main() {
    std::string file;
    std::cout << "Введите имя файла изображения (jpg/png): ";
    std::getline(std::cin, file);

    try {
        loadImage(file);
    } catch (const std::runtime_error& e) {
        std::cerr << "Ошибка загрузки: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 6: Исключение при попытке доступа к защищённым данным**

**Описание:** Напишите класс `SecureData`, который имеет приватные данные. Доступ к ним возможен только при предоставлении правильного "ключа". Если ключ неверен, выбросьте исключение.

**Решение:**

```cpp
#include <iostream>
#include <stdexcept>
#include <string>

class SecureData {
    std::string data = "Секретные данные";
    std::string key = "12345";
public:
    std::string getData(const std::string& inputKey) {
        if (inputKey != key) {
            throw std::runtime_error("Неверный ключ доступа.");
        }
        return data;
    }
};

int main() {
    SecureData sd;
    std::string input;
    std::cout << "Введите ключ: ";
    std::getline(std::cin, input);

    try {
        std::cout << "Данные: " << sd.getData(input) << std::endl;
    } catch (const std::runtime_error& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 7: Обработка ошибки при конвертации валюты**

**Описание:** Напишите функцию `convertCurrency`, которая принимает сумму и код валюты. Если код валюты неизвестен, выбросьте исключение.

**Решение:**

```cpp
#include <iostream>
#include <stdexcept>
#include <string>

double convertCurrency(double amount, const std::string& currency) {
    if (currency == "USD") return amount * 1.0;
    if (currency == "EUR") return amount * 0.85;
    if (currency == "RUB") return amount * 90.0;
    throw std::invalid_argument("Неизвестный код валюты: " + currency);
}

int main() {
    double amount;
    std::string currency;
    std::cout << "Введите сумму: ";
    std::cin >> amount;
    std::cout << "Введите код валюты (USD, EUR, RUB): ";
    std::cin >> currency;

    try {
        double result = convertCurrency(amount, currency);
        std::cout << "Результат: " << result << " USD" << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 8: Исключение при работе с базой данных (условно)**

**Описание:** Имитируйте подключение к базе данных. Если строка подключения некорректна (например, отсутствует хост), выбросьте исключение.

**Решение:**

```cpp
#include <iostream>
#include <string>
#include <stdexcept>

void connectToDatabase(const std::string& connStr) {
    if (connStr.find("host=") == std::string::npos) {
        throw std::runtime_error("Строка подключения не содержит 'host'.");
    }
    std::cout << "Подключение к базе данных установлено." << std::endl;
}

int main() {
    std::string conn;
    std::cout << "Введите строку подключения (например, host=localhost): ";
    std::getline(std::cin, conn);

    try {
        connectToDatabase(conn);
    } catch (const std::runtime_error& e) {
        std::cerr << "Ошибка подключения: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 9: Обработка ошибки при вычислении факториала**

**Описание:** Напишите функцию `factorial`, которая вычисляет факториал числа. Обработайте отрицательные числа и числа, превышающие разумный предел (например, 20).

**Решение:**

```cpp
#include <iostream>
#include <stdexcept>

long long factorial(int n) {
    if (n < 0) {
        throw std::domain_error("Факториал отрицательного числа не определён.");
    }
    if (n > 20) {
        throw std::overflow_error("Факториал числа слишком велик для вычисления.");
    }
    long long result = 1;
    for (int i = 2; i <= n; ++i) {
        result *= i;
    }
    return result;
}

int main() {
    int num;
    std::cout << "Введите число для вычисления факториала: ";
    std::cin >> num;

    try {
        long long result = factorial(num);
        std::cout << "Факториал " << num << " = " << result << std::endl;
    } catch (const std::domain_error& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    } catch (const std::overflow_error& e) {
        std::cerr << "Ошибка: " << e.what() << std::endl;
    }
    return 0;
}
```

---

### **Задача 10: Обработка исключения при логировании**

**Описание:** Напишите простую функцию логирования в файл. Если файл не удаётся открыть, выбросьте исключение.

**Решение:**

```cpp
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>

void logToFile(const std::string& message, const std::string& filename) {
    std::ofstream file(filename, std::ios::app);
    if (!file.is_open()) {
        throw std::runtime_error("Не удалось открыть файл для логирования: " + filename);
    }
    file << message << std::endl;
    file.close();
    std::cout << "Сообщение записано в лог." << std::endl;
}

int main() {
    std::string msg, file;
    std::cout << "Введите сообщение для лога: ";
    std::getline(std::cin, msg);
    std::cout << "Введите имя файла лога: ";
    std::getline(std::cin, file);

    try {
        logToFile(msg, file);
    } catch (const std::runtime_error& e) {
        std::cerr << "Ошибка логирования: " << e.what() << std::endl;
    }
    return 0;
}
```

---

## **Часть 2: Пространство имён**

---

### **Задача 1: Организация функций ввода-вывода**

**Описание:** Создайте пространство имён `IO` с функциями `readInt()` и `writeInt()`, которые обертывают `std::cin` и `std::cout`.

**Решение:**

```cpp
#include <iostream>

namespace IO {
    int readInt() {
        int val;
        std::cin >> val;
        return val;
    }

    void writeInt(int val) {
        std::cout << val << std::endl;
    }
}

int main() {
    std::cout << "Введите число: ";
    int num = IO::readInt();
    std::cout << "Вы ввели: ";
    IO::writeInt(num);
    return 0;
}
```

---

### **Задача 2: Пространство имён для констант физических величин**

**Описание:** Создайте пространство имён `Physics` с константами, такими как `SPEED_OF_LIGHT`, `GRAVITY`.

**Решение:**

```cpp
#include <iostream>

namespace Physics {
    const double SPEED_OF_LIGHT = 299792458.0; // м/с
    const double GRAVITY = 9.81; // м/с^2
}

int main() {
    std::cout << "Скорость света: " << Physics::SPEED_OF_LIGHT << " м/с" << std::endl;
    std::cout << "Ускорение свободного падения: " << Physics::GRAVITY << " м/с^2" << std::endl;
    return 0;
}
```

---

### **Задача 3: Пространство имён для математических функций**

**Описание:** Создайте пространство имён `MathUtils` с функцией `power`, которая возводит число в степень.

**Решение:**

```cpp
#include <iostream>

namespace MathUtils {
    double power(double base, int exp) {
        double result = 1.0;
        for (int i = 0; i < exp; ++i) {
            result *= base;
        }
        return result;
    }
}

int main() {
    double base = 2.0;
    int exp = 3;
    std::cout << base << "^" << exp << " = " << MathUtils::power(base, exp) << std::endl;
    return 0;
}
```

---

### **Задача 4: Использование `using` для сокращения кода**

**Описание:** В `main` используйте `using` для импорта конкретной функции из пространства `MathUtils` и вызовите её.

**Решение:**

```cpp
#include <iostream>

namespace MathUtils {
    double power(double base, int exp) {
        double result = 1.0;
        for (int i = 0; i < exp; ++i) {
            result *= base;
        }
        return result;
    }
}

int main() {
    using MathUtils::power;
    std::cout << "2^4 = " << power(2, 4) << std::endl;
    return 0;
}
```

---

### **Задача 5: Пространство имён для работы с геометрией**

**Описание:** Создайте пространство имён `Shapes` с классом `Rectangle`, который имеет метод `area`.

**Решение:**

```cpp
#include <iostream>

namespace Shapes {
    class Rectangle {
        double width, height;
    public:
        Rectangle(double w, double h) : width(w), height(h) {}
        double area() const {
            return width * height;
        }
    };
}

int main() {
    Shapes::Rectangle rect(5.0, 3.0);
    std::cout << "Площадь прямоугольника: " << rect.area() << std::endl;
    return 0;
}
```

---

### **Задача 6: Вложенные пространства имён для библиотеки**

**Описание:** Создайте вложенное пространство имён `Graphics::2D` с функцией `drawLine`.

**Решение:**

```cpp
#include <iostream>

namespace Graphics {
    namespace _2D {
        void drawLine(int x1, int y1, int x2, int y2) {
            std::cout << "Рисуем линию от (" << x1 << "," << y1 << ") до (" << x2 << "," << y2 << ")" << std::endl;
        }
    }
}

int main() {
    Graphics::_2D::drawLine(0, 0, 10, 10);
    return 0;
}
```

---

### **Задача 7: Повторное объявление пространства имён с классом и функцией**

**Описание:** Объявите пространство `Game` дважды: в первом — класс `Player`, во втором — функцию `resetGame`.

**Решение:**

```cpp
#include <iostream>

namespace Game {
    class Player {
    public:
        std::string name;
        Player(const std::string& n) : name(n) {}
    };
}

namespace Game {
    void resetGame() {
        std::cout << "Игра сброшена." << std::endl;
    }
}

int main() {
    Game::Player p("Alice");
    std::cout << "Игрок: " << p.name << std::endl;
    Game::resetGame();
    return 0;
}
```

---

### **Задача 8: Пространство имён для настроек приложения**

**Описание:** Создайте пространство имён `AppConfig` с переменными `windowWidth`, `windowHeight`.

**Решение:**

```cpp
#include <iostream>

namespace AppConfig {
    int windowWidth = 800;
    int windowHeight = 600;
}

int main() {
    std::cout << "Размер окна: " << AppConfig::windowWidth << "x" << AppConfig::windowHeight << std::endl;
    return 0;
}
```

---

### **Задача 9: Пространство имён для вспомогательных утилит**

**Описание:** Создайте пространство `Utils` с функцией `trim`, которая удаляет пробелы в начале и в конце строки.

**Решение:**

```cpp
#include <iostream>
#include <string>

namespace Utils {
    std::string trim(const std::string& str) {
        size_t start = str.find_first_not_of(" \t\n\r");
        if (start == std::string::npos) return "";
        size_t end = str.find_last_not_of(" \t\n\r");
        return str.substr(start, end - start + 1);
    }
}

int main() {
    std::string input = "  hello world  ";
    std::cout << "До: [" << input << "]" << std::endl;
    std::cout << "После: [" << Utils::trim(input) << "]" << std::endl;
    return 0;
}
```

---

### **Задача 10: Анонимное пространство имён для локальной утилиты**

**Описание:** Создайте анонимное пространство имён с функцией `isEven`, которая используется только внутри текущего файла.

**Решение:**

```cpp
#include <iostream>

namespace {
    bool isEven(int n) {
        return n % 2 == 0;
    }
}

int main() {
    int num = 42;
    if (isEven(num)) {
        std::cout << num << " - чётное." << std::endl;
    } else {
        std::cout << num << " - нечётное." << std::endl;
    }
    return 0;
}
```

---

Эти задачи показывают, как исключения и пространства имён применяются на практике для повышения надёжности, читаемости и структурированности кода.