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


List.h

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;

struct Grade {
    string subject;
    string date;
    int mark;
};

struct Student {
    string number;
    string last_name;
    string birth_day;
    string group;
    vector<Grade> results;
};

struct Node {
    Student item;
    Node* next;
};

class List {
private:
    Node* head;
    int size;
    void clear();
    Node* getNodeByIndex(int index);
public:
    List();
    List(const List& other);
    ~List();
    List& operator=(const List& other);

    void addToStart(const Student& s);
    void addAfterIndex(int index, const Student& s);
    void deleteNFromIndex(int index, int n);

    void loadFromFile(const string& filename);
    void addFromKeyboard();

    List findByBirthDate(const string& birthDate);
    double averageMarkBySubject(const string& studentNumber, const string& subject);

    void saveToFile(const string& filename) const;
    void print() const;
    int getSize() const;

    friend ostream& operator<<(ostream& os, const List& list);
};


------------------------------------------------------------------


List.cpp

#include "List.h"

void List::clear() {
    Node* temp = head;
    while (temp) {
        Node* next = temp->next;
        delete temp;
        temp = next;
    }
    head = nullptr;
    size = 0;
}

Node* List::getNodeByIndex(int index) {
    if (index < 0 || index >= size) return nullptr;
    Node* temp = head;
    for (int i = 0; i < index; i++) temp = temp->next;
    return temp;
}

List::List() : head(nullptr), size(0) {}

List::List(const List& other) : head(nullptr), size(0) {
    Node* temp = other.head;
    while (temp) {
        Node* newNode = new Node{temp->item, nullptr};
        if (!head) head = newNode;
        else {
            Node* t = head;
            while (t->next) t = t->next;
            t->next = newNode;
        }
        size++;
        temp = temp->next;
    }
}

List::~List() {
    clear();
}

List& List::operator=(const List& other) {
    if (this != &other) {
        clear();
        Node* temp = other.head;
        while (temp) {
            Node* newNode = new Node{temp->item, nullptr};
            if (!head) head = newNode;
            else {
                Node* t = head;
                while (t->next) t = t->next;
                t->next = newNode;
            }
            size++;
            temp = temp->next;
        }
    }
    return *this;
}

void List::addToStart(const Student& s) {
    Node* newNode = new Node{s, head};
    head = newNode;
    size++;
}

void List::addAfterIndex(int index, const Student& s) {
    if (index < 0 || index >= size) return;
    Node* current = getNodeByIndex(index);
    if (!current) return;
    Node* newNode = new Node{s, current->next};
    current->next = newNode;
    size++;
}

void List::deleteNFromIndex(int index, int n) {
    if (index < 0 || index >= size || n <= 0) return;
    if (index == 0) {
        for (int i = 0; i < n && head; i++) {
            Node* temp = head;
            head = head->next;
            delete temp;
            size--;
        }
        return;
    }
    Node* prev = getNodeByIndex(index - 1);
    if (!prev) return;
    Node* current = prev->next;
    int deleted = 0;
    while (current && deleted < n) {
        Node* temp = current;
        current = current->next;
        delete temp;
        deleted++;
        size--;
    }
    prev->next = current;
}

void List::loadFromFile(const string& filename) {
    ifstream file(filename);
    if (!file) return;
    int n;
    file >> n;
    for (int i = 0; i < n; i++) {
        Student s;
        int m;
        file >> s.number >> s.last_name >> s.birth_day >> s.group;
        file >> m;
        for (int j = 0; j < m; j++) {
            Grade g;
            file >> g.subject >> g.date >> g.mark;
            s.results.push_back(g);
        }
        addToStart(s);
    }
    file.close();
}

void List::addFromKeyboard() {
    Student s;
    int m;
    cout << "Number: "; cin >> s.number;
    cout << "Last name: "; cin >> s.last_name;
    cout << "Birth day: "; cin >> s.birth_day;
    cout << "Group: "; cin >> s.group;
    cout << "Grades count: "; cin >> m;
    for (int i = 0; i < m; i++) {
        Grade g;
        cout << "Subject: "; cin >> g.subject;
        cout << "Date: "; cin >> g.date;
        cout << "Mark: "; cin >> g.mark;
        s.results.push_back(g);
    }
    addToStart(s);
}

List List::findByBirthDate(const string& birthDate) {
    List result;
    Node* temp = head;
    while (temp) {
        if (temp->item.birth_day == birthDate) {
            Node* newNode = new Node{temp->item, nullptr};
            if (!result.head) result.head = newNode;
            else {
                Node* t = result.head;
                while (t->next) t = t->next;
                t->next = newNode;
            }
            result.size++;
        }
        temp = temp->next;
    }
    return result;
}

double List::averageMarkBySubject(const string& studentNumber, const string& subject) {
    Node* temp = head;
    while (temp) {
        if (temp->item.number == studentNumber) {
            int sum = 0, count = 0;
            for (const auto& g : temp->item.results) {
                if (g.subject == subject) {
                    sum += g.mark;
                    count++;
                }
            }
            if (count == 0) return 0.0;
            return static_cast<double>(sum) / count;
        }
        temp = temp->next;
    }
    return 0.0;
}

void List::saveToFile(const string& filename) const {
    ofstream file(filename);
    if (!file) return;
    file << size << "\n";
    Node* temp = head;
    while (temp) {
        file << temp->item.number << " " << temp->item.last_name << " "
             << temp->item.birth_day << " " << temp->item.group << "\n";
        file << temp->item.results.size() << "\n";
        for (const auto& g : temp->item.results) {
            file << g.subject << " " << g.date << " " << g.mark << "\n";
        }
        temp = temp->next;
    }
    file.close();
}

void List::print() const {
    Node* temp = head;
    int idx = 0;
    while (temp) {
        cout << "[" << idx << "] " << temp->item.last_name << " (" << temp->item.number << ") "
             << temp->item.group << " " << temp->item.birth_day << "\n";
        for (const auto& g : temp->item.results) {
            cout << "  " << g.subject << " (" << g.date << "): " << g.mark << "\n";
        }
        temp = temp->next;
        idx++;
    }
}

int List::getSize() const {
    return size;
}

ostream& operator<<(ostream& os, const List& list) {
    Node* temp = list.head;
    int idx = 0;
    while (temp) {
        os << "[" << idx << "] " << temp->item.last_name << " (" << temp->item.number << ")\n";
        temp = temp->next;
        idx++;
    }
    return os;
}


--------------------


main.cpp

#include "List.h"
#include <Windows.h>
#include <cstdlib>

int main(int argc, char* argv[]) {
    system("chcp 65001 > nul");
    SetConsoleOutputCP(65001);
    SetConsoleCP(65001);

    string filename = "data.txt";
    if (argc > 1) filename = argv[1];

    List list;
    list.loadFromFile(filename);
    cout << "Initial list:\n" << list << "\n";

    cout << "Add after index 1:\n";
    Student s{"200", "Testov", "10.10.2004", "101-И", {{"Alg", "01.01.2025", 5}}};
    list.addAfterIndex(1, s);
    cout << "After add:\n" << list << "\n";

    cout << "Delete 2 nodes from index 0:\n";
    list.deleteNFromIndex(0, 2);
    cout << "After delete:\n" << list << "\n";

    string bDate;
    cout << "Enter birth date to search: ";
    cin >> bDate;
    List found = list.findByBirthDate(bDate);
    cout << "Found by date " << bDate << ":\n" << found << "\n";

    string sNum, subj;
    cout << "Enter student number: ";
    cin >> sNum;
    cout << "Enter subject: ";
    cin >> subj;
    double avg = list.averageMarkBySubject(sNum, subj);
    cout << "Average: " << avg << "\n";

    list.saveToFile("output.txt");
    cout << "Saved to file.\n";

    return 0;
}

--------------------------------------

data.txt

5
101 Иванов 15.05.2004 101-И
2
Математика 10.10.2025 4
Физика 12.10.2025 3
102 Петров 20.03.2004 101-И
1
История 11.10.2025 5
103 Сидоров 01.07.2003 102-И
3
Математика 10.10.2025 3
Программирование 11.10.2025 2
Физика 12.10.2025 4
104 Кузнецов 14.12.2004 102-И
2
Физика 12.10.2025 3
Математика 15.10.2025 3
105 Смирнова 15.05.2004 101-И
1
История 11.10.2025 5