111111
unknown
plain_text
2 years ago
5.3 kB
4
Indexable
#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; }
Editor is loading...