You are on page 1of 8

Міністерство освіти і науки України

Вінницький національний технічний університет


Факультет інформаційних технологій та комп'ютерної інженерії
Кафедра програмного забезпечення

Лабораторна робота №2
з дисципліни “Кодування та захист інформації ”
застосування словникових методів

Виконала:
студентка ВНТУ групи 2ПІ-18б
Богач К.С
Перевірив:
Майданюк В.П

Вінниця 2021
2

Лабораторна робота №2
МЕТА:Отримати практичні навики застосування словникових методів

ХІД РОБОТИ

LZW метод

Запропонований у 1984 р. Велчем.


При стисненні та відновленні LZW маніпулює трьома об`єктами:
потоком символів, потоком кодів і таблицею рядків.
Перевіряється, чи траплявся даний рядок. Якщо так, зчитується
наступний символ, ні – заноситься в таблицю.

Рисунок 1 - LZW метод


3

Лістинг

// ConsoleApplication36.cpp
//

#include "stdafx.h"
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
#include <sys/stat.h>
#include <math.h>
using namespace std;
template <typename Iterator>
Iterator compress(const std::string &uncompressed, Iterator result) {//зжаття
int dictSize = 256;
int maxSize = 4096;
std::map<std::string, int> dictionary;
for (int i = 0; i < 256; i++)
dictionary[std::string(1, i)] = i;

std::string w;
for (std::string::const_iterator it = uncompressed.begin(); it !=
uncompressed.end(); ++it) {
char c = *it;
std::string wc = w + c;
if (dictionary.count(wc))
w = wc;
else {
*result++ = dictionary[w];

if (dictSize < maxSize) {


dictionary[wc] = dictSize++;
}
w = std::string(1, c);
}
}

if (!w.empty())
*result++ = dictionary[w];
return result;
}

template <typename Iterator>


std::string decompress(Iterator begin, Iterator end) {
int dictSize = 256;
std::map<int, std::string> dictionary;
for (int i = 0; i < 256; i++)
dictionary[i] = std::string(1, i);

std::string w(1, *begin++);


std::string result = w;
std::string entry;
for (; begin != end; begin++) {
int k = *begin;
if (dictionary.count(k))
4

entry = dictionary[k];
else if (k == dictSize)
entry = w + w[0];
else
throw "Bad compressed k";

result += entry;

if (dictSize < 4096) {


dictionary[dictSize++] = w + entry[0];
}
w = entry;
}
return result;
}

std::string int2BinaryString(int c, int cl) {


std::string p = "";
while (c>0) {
if (c % 2 == 0)
p = "0" + p;
else
p = "1" + p;
c = c >> 1;
}
int zeros = cl - p.size();
if (zeros<0) {
std::cout << “Nebezpeka";
p = p.substr(p.size() - cl);
}
else {
for (int i = 0; i<zeros; i++)
p = "0" + p;
}
return p;
}

int binaryString2Int(std::string p) {
int code = 0;
if (p.size()>0) {
if (p.at(0) == '1')
code = 1;
p = p.substr(1);
while (p.size()>0) {
code = code << 1;
if (p.at(0) == '1')
code++;
p = p.substr(1);
}
}
return code;
}

std::vector<int> grabIntsFromCompressedString(std::string binString) {


std::vector<int> result;
std::string temp;
for (unsigned int i = 0; i < binString.length(); i++) {
temp += binString[i];
if (temp.length() >= 12) {
result.push_back(binaryString2Int(temp));
temp = "";
}
5

}
if (temp.length() != 0) {

}
return result;
}

void writeCompressedToFile(std::vector<int> compressed, const char* file) {


std::string bcode = "";
std::string p = "";
int bits;
for (std::vector<int>::iterator it = compressed.begin(); it != compressed.end();
++it) {
bits = 12;
p = int2BinaryString(*it, bits);

bcode += p;
}

std::ofstream myfile;
myfile.open(file, std::ios::binary);

std::string zeros = "00000000";


if (bcode.size() % 8 != 0)
bcode += zeros.substr(0, 8 - bcode.size() % 8);

int b;
for (unsigned int i = 0; i < bcode.size(); i += 8) {
b = 1;
for (int j = 0; j < 8; j++) {
b = b << 1;
if (bcode.at(i + j) == '1')
b += 1;
}
char c = (char)(b & 255);
myfile.write(&c, 1);
}
cout <<endl<< bcode; //бінарний код рядок

myfile.close();
}

std::string readCompressedFromFile(const std::string filename) {


std::ifstream myfile2;
myfile2.open(filename.c_str(), std::ios::binary);
struct stat filestatus;
stat(filename.c_str(), &filestatus);
long fsize = filestatus.st_size;

std::string zeros = "00000000";

char c2[1226];
myfile2.read(c2, fsize);

std::string s = "";
long count = 0;
while (count<fsize) {
unsigned char uc = (unsigned char)c2[count];
std::string p = "";
6

for (int j = 0; j<8 && uc>0; j++) {


if (uc % 2 == 0)
p = "0" + p;
else
p = "1" + p;
uc = uc >> 1;
}
p = zeros.substr(0, 8 - p.size()) + p;
s += p;
count++;
}
myfile2.close();
return s;
}

std::string readAllBytes(char const* filename) {


std::ifstream f(filename);
std::string theString((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
f.close();
return theString;
}

void writeAllBytes(std::string &message, std::string filename) {


std::ofstream fout(filename.c_str());
fout << message;
fout.close();
}

int main() {
std::vector<int> compressed;

std::string filename = "E:\\e.txt";

double Pi[11];
Pi[0] = 0.07;
Pi[1] = 0.13;
Pi[2] = 0.13;
Pi[3] = 0.07;
Pi[4] = 0.13;
Pi[5] = 0.07;
Pi[6] = 0.13;
Pi[7] = 0.07;
Pi[8] = 0.07;
Pi[9] = 0.07;
Pi[10] = 0.07;
double logar=0;
for (int i = 0; i < 11; i++)
{
logar += -(Pi[i])*(log(Pi[i]));

}
cout << "Entropia";//ентропія
cout << logar;

const char* cstrFilename = filename.c_str();


std::string newFilename = filename + ".lzw";
const char* cstrNewFilename = newFilename.c_str();

std::string message = readAllBytes(cstrFilename);


7

compress(message, std::back_inserter(compressed));

writeCompressedToFile(compressed, cstrNewFilename);

_gettch();
return 0;
}

ЗНІМКИ ЕКРАНУ

Рисунок 2 – Початковий розмір

Рисунок 3 – Результат роботи програми

Стиснення: 272/158 = 1,72 рази

Рисунок 4 – Бітовий код


8

Рисунок 5 – Ентропія

ВИСНОВКИ

Метод LZW належить до словникових методів.


Кожний раз, коли генерується код, новий рядок добавляється в таблицю
рядків. LZW постійно перевіряє, чи даний рядок вже відомий, і, якщо так,
виводить код без генерування нового.
Таблиця може бути точно відновлена на основі вихідного потоку
алгоритму стиснення.
Досягнено стиснення в 1,72 рази.

You might also like