Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Хаффман и не правильное разархивирование, выводит лишние/не подходящие символы 
V
    Опции темы
cristaloleg
Дата 12.1.2010, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 15.6.2009
Где: Donetsk

Репутация: нет
Всего: нет



Я уже долго работаю с кодировкой методом Хаффмана...сделано много(для меня), и вот: он уже строит дерево, архивирует файл, но разархивировать не получается!!!

Почему не пойму(как всегда =) ). Алгоритм архивации таков: подсчитываем скок и каких символов в файле, строим дерево, записываем инфу(не много) для восстановления и потом кодируем в файл.

Алгоритм разархивирования: из информации для разархивирования строим дерево, преобразуем в
коды(0 и 1), и выводим в файл.(Вот здесь и проблема работы! =( )

Код

#include <iostream>
#include <fstream>
#include <string.h>
#include <windows.h>
#include <algorithm>
#include <vector>
using namespace std;
 
class Huffman
{
private:
        char *key;                                                                      //значение ветки
        unsigned long int **mas;                                        //храним таблицу символов
        char *file;                                                                     //файл
        //тут добавить map<int, char>
        unsigned long int all, plus;                            //кол-во всех элементов(в файле), и положительных(для таблицы)
        Huffman *parent, *left, *right;                         //указатели на ближние значения
public:
        Huffman();                                                                      //конструктор
        ~Huffman();                                                                     //деструктор
 
        void Archive(char *path);                                       //архивировать файл
        void Extract(char *path);                                       //разархивировать файл
        
        void SetFile(char *f);                                          //установить файл для работы(не нужно, если сделать пред. ф-ции)
 
        void Write();                                                           //считываем символ, сравниваем с базой, добаляем в масив дял дальнейшего...
        void/*long int **/Read();                                       //
 
        Huffman *GoUp();                                                        //переход к корню(самый верх)
 
        unsigned long int GetPlus();                            //кол-во положительных элементов
        unsigned long int * SearchMin();                        //поиск двух наименьших в файле
        char GetFromMas(unsigned long int k);           //получить элемент из таблицы(символ)
 
        void PutBit(unsigned long int &This, unsigned long int &count, int bit, ofstream &out); //шифруем
        int Getbit(unsigned long int &This, unsigned long int &count, ifstream &in);                    //дешифруем
 
 
        Huffman *CreateTree(char k1, char k2);          //задаём "корень" дерева(можно будет изменить и задавать ток правый элемент...а дальше след. ф-цией)
        Huffman *AddParent(char k);                                     //задаём следующего предка
        Huffman *AddLeaf(char k);                                       //задаём значение в правой ветке
 
        Huffman *CreateTabl();                                          //вывод всего дерева
        void Print();                                                           //вывод тек. значения
};
 
void main()
{
        setlocale(LC_CTYPE, "Russian");
        Huffman *tree = new Huffman();
        char path[100]={0};
        
        cout<<"Please input file: ";
        cin>>path;
        tree -> SetFile(path);
 
        /*tree -> SearchMin();
        tree = tree -> CreateTree(tree -> GetFromMas(0), tree -> GetFromMas(1));
        cout << "\tStarting...\n";
        int l = tree -> GetPlus();
        for(unsigned long int i = 2; i < l; ++i)
        {
                char k = tree -> GetFromMas(i);
                tree = tree -> AddParent(k);
        }
        tree -> CreateTabl();
        unsigned long int i = 0;
        tree -> Read();*/
        tree -> Write();
        cout << "\n\tFinish!!!\n\a";
}
 
void Huffman :: Read()
{
        GoUp();
        Huffman *obj = this;
        unsigned long int k = 0, i = 1;
        unsigned long int This = 0, count = 0, bit = 0;
        char ch[2];
 
        vector<int> my_vector;
        
        ifstream in;    in.open(file);
        strcat(file, ".huf");
        ofstream out;   out.open(file, ios::binary);
 
        //теги для разкодирования...
        while(obj -> left)
                obj = obj -> left;
 
        out << plus << " ";
        out << ((int)*(obj -> key)) << " ";
        obj = obj -> parent;
        out << ((int)*(obj -> right -> key));
        obj = obj -> parent;
        
        while(obj)
        {
                out << " " << ((int)*(obj -> right -> key));
                obj = obj -> parent;
        }
        out << " ";
 
        ch[1] = '\0';
        
        for(i; i < all-1; ++i)
        {
                in.get(ch[0]);
 
                Huffman *obj = this;
                while(obj -> left != NULL)
                {
                        if(strcmp(obj -> right -> key, &ch[0]) == 0)
                        {
                                my_vector.push_back(1);
                                break;
                        }
                        obj = obj -> left;
                        my_vector.push_back(0);
                }
                GoUp();
        }
        in.close();
 
        cout << all << "\n";
        k = my_vector.size();
        
        ofstream out2("e:\\1.txt");
 
        for(i = 0; i < 8*(k/8); ++i)
        {
                PutBit(This, count, my_vector[i], out);
                out2 << my_vector[i];
        }
        for(i; i < k; ++i)
        {
                This = This | (my_vector[i] << count);
                ++count;
                
                if(i == k-1)
                {
                        out << (char)This;
                        count = 0;
                        This = 0;
                }
        }
        out.close();
        my_vector.clear();
}
 
void Huffman :: PutBit(unsigned long int &This, unsigned long int &count, int bit, ofstream &out)
{
        This = This | (bit << count);
        ++count;
        
        if(count == 8)
        {
                out << (char)This;
                count = 0;
                This = 0;
        }
}
 
void Huffman :: Write()
{
        Huffman *obj = this;
        unsigned long int i, This = 0, count = 8;
        char *f = new char;
 
        vector<int> my_vector;
 
        ifstream in;    in.open(file);
        strcat(file, ".uhuf");
        ofstream out;   out.open(file);
 
        unsigned long int s, k;
        in >> s;
 
        for(i = 0; i < s; ++i)
        {
                in >> k;
                mas[1][i] = k;
        }
 
        for(i = 0; i < s; ++i)
                cout << (char)mas[1][i] << "\n";
 
        obj -> mas = mas;
        obj = obj -> CreateTree(obj -> GetFromMas(0), obj -> GetFromMas(1));
        for(int j = 2; j < s; ++j)
        {
                char k = obj -> GetFromMas(j);
                obj = obj -> AddParent(k);
        }
        system("cls");
        obj -> CreateTabl();
 
        ofstream out2("E:\\2.txt");
 
        while(in)
        {
                my_vector.push_back(Getbit(This, count, in));
                out2 << my_vector.back();
        }
        out2.close();
        This = 0;
        count = 0;
        s = my_vector.size();
        i = 8;
 
        while(i < s)
        {
                obj = obj -> GoUp();
                while(true)
                {
                        if(i >= s)
                                break;
                        if(my_vector[i] == 0)
                        {
                                if(obj -> left)
                                        obj = obj -> left;
                                else
                                        obj = obj -> GoUp();
                                ++i;
                        }
                        else
                        {
                                if(obj -> right)
                                        f = obj -> right -> key;
                                else
                                        f = key;
                                ++i;
                                break;
                        }
                }
                out.write(f, strlen(f));
        }
        in.close();
        out.close();
        my_vector.clear();
}
 
int Huffman :: Getbit(unsigned long int &This, unsigned long int &count, ifstream &in)
{
        char k;
        int bit;
        if(count == 8)
        {
                in.get(k);
                This = k;
                count = 0;
        }
        
        bit = (This >> count) & 1;
        ++count;
        return bit;
}
 
unsigned long int *Huffman :: SearchMin()
{
        /*
        сделать map<int, char>... в котором буду хранить инфу о символах...
        сделать сортировку так, чтобы в поле int сортировались(по убыванию???) все, кроме нулей(и отр, если баги)
        ДОБАВИТЬ map в класс...как член!!!
        */
        unsigned int j, k;
        unsigned long int  ch;
        ifstream in(file);
 
        while(in)
        {
                char k;         in.get(k);      j = k;
                mas[0][j]++;
                all++;
        }
        in.close();
        for(int i = 0; i < 64; ++i)
        {
                for(int j = 0; j < 254; ++j)
                {
                        if((mas[0][j] > mas[0][j+1] && mas[0][j+1] > 0) || (mas[0][j] < mas[0][j+1] && mas[0][j] == 0))
                        {
                                k = mas[0][j];
                                mas[0][j] = mas[0][j+1];        
                                mas[0][j+1] = k;
                                
                                ch = mas[1][j];
                                mas[1][j] = mas[1][j+1];
                                mas[1][j+1] = ch;
                        }
                }
        }
 
        for(int i=0; i<255; ++i)
        {
                if(mas[0][i] != 0)
                        plus++;
                cout << mas[0][i] << " " << (char)mas[1][i] << "\n";
        }
        plus++;
        for(int j = 0; j < 20; ++j)
        {
                for(int i=0; i<plus; ++i)
                {
                        if((mas[0][i] > mas[0][i+1] && mas[0][i+1] > 0)/* || (mas[0][i] < mas[0][i+1] && mas[0][i] == 0)*/)
                        {
                                k = mas[0][i];
                                mas[0][i] = mas[0][i+1];        
                                mas[0][i+1] = k;
                                
                                ch = mas[1][i];
                                mas[1][i] = mas[1][i+1];
                                mas[1][i+1] = ch;
                        }
                }
        }
        system("cls");
        for(int i = 0; i < plus; ++i)
        {
                cout << mas[0][i] << " " << (char)mas[1][i] << "\n";
        }
        return NULL;
}
 
Huffman *Huffman :: AddParent(char k)
{
        Huffman *buf = new Huffman;
        parent = buf;
        
        delete[] buf -> mas[0];
        delete[] buf -> mas[1];
        
        buf -> mas = mas;
        buf -> all = all;
        buf -> plus = plus;
        buf -> file = file;
        buf -> left = this;
        buf -> right = new Huffman;
        buf -> right = buf -> right -> AddLeaf(k);      
        return buf;
}
 
Huffman *Huffman :: AddLeaf(char k)
{
        strcpy(key, &k);
        return this;
}
 
Huffman *Huffman :: CreateTree(char k1, char k2)
{
        parent = NULL;
        
        left = new Huffman;
        strcpy(left -> key, &k1);
        left -> parent = this;
        
        right = new Huffman;
        strcpy(right -> key, &k2);
        right -> parent = this;
        
        char *c = new char;
        strcpy(c, &k1);
        strcat(c, &k2);
        key = c;
        return this;
}
 
Huffman :: Huffman()
{
        all = 0;
        plus = 0;
        key = new char;
        file = NULL;
 
        mas = new unsigned long int*[2];
        mas[0] = new unsigned long int[255];
        mas[1] = new unsigned long int[255];
        for(int i = 0; i < 255; ++i)
        {
                mas[0][i] = 0;
                mas[1][i] = i;
        }
        parent = NULL;
        left = NULL;
        right = NULL;
}
 
Huffman :: ~Huffman()
{
        delete parent, right, left, key;
}
 
void Huffman :: SetFile(char *f)
{
        file = f;
}
 
Huffman *Huffman :: GoUp()
{
        Huffman *obj = this;
        while(obj -> parent)
                obj = obj -> parent;
        return obj;
}
 
char Huffman :: GetFromMas(unsigned long int k)
{
        return ((char)mas[1][k]);
}
 
unsigned long int Huffman :: GetPlus()
{
        return plus;
}
 
Huffman *Huffman :: CreateTabl()
{
        Huffman *obj = this;
        while(obj -> left)
        {
                obj -> right -> Print();
                cout << "\n";
                obj = obj -> left;
        }
        obj -> Print();
        obj = GoUp();
        return obj;
}       
 
void Huffman :: Print()
{
        cout << key;
}
 
void Huffman :: Archive(char *path)
{
        Huffman *tree = new Huffman;
        tree -> SetFile(path);
 
        tree -> SearchMin();
        tree = tree -> CreateTree(tree -> GetFromMas(0), tree -> GetFromMas(1));
        int l = tree -> GetPlus();
        for(unsigned long int i = 2; i < l; ++i)
        {
                char k = tree -> GetFromMas(i);
                tree = tree -> AddParent(k);
        }
        tree -> Read();
}
 
void Huffman :: Extract(char *path)
{
        Huffman *obj = this;
        unsigned long int i, This = 0, count = 8;
        char *f = new char;
 
        vector<int> my_vector;
 
        ifstream in;    in.open(path, ios_base::binary);
        strcat(path, ".uhuf");
        ofstream out;   out.open(path, ios::binary);
        unsigned long int s;    in >> s;        in.read(f, s+1);        cout << f;
 
        for(i = 5; i < s-5; ++i)
        {
                mas[1][i-5] = f[i];
        }
        
        s -= 10;
        for(i = 0; i < s; ++i)
                cout << (char)mas[1][i] << "\n";
 
        obj -> mas = mas;
        obj = obj -> CreateTree(obj -> GetFromMas(0), obj -> GetFromMas(1));
        for(int j = 2; j < s; ++j)
        {
                char k = obj -> GetFromMas(j);
                obj = obj -> AddParent(k);
        }
        system("cls");
        obj -> CreateTabl();
 
        while(in)
        {
                my_vector.push_back(Getbit(This, count, in));
        }
        This = 0;
        count = 0;
        s = my_vector.size();
        i = 0;
 
        while(i < s)
        {
                obj = obj -> GoUp();
                while(true)
                {
                        if(i >= s)
                                break;
                        if(my_vector[i] == 0)
                        {
                                if(obj -> left)
                                        obj = obj -> left;
                                else
                                        obj = obj -> GoUp();
                                ++i;
                        }
                        else
                        {
                                if(obj -> right)
                                        f = obj -> right -> key;
                                else
                                        f = key;
                                ++i;
                                break;
                        }
                }
                out.write(f, strlen(f));
        }
        in.close();
        out.close();
        my_vector.clear();
}


примечание: функция Read архивирует файл, разархивирует Write...во всяком случае должна...

Спасибо за помощь.
PM   Вверх
xvr
Дата 13.1.2010, 12:52 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Эта такая головоломка - 'вот вам 500 срок, угадайте, что (и где) не так!' ?  smile 

PM MAIL   Вверх
Earnest
Дата 13.1.2010, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(cristaloleg @  12.1.2010,  18:45 Найти цитируемый пост)
он уже строит дерево, архивирует файл, но разархивировать не получается!!!

Совершенно не факт, что архивируется правильно.
Тебе нужно сделать следующее: создать простой тест, который ты можешь пройти "руками". Сначала заархивируй, проверяя пошагово, что получается. Если все правильно - то же самое проделай для разархивации.
А рассчитывать, что кто-то это за тебя сделает... ну извини smile 


--------------------
...
PM   Вверх
mes
Дата 13.1.2010, 13:40 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(cristaloleg @  12.1.2010,  16:45 Найти цитируемый пост)
функция Read архивирует файл, разархивирует Write..

 smile 

cristaloleg,  пробежав по коду глазами, почувствовал, что Вам нужно серьезней относится к тому, что написано в Вашей подписи.
 smile 



--------------------
PM MAIL WWW   Вверх
Albor
Дата 13.1.2010, 13:41 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: нет
Всего: 9



Извиняюсь, но как это похоже на анекдот!
- Я сделал архиватор, сжимающий файл любого размера в 4 байта, но есть проблемка!
- Молодец, проблемка какая?
- Не могу написать разархиватор!

PM MAIL ICQ   Вверх
Earnest
Дата 13.1.2010, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



mes, Albor, порадовали! smile  


--------------------
...
PM   Вверх
cristaloleg
Дата 13.1.2010, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 15.6.2009
Где: Donetsk

Репутация: нет
Всего: нет



всё...больше можете не помогать...сам как нибудь
PM   Вверх
Albor
Дата 13.1.2010, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: нет
Всего: 9



Обиделся, да?
Цитата(cristaloleg @  13.1.2010,  17:21 Найти цитируемый пост)
всё...больше можете не помогать...сам как нибудь 

А знаешь, хорошая мысль! Главное - очень полезно самому выявить свои ошибки.
PM MAIL ICQ   Вверх
cristaloleg
Дата 13.1.2010, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 15.6.2009
Где: Donetsk

Репутация: нет
Всего: нет



Цитата(Albor @  13.1.2010,  17:01 Найти цитируемый пост)
Обиделся, да?

А знаешь, хорошая мысль! Главное - очень полезно самому выявить свои ошибки. 


нет не обиделся smile 
я знаю что хорошая идея smile 

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0677 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.