111111

mail@pastecode.io avatar
unknown
plain_text
a year ago
5.3 kB
2
Indexable
Never
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <fstream>
using namespace std;

class Node
{
public:
    int a;
    char c;
    Node* left, * right;

    Node() { left = right = NULL; }

    Node(Node* L, Node* R)
    {
        left = L;
        right = R;
        a = L->a + R->a;
    }
};

struct MyCompare
{
    bool operator()(const Node* l, const Node* r) const { return l->a < r->a; }
};

vector<bool> code;
map<char, vector<bool> > table;
Node* root; // Global variable root

void BuildTable(Node* root)
{
    if (root->left != NULL)
    {
        code.push_back(0);
        BuildTable(root->left);
    }

    if (root->right != NULL)
    {
        code.push_back(1);
        BuildTable(root->right);
    }

    if (root->left == NULL && root->right == NULL) {
        table[root->c] = code;
    }

    // Clear the code vector before returning from each recursive call
    if (!code.empty()) {
        code.pop_back();
    }
}

void processFile(const string& filename, const string& encodedFilename)
{
    ifstream f(filename, ios::out | ios::binary);

    map<char, int> m;

    while (!f.eof())
    {
        char c = f.get();
        m[c]++;
    }

    list<Node*> t;
    for (map<char, int>::iterator itr = m.begin(); itr != m.end(); ++itr)
    {
        Node* p = new Node;
        p->c = itr->first;
        p->a = itr->second;
        t.push_back(p);
    }

    while (t.size() != 1)
    {
        t.sort(MyCompare());

        Node* SonL = t.front();
        t.pop_front();
        Node* SonR = t.front();
        t.pop_front();

        Node* parent = new Node(SonL, SonR);
        t.push_back(parent);
    }

    root = t.front(); // Assign the root value to the global variable

    BuildTable(root);

    f.clear();
    f.seekg(0);

    ofstream g(encodedFilename, ios::out | ios::binary);

    int count = 0;
    char buf = 0;
    while (!f.eof())
    {
        char c = f.get();
        vector<bool> x = table[c];
        for (int n = 0; n < x.size(); n++)
        {
            buf = buf | x[n] << (7 - count);
            count++;
            if (count == 8) {
                count = 0;
                g.write(reinterpret_cast<const char*>(&buf), sizeof(buf));
                buf = 0;
            }
        }
    }

    f.close();
    g.close();
}

void decodeFile(const string& encodedFilename, const string& decodedFilename)
{
    ifstream F(encodedFilename, ios::in | ios::binary);
    ofstream ass(decodedFilename, ios::out | ios::binary);

    setlocale(0, "Russian");

    Node* p = root;
    int count = 0;
    char byte;
    F.read(reinterpret_cast<char*>(&byte), sizeof(byte));
    while (!F.eof())
    {
        bool b = byte & (1 << (7 - count));
        if (b) p = p->right;
        else p = p->left;
        if (p->left == NULL && p->right == NULL) {
            ass.write(reinterpret_cast<const char*>(&p->c), sizeof(p->c));
            p = root;
        }
        count++;
        if (count == 8) {
            count = 0;
            F.read(reinterpret_cast<char*>(&byte), sizeof(byte));
        }
    }

    F.close();
    ass.close();
}

void menu()
{
    setlocale(0, "Russian");
    int choice;
    bool exitMenu = false;

    while (!exitMenu)
    {
        std::cout << "Меню:\n";
        std::cout << "1) Закодировать файлы\n";
        std::cout << "2) Декодировать файл\n";
        std::cout << "3) Выход\n";
        std::cout << "Выберите пункт меню: ";
        std::cin >> choice;

        switch (choice)
        {
        case 1:
        {
            int numFiles;
            std::cout << "Введите количество файлов для закодировки: ";
            std::cin >> numFiles;

            for (int i = 0; i < numFiles; ++i)
            {
                std::string filename, encodedFilename;
                std::cout << "Введите имя файла " << i + 1 << ": ";
                std::cin >> filename;
                std::cout << "Введите имя закодированного файла " << i + 1 << ": ";
                std::cin >> encodedFilename;
                processFile(filename, encodedFilename);
                std::cout << "Файл " << filename << " успешно закодирован в " << encodedFilename << ".\n";
            }
            break;
        }
        case 2:
        {
            std::string encodedFilename, decodedFilename;
            std::cout << "Введите имя закодированного файла: ";
            std::cin >> encodedFilename;
            std::cout << "Введите имя декодированного файла: ";
            std::cin >> decodedFilename;
            decodeFile(encodedFilename, decodedFilename);
            std::cout << "Файл " << encodedFilename << " успешно декодирован в " << decodedFilename << ".\n";
            break;
        }
        case 3:
            exitMenu = true;
            std::cout << "Выход из программы.\n";
            break;
        default:
            std::cout << "Неверный выбор. Попробуйте снова.\n";
            break;
        }
    }
}

int main()
{
    menu();

    return 0;
}