Загрузка данных


#include <iostream>
#include <fstream>
#include <string>
#include <limits>
#include <algorithm>

using namespace std;


int readInt(const string& prompt);


class Classroom {
private:
    string building;   // корпус
    int    roomNumber; // аудитория
    int    capacity;   // мест

public:
    Classroom()
        : building(""), roomNumber(0), capacity(0) {
    }

    Classroom(const string& b, int rn, int cap)
        : building(b), roomNumber(rn), capacity(cap) {
    }

    Classroom(const Classroom& other)
        : building(other.building),
        roomNumber(other.roomNumber),
        capacity(other.capacity) {
    }

    ~Classroom() {}

    string getBuilding()    const { return building; }
    int    getRoomNumber()  const { return roomNumber; }
    int    getCapacity()    const { return capacity; }

    void setBuilding(const string& b) { building = b; }
    void setRoomNumber(int rn) { roomNumber = rn; }
    void setCapacity(int cap) { capacity = cap; }

    void input() {
        cout << "  Корпус: ";
        getline(cin, building);
        roomNumber = readInt("  Номер аудитории: ");
        capacity = readInt("  Количество мест: ");
    }

    void print(int idx) const {
        cout << idx << ". "
            << "[" << building << "] "
            << "ауд. " << roomNumber
            << ", мест: " << capacity
            << "\n";
    }
};


struct Node {
    Classroom data;
    Node* prev;
    Node* next;

    Node(const Classroom& c)
        : data(c), prev(nullptr), next(nullptr) {
    }
};


//  двусвязный список
class DoublyLinkedList {
private:
    Node* head;
    Node* tail;
    int   size;

public:
    DoublyLinkedList() : head(nullptr), tail(nullptr), size(0) {}

    ~DoublyLinkedList() { clear(); }

    // добавить элемент в конец
    void pushBack(const Classroom& c) {
        Node* newNode = new Node(c);
        if (!tail) {
            head = tail = newNode;
        }
        else {
            newNode->prev = tail;
            tail->next = newNode;
            tail = newNode;
        }
        ++size;
    }

    // удалить элемент по индексу
    bool removeAt(int idx) {
        Node* cur = getNodeAt(idx);
        if (!cur) return false;

        if (cur->prev) cur->prev->next = cur->next;
        else           head = cur->next;

        if (cur->next) cur->next->prev = cur->prev;
        else           tail = cur->prev;

        delete cur;
        --size;
        return true;
    }

    // получить указатель на узел по индексу 
    Node* getNodeAt(int idx) const {
        if (idx < 1 || idx > size) return nullptr;
        Node* cur = head;
        for (int i = 1; i < idx; ++i) cur = cur->next;
        return cur;
    }

    int  getSize() const { return size; }
    bool isEmpty() const { return size == 0; }
    Node* getHead() const { return head; }

    // очистить список
    void clear() {
        Node* cur = head;
        while (cur) {
            Node* next = cur->next;
            delete cur;
            cur = next;
        }
        head = tail = nullptr;
        size = 0;
    }

    // вывод списка 
    void print() const {
        if (isEmpty()) {
            cout << "  Список пуст.\n";
            return;
        }
        cout << "\n  --- Список аудиторий ---\n";
        Node* cur = head;
        int idx = 1;
        while (cur) {
            cur->data.print(idx);
            cur = cur->next;
            ++idx;
        }
    }

    // запись в файл
    void saveToFile(const string& filename) const {
        ofstream f(filename);
        if (!f) { cout << "  Ошибка открытия файла!\n"; return; }
        Node* cur = head;
        while (cur) {
            f << cur->data.getBuilding() << "\n"
                << cur->data.getRoomNumber() << "\n"
                << cur->data.getCapacity() << "\n";
            cur = cur->next;
        }
        cout << "  Данные сохранены в файл \"" << filename << "\".\n";
    }

    // чтение из файла
    void loadFromFile(const string& filename) {
        ifstream f(filename);
        if (!f) { cout << "  Файл \"" << filename << "\" не найден!\n"; return; }
        clear();
        string building;
        int roomNumber, capacity;
        while (getline(f, building)) {
            if (!(f >> roomNumber)) break;
            if (!(f >> capacity))  break;
            f.ignore();
            pushBack(Classroom(building, roomNumber, capacity));
        }
        cout << "  Загружено " << size << " записей из \"" << filename << "\".\n";
    }


    void sortBy(int field, bool asc) {
        if (size < 2) return;
        bool swapped;
        do {
            swapped = false;
            Node* cur = head;
            while (cur && cur->next) {
                bool doSwap = false;
                if (field == 0) {
                    int cmp = cur->data.getBuilding().compare(cur->next->data.getBuilding());
                    doSwap = asc ? (cmp > 0) : (cmp < 0);
                }
                else if (field == 1) {
                    int a = cur->data.getRoomNumber();
                    int b = cur->next->data.getRoomNumber();
                    doSwap = asc ? (a > b) : (a < b);
                }
                else {
                    int a = cur->data.getCapacity();
                    int b = cur->next->data.getCapacity();
                    doSwap = asc ? (a > b) : (a < b);
                }
                if (doSwap) {
                    Classroom tmp = cur->data;
                    cur->data = cur->next->data;
                    cur->next->data = tmp;
                    swapped = true;
                }
                cur = cur->next;
            }
        } while (swapped);
    }
};


