<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[huffman codierung -&amp;gt; wirres zeug bei einigen daten]]></title><description><![CDATA[<p>Hallo</p>
<p>ich möchte den huffman codierer nachbauen. für kleine texte funktiniert das<br />
prima. für größere, insbesondere binärdateien klappt das aber nichtmehr, und<br />
warum das nicht klappt versteh ich nicht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>zuerst hab ich mir eine kleine bitstream klasse geschrieben, damit das<br />
bitgeschiebe sicherer wird.</p>
<pre><code class="language-cpp">class bitstream
{
public:
	bitstream() : frac(0)
	{
	}
	void pushbit(unsigned char bit)
	{
		bit &amp;= 1;

		if (!frac)
			vec.push_back(bit);
		else
			vec.back() |= bit &lt;&lt; frac;

		++frac;
		frac %= bitcount;
	}
	unsigned char getbit(unsigned pos) const
	{
		if (pos &gt;= getsize())
			return 0;

		return (vec[pos / bitcount] &gt;&gt; (pos % bitcount)) &amp; 1;
	}
	unsigned getsize() const
	{
		return vec.size() * bitcount + frac - (frac ? bitcount : 0);
	}
private:
	static const unsigned bitcount = 32;
	std::vector&lt;unsigned&gt; vec;
	unsigned frac; // rest eines 32-bit wortes
};
</code></pre>
<p>die benötigten struturen und funktionen:</p>
<pre><code class="language-cpp">struct node // ein knoten im graphen
{
	bool operator &lt; (const node &amp;other)
	{
		return num &lt; other.num;
	}
	node *left, *right;
	unsigned num;
	unsigned value;
};
struct lookup // tabelle, die die umwandlung zeichen -&gt; huffcode erlaubt
{
	unsigned data; // die bits
	unsigned length; // bit-länge
};
void build_lookup(lookup *l, node *p, unsigned char data, unsigned length)
{ // baut rekurisv die tabelle auf
	if (p-&gt;left)
	{
		build_lookup(l, p-&gt;left, data &lt;&lt; 1, length + 1);
		build_lookup(l, p-&gt;right, (data &lt;&lt; 1) | 1, length + 1);
	}
	else
	{
		l[p-&gt;value].data = data;
		l[p-&gt;value].length = length;
	}
}
</code></pre>
<p>als erstes zähle ich welches zeichen wie oft vorkommt. im zweiten teil (+256)<br />
des buffers speichere ich das zeichen selber um den buffer kompakt und ohne<br />
lücken(wichtig) zu halten:</p>
<pre><code class="language-cpp">const unsigned char *pstr = msg;
	const unsigned char *endptr = msg + strlen((char*)msg); //f.GetBufferSize();
	while (pstr != endptr)
	{
		bool found = false;
		for (unsigned i = 0; i &lt; max_pos; ++i)
		{
			if (buffer[256 + i] == *pstr)
			{
				++buffer[i];
				found = true;
				break;
			}
		}
		if (!found)
		{
			buffer[max_pos] = 1;
			buffer[256 + max_pos++] = *pstr;
		}
		++pstr;
	}
</code></pre>
<p>jetzt noch die baumstrucktur aufbauen:</p>
<pre><code class="language-cpp">node nodes[512];
	node *root = 0;
	for (unsigned i = 0; i &lt; max_pos; ++i)
	{
		nodes[i].left = 0;
		nodes[i].right = 0;
		nodes[i].num = buffer[i];
		nodes[i].value = buffer[256 + i];
	}
	unsigned index = 512; // position vor der neue elemente eingefügt werden
	while (max_pos &gt; 1)
	{
		node *min_node;

		min_node = std::min_element(nodes, nodes + max_pos);
		std::swap(*min_node, nodes[max_pos - 1]); // kleinstes element an das ende kopieren
		min_node = std::min_element(nodes, nodes + max_pos - 1);
		std::swap(*min_node, nodes[max_pos - 2]); // zweitkleinstes element vor das ende kopieren

		// platz freimachen (ans ende des buffers kopieren)
		nodes[--index] = nodes[max_pos - 1];
		nodes[--index] = nodes[max_pos - 2];

		node &amp;last = nodes[max_pos - 2]; // freigewordenes element

		last.left = &amp;nodes[index];
		last.right = &amp;nodes[index + 1];
		last.num = last.left-&gt;num + last.right-&gt;num;
		last.value = 0;

		root = &amp;last;

		--max_pos;
	}
</code></pre>
<p>danach &quot;nurnoch&quot; codieren und decodieren</p>
<pre><code class="language-cpp">lookup table[256];
build_lookup(table, root, 0, 0);

bitstream bs;

pstr = msg;
while (pstr != endptr)
{
	const lookup &amp;l = table[*pstr++];

	for (unsigned i = 0; i &lt; l.length; ++i)
		bs.pushbit(l.data &gt;&gt; (l.length - i - 1));
}

// decode
std::vector&lt;unsigned char&gt; decoded;

unsigned pos = 0;

while (bs.getsize() &gt; pos)
{
	node *pnode = root;
	while (pnode-&gt;left)
	{
		pnode = bs.getbit(pos) ? pnode-&gt;right : pnode-&gt;left;
		++pos;
	}
	decoded.push_back(pnode-&gt;value);
}
</code></pre>
<p>bei kleinen daten klappt es wie bereits gesagt. ich weiß echt nich woran<br />
das liegen kann, das programm läuft auch ohne absturz, warnung etc...</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/240544/huffman-codierung-gt-wirres-zeug-bei-einigen-daten</link><generator>RSS for Node</generator><lastBuildDate>Mon, 21 Sep 2026 22:54:57 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/240544.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 07 May 2009 18:37:44 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to huffman codierung -&amp;gt; wirres zeug bei einigen daten on Thu, 07 May 2009 18:37:44 GMT]]></title><description><![CDATA[<p>Hallo</p>
<p>ich möchte den huffman codierer nachbauen. für kleine texte funktiniert das<br />
prima. für größere, insbesondere binärdateien klappt das aber nichtmehr, und<br />
warum das nicht klappt versteh ich nicht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>zuerst hab ich mir eine kleine bitstream klasse geschrieben, damit das<br />
bitgeschiebe sicherer wird.</p>
<pre><code class="language-cpp">class bitstream
{
public:
	bitstream() : frac(0)
	{
	}
	void pushbit(unsigned char bit)
	{
		bit &amp;= 1;

		if (!frac)
			vec.push_back(bit);
		else
			vec.back() |= bit &lt;&lt; frac;

		++frac;
		frac %= bitcount;
	}
	unsigned char getbit(unsigned pos) const
	{
		if (pos &gt;= getsize())
			return 0;

		return (vec[pos / bitcount] &gt;&gt; (pos % bitcount)) &amp; 1;
	}
	unsigned getsize() const
	{
		return vec.size() * bitcount + frac - (frac ? bitcount : 0);
	}
private:
	static const unsigned bitcount = 32;
	std::vector&lt;unsigned&gt; vec;
	unsigned frac; // rest eines 32-bit wortes
};
</code></pre>
<p>die benötigten struturen und funktionen:</p>
<pre><code class="language-cpp">struct node // ein knoten im graphen
{
	bool operator &lt; (const node &amp;other)
	{
		return num &lt; other.num;
	}
	node *left, *right;
	unsigned num;
	unsigned value;
};
struct lookup // tabelle, die die umwandlung zeichen -&gt; huffcode erlaubt
{
	unsigned data; // die bits
	unsigned length; // bit-länge
};
void build_lookup(lookup *l, node *p, unsigned char data, unsigned length)
{ // baut rekurisv die tabelle auf
	if (p-&gt;left)
	{
		build_lookup(l, p-&gt;left, data &lt;&lt; 1, length + 1);
		build_lookup(l, p-&gt;right, (data &lt;&lt; 1) | 1, length + 1);
	}
	else
	{
		l[p-&gt;value].data = data;
		l[p-&gt;value].length = length;
	}
}
</code></pre>
<p>als erstes zähle ich welches zeichen wie oft vorkommt. im zweiten teil (+256)<br />
des buffers speichere ich das zeichen selber um den buffer kompakt und ohne<br />
lücken(wichtig) zu halten:</p>
<pre><code class="language-cpp">const unsigned char *pstr = msg;
	const unsigned char *endptr = msg + strlen((char*)msg); //f.GetBufferSize();
	while (pstr != endptr)
	{
		bool found = false;
		for (unsigned i = 0; i &lt; max_pos; ++i)
		{
			if (buffer[256 + i] == *pstr)
			{
				++buffer[i];
				found = true;
				break;
			}
		}
		if (!found)
		{
			buffer[max_pos] = 1;
			buffer[256 + max_pos++] = *pstr;
		}
		++pstr;
	}
</code></pre>
<p>jetzt noch die baumstrucktur aufbauen:</p>
<pre><code class="language-cpp">node nodes[512];
	node *root = 0;
	for (unsigned i = 0; i &lt; max_pos; ++i)
	{
		nodes[i].left = 0;
		nodes[i].right = 0;
		nodes[i].num = buffer[i];
		nodes[i].value = buffer[256 + i];
	}
	unsigned index = 512; // position vor der neue elemente eingefügt werden
	while (max_pos &gt; 1)
	{
		node *min_node;

		min_node = std::min_element(nodes, nodes + max_pos);
		std::swap(*min_node, nodes[max_pos - 1]); // kleinstes element an das ende kopieren
		min_node = std::min_element(nodes, nodes + max_pos - 1);
		std::swap(*min_node, nodes[max_pos - 2]); // zweitkleinstes element vor das ende kopieren

		// platz freimachen (ans ende des buffers kopieren)
		nodes[--index] = nodes[max_pos - 1];
		nodes[--index] = nodes[max_pos - 2];

		node &amp;last = nodes[max_pos - 2]; // freigewordenes element

		last.left = &amp;nodes[index];
		last.right = &amp;nodes[index + 1];
		last.num = last.left-&gt;num + last.right-&gt;num;
		last.value = 0;

		root = &amp;last;

		--max_pos;
	}
</code></pre>
<p>danach &quot;nurnoch&quot; codieren und decodieren</p>
<pre><code class="language-cpp">lookup table[256];
build_lookup(table, root, 0, 0);

bitstream bs;

pstr = msg;
while (pstr != endptr)
{
	const lookup &amp;l = table[*pstr++];

	for (unsigned i = 0; i &lt; l.length; ++i)
		bs.pushbit(l.data &gt;&gt; (l.length - i - 1));
}

// decode
std::vector&lt;unsigned char&gt; decoded;

unsigned pos = 0;

while (bs.getsize() &gt; pos)
{
	node *pnode = root;
	while (pnode-&gt;left)
	{
		pnode = bs.getbit(pos) ? pnode-&gt;right : pnode-&gt;left;
		++pos;
	}
	decoded.push_back(pnode-&gt;value);
}
</code></pre>
<p>bei kleinen daten klappt es wie bereits gesagt. ich weiß echt nich woran<br />
das liegen kann, das programm läuft auch ohne absturz, warnung etc...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1707400</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1707400</guid><dc:creator><![CDATA[huffi]]></dc:creator><pubDate>Thu, 07 May 2009 18:37:44 GMT</pubDate></item><item><title><![CDATA[Reply to huffman codierung -&amp;gt; wirres zeug bei einigen daten on Fri, 08 May 2009 09:44:03 GMT]]></title><description><![CDATA[<p>Ehrlich gesagt, ist mir das zu viel zum Durchlesen. An deiner Stelle würde ich mir Stift und Zettel schnappen und parallel zum Debugger von Hand mitrechnen. Dann sollte dein Fehler schon auffallen. Mit ein wenig Geschick ist das nicht allzu viel Arbeit.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1707626</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1707626</guid><dc:creator><![CDATA[Michael E.]]></dc:creator><pubDate>Fri, 08 May 2009 09:44:03 GMT</pubDate></item></channel></rss>