-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblatt07_a_neu.cpp
185 lines (150 loc) · 3.73 KB
/
blatt07_a_neu.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Programmentwurf zu Aufgabe 7a, WS 2014/2015
// Programmieren II fuer Mathematiker
// Includedateien
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
// #define DEBUG
using namespace std;
const unsigned TABLEMAXSIZE = 1 << 12;
template <typename T>
string vec2str(vector<T> const & vec)
{
ostringstream res("[");
res << '[';
if (!vec.empty())
{
auto it = vec.begin();
res << *it;
while (++it != vec.end())
{
res << ", " << *it;
}
}
res << ']';
return res.str();
}
template <typename I, typename T>
string map2str(map<I, T> const & m)
{
ostringstream res;
res << '[';
if (!m.empty())
{
auto it = m.begin();
res << '(' << it->first << ", " << it->second << ')';
while (++it != m.end())
{
res << ", " << '(' << it->first << ", " << it->second << ')';
}
}
res << ']';
return res.str();
}
class LZW {
private:
vector<string> stdtable;
string name_data,
name_comp;
public:
LZW(string name_data = "ein", string name_comp = "aus")
: name_data(name_data), name_comp(name_comp)
{
// Index anlegen und initialisieren
for (int ch = 0, i = 0; ch <= 255; ++ch, ++i)
{
string str(1, (char)ch);
stdtable.push_back(str);
}
}
void komprimieren()
{
auto table = stdtable;
map<string, int> index;
int j = 0;
for (auto it = stdtable.begin(); it != stdtable.end(); ++it, ++j)
{
index[*it] = j;
}
// Eingabedatei binaer zum Lesen oeffnen
ifstream ein;
ein.open(name_data, ifstream::binary);
if (!ein.good()) return;
// Ausgabedatei als Textdatei zum Schreiben oeffnen
ofstream aus;
aus.open(name_comp);
// Kompressionsalgorithmus durchfuehren
char ch;
ein.read(&ch, 1);
while (ein.good())
{
string sequenz(1, ch);
decltype(index.find(sequenz)) pos, pos_;
while ( (pos_ = index.find(sequenz)) != index.end() && !ein.eof() )
{
pos = pos_;
ein.read(&ch, 1);
sequenz.push_back(ch);
}
// pos->second() ist der Index der längsten Teilzeichenkette gerade noch in der Tabelle.
// pos_ ist auf jeden Fall index.end()
aus << pos->second << " ";
if (table.size() < TABLEMAXSIZE)
{
index[sequenz] = table.size();
table.push_back(sequenz);
ch = *(sequenz.rbegin());
sequenz.pop_back();
}
}
// Ein- und Ausgabedateien schliessen
ein.close();
aus.close();
// Groesse der Eingabedatei und geschaetzte Groesse der komprim. Datei ausgeben
}
void dekomprimieren()
{
ifstream ein;
ofstream aus;
ein.open(name_comp);
aus.open(name_data);
// stdtable bereits initialisiert.
vector<string> table = stdtable;
table.reserve(TABLEMAXSIZE);
while (ein.good())
{
int i; ein >> i;
aus << table[i];
if (table.size() < TABLEMAXSIZE)
{
auto pos = ein.tellg();
int j; ein >> j;
string s = table[i];
s.push_back(table.size() <= j ? table[j][0] : table[i][0]);
// table.push_back(s); // does not work, but WHY??
table.resize(table.size() + 1);
*table.rbegin() = s;
ein.seekg(pos, ein.beg);
}
}
ein.close();
aus.close();
}
};
int main()
{
string inpfile;
cout << "KOMPRESSION" << endl << endl;
cout << "Geben Sie einen Dateinamen ein:" << endl;
cin >> inpfile;
LZW lzwK(inpfile, inpfile + ".lzw");
lzwK.komprimieren();
cout << endl << endl;
return 0;
cout << "DEKOMPRESSION" << endl << endl;
LZW lzwD("aus.dat", "comp.lzw");
lzwD.dekomprimieren();
return 0;
}