void clearInput() {
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}


int readInt(const string& prompt) {
    while (true) {
        cout << prompt;

        string buf;
        char ch;


        while ((ch = getchar()) != '\n' && ch != EOF) {
            buf += ch;
        }

        if (buf.empty()) {
            cout << "  Ошибка: введите число, не пустую строку.\n";
            continue;
        }

        bool valid = true;
        for (int i = 0; i < (int)buf.size(); ++i) {

            if (i == 0 && buf[i] == '-') {
                if (buf.size() == 1) { valid = false; break; }
                continue;
            }
            if (!isdigit((unsigned char)buf[i])) {
                valid = false;
                break;
            }
        }

        if (!valid) {
            cout << "  Ошибка: допустимы только цифры\n";
            continue;
        }

        try {
            int val = stoi(buf);
            return val;
        }
        catch (...) {
            cout << "  Ошибка: число слишком большое.\n";
        }
    }
}

//  Меню
void menuAdd(DoublyLinkedList& list) {
    cout << "\n  === Добавление аудитории ===\n";
    Classroom c;
    c.input();
    list.pushBack(c);
    cout << "  Запись добавлена.\n";
}

void menuDelete(DoublyLinkedList& list) {
    if (list.isEmpty()) { cout << "  Список пуст.\n"; return; }
    list.print();
    int idx = readInt("\n  Номер записи для удаления: ");
    if (list.removeAt(idx))
        cout << "  Запись удалена.\n";
    else
        cout << "  Неверный номер записи.\n";
}

void menuEdit(DoublyLinkedList& list) {
    if (list.isEmpty()) { cout << "  Список пуст.\n"; return; }
    list.print();
    int idx = readInt("\n  Номер записи для редактирования: ");
    Node* node = list.getNodeAt(idx);
    if (!node) { cout << "  Неверный номер записи.\n"; return; }

    cout << "\n  Что изменить?\n"
        << "  1. Корпус\n"
        << "  2. Номер аудитории\n"
        << "  3. Количество мест\n"
        << "  4. Все поля\n";
    int choice = readInt("  Выбор: ");

    if (choice == 1 || choice == 4) {
        cout << "  Новый корпус: ";
        string b; getline(cin, b);
        node->data.setBuilding(b);
    }
    if (choice == 2 || choice == 4) {
        int rn = readInt("  Новый номер аудитории: ");
        node->data.setRoomNumber(rn);
    }
    if (choice == 3 || choice == 4) {
        int cap = readInt("  Новое количество мест: ");
        node->data.setCapacity(cap);
    }
    cout << "  Запись обновлена.\n";
}

void menuPrint(DoublyLinkedList& list) {
    if (list.isEmpty()) { cout << "  Список пуст.\n"; return; }

    cout << "\n  === Вывод списка ===\n"
        << "  Сортировка по:\n"
        << "  1. Корпус\n"
        << "  2. Номер аудитории\n"
        << "  3. Количество мест\n"
        << "  4. Без сортировки\n";
    int field = readInt("  Выбор поля: ");

    if (field >= 1 && field <= 3) {
        cout << "  Порядок:\n"
            << "  1. По возрастанию\n"
            << "  2. По убыванию\n";
        int order = readInt("  Выбор: ");
        bool asc = (order != 2);
        list.sortBy(field - 1, asc);
    }

    list.print();
}

void menuSave(DoublyLinkedList& list) {
    cout << "  Имя файла: ";
    string filename; getline(cin, filename);
    list.saveToFile(filename);
}

void menuLoad(DoublyLinkedList& list) {
    cout << "  Имя файла: ";
    string filename; getline(cin, filename);
    list.loadFromFile(filename);
}









int main() {

    setlocale(LC_ALL, "RU");

    DoublyLinkedList list;


    cout << "\n|-------------------------------------|\n"
        << "|            Учёт аудиторий           |\n"
        << "|-------------------------------------|\n";


    int choice = 0;
    do {
        cout << "\n  ========================\n"
            << "  1. Добавить аудиторию\n"
            << "  2. Удалить аудиторию\n"
            << "  3. Редактировать аудиторию\n"
            << "  4. Вывести список (с сортировкой)\n"
            << "  5. Сохранить в файл\n"
            << "  6. Загрузить из файла\n"
            << "  0. Выход\n";
        choice = readInt("  Выбор: ");

        switch (choice) {
        case 1: menuAdd(list);    break;
        case 2: menuDelete(list); break;
        case 3: menuEdit(list);   break;
        case 4: menuPrint(list);  break;
        case 5: menuSave(list);   break;
        case 6: menuLoad(list);   break;
        case 0: break;
        default: cout << "\n  Неизвестный пункт меню.\n";
        }
    } while (choice != 0);

    return 0;
}