111111
unknown
plain_text
2 years ago
5.3 kB
5
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...