<?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[Eleganteste Lösung für Dynamischen String]]></title><description><![CDATA[<p>Ich komme von C# und versuche mein C++ zu verbessern. Zu Anfang versuche ich mich an einem NBT (&quot;Minecraft&quot; Tag Format) Parser .</p>
<p>Ich lese eine Datei im genannten NBT Format ein welche aus vielen dieser &quot;Tags&quot; besteht. Diese Tags liegen im Speicher hintereinander und haben unterschiedliche Größen.</p>
<p>Betrachtet man den Anfang eines einzelnen Tags:</p>
<pre><code>#pragma pack(push, 1)

struct NbtNode {
TagType tag_type; //Typ des Tags (1-10) //1 Byte
int16_t tag_name_length; //Länge des Tag-Namen der darauf folgt //2 byte
char tag_name[tag_name_length]; //Name des Tags
...
};

#pragma pack(pop)
</code></pre>
<pre><code>//Damit arbeiten
NbtNode* node = (NbtNode*)buffer; //buffer ist die zuvor eingelesen Datei im NBT Format

node-&gt;tag_name_length; 
node = node-&gt;next_node;
//etc
</code></pre>
<p>Das Problem ist natürlich, dass die Größe von tag_name erst zur Laufzeit bekannt ist (bzw. nachdem man die Datei eingelesen und interpretiert hat) und diese wichtig ist, um das struct weiterhin korrekt auf den Speicher anwenden zu können. Gibt es eine &quot;elegante&quot; Lösung zu diesem Problem?</p>
<pre><code>struct NbtNode {
	TagType tag_type;
	int16_t tag_name_length;
	char  tag_name[];
}
</code></pre>
<p>Ist zwar möglich aber die Tag-Namen sind nicht 0-terminiert.</p>
<p>Danke schon mal im voraus.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/331313/eleganteste-lösung-für-dynamischen-string</link><generator>RSS for Node</generator><lastBuildDate>Fri, 01 May 2026 15:51:21 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/331313.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 21 Feb 2015 15:27:45 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sat, 21 Feb 2015 15:27:45 GMT]]></title><description><![CDATA[<p>Ich komme von C# und versuche mein C++ zu verbessern. Zu Anfang versuche ich mich an einem NBT (&quot;Minecraft&quot; Tag Format) Parser .</p>
<p>Ich lese eine Datei im genannten NBT Format ein welche aus vielen dieser &quot;Tags&quot; besteht. Diese Tags liegen im Speicher hintereinander und haben unterschiedliche Größen.</p>
<p>Betrachtet man den Anfang eines einzelnen Tags:</p>
<pre><code>#pragma pack(push, 1)

struct NbtNode {
TagType tag_type; //Typ des Tags (1-10) //1 Byte
int16_t tag_name_length; //Länge des Tag-Namen der darauf folgt //2 byte
char tag_name[tag_name_length]; //Name des Tags
...
};

#pragma pack(pop)
</code></pre>
<pre><code>//Damit arbeiten
NbtNode* node = (NbtNode*)buffer; //buffer ist die zuvor eingelesen Datei im NBT Format

node-&gt;tag_name_length; 
node = node-&gt;next_node;
//etc
</code></pre>
<p>Das Problem ist natürlich, dass die Größe von tag_name erst zur Laufzeit bekannt ist (bzw. nachdem man die Datei eingelesen und interpretiert hat) und diese wichtig ist, um das struct weiterhin korrekt auf den Speicher anwenden zu können. Gibt es eine &quot;elegante&quot; Lösung zu diesem Problem?</p>
<pre><code>struct NbtNode {
	TagType tag_type;
	int16_t tag_name_length;
	char  tag_name[];
}
</code></pre>
<p>Ist zwar möglich aber die Tag-Namen sind nicht 0-terminiert.</p>
<p>Danke schon mal im voraus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443707</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443707</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Sat, 21 Feb 2015 15:27:45 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sat, 21 Feb 2015 15:41:59 GMT]]></title><description><![CDATA[<p>Nimm std::string.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443710</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443710</guid><dc:creator><![CDATA[Hyde++ 0]]></dc:creator><pubDate>Sat, 21 Feb 2015 15:41:59 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sat, 21 Feb 2015 16:03:32 GMT]]></title><description><![CDATA[<p>Das wäre natürlich möglich wenn mein struct nicht ein bestimmtes Format/Größe einhalten müsste.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443712</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443712</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Sat, 21 Feb 2015 16:03:32 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sat, 21 Feb 2015 16:16:05 GMT]]></title><description><![CDATA[<p>Muss sie nicht. Du (sie) muss nur Möglichkeiten zum de-/serialisieren haben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443717</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443717</guid><dc:creator><![CDATA[Swordfish]]></dc:creator><pubDate>Sat, 21 Feb 2015 16:16:05 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sat, 21 Feb 2015 17:08:52 GMT]]></title><description><![CDATA[<p>Danke für das Stichwort.</p>
<pre><code>NbtNode* node = new NbtNode(is); //is = ifstream
</code></pre>
<pre><code>struct NbtNode {
	TagType tag_type;
	int16_t tag_name_length;
	std::string  tag_name;

	NbtNode(std::ifstream&amp; is) : tag_type((TagType)12), tag_name_length(0)
	{
		deserialize(is);
	}

	std::ifstream&amp; deserialize(std::ifstream&amp; is) {
		is.read((char*)&amp;tag_type, 1);
		is.read((char*)&amp;tag_name_length, 2);
		is.read((char*)&amp;tag_name, tag_name_length);
		return is;
	}

};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2443723</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443723</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Sat, 21 Feb 2015 17:08:52 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sat, 21 Feb 2015 17:29:44 GMT]]></title><description><![CDATA[<p>Wieso new? Und dein read ist falsch. Du musst erst den String auf die Größe bringen und dann in den Zeichenspeicher lesen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443725</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443725</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Sat, 21 Feb 2015 17:29:44 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sat, 21 Feb 2015 17:33:30 GMT]]></title><description><![CDATA[<p>Vivida schrieb:</p>
<blockquote>
<pre><code>tag_type((TagType)12), // ...
</code></pre>
</blockquote>
<p>Schaut auch grausig aus. Ist <code>TagType</code> denn kein <code>enum</code> ??</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443726</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443726</guid><dc:creator><![CDATA[Swordfish]]></dc:creator><pubDate>Sat, 21 Feb 2015 17:33:30 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sun, 22 Feb 2015 01:57:56 GMT]]></title><description><![CDATA[<p>Bin natürlich dankbar für Verbesserungsvorschläge.</p>
<p>Nathan schrieb:</p>
<blockquote>
<p>Wieso new? Und dein read ist falsch. Du musst erst den String auf die Größe bringen und dann in den Zeichenspeicher lesen.</p>
</blockquote>
<p>Wieso new? Weil unwissend und C# Gewohnheit. Hatte den String noch nicht getestet und das war natürlich kompletter Blödsinn den ich da geschrieben habe, danke.</p>
<p>Swordfish schrieb:</p>
<blockquote>
<p>Vivida schrieb:</p>
<blockquote>
<pre><code>tag_type((TagType)12), // ...
</code></pre>
</blockquote>
<p>Schaut auch grausig aus. Ist <code>TagType</code> denn kein <code>enum</code> ??</p>
</blockquote>
<p>Ist schon ein Enum aber in der Dokumentation ist kein default/empty TagType vorgesehen daher hab ich einfach eine Zahl außerhalb des Umfanges angegeben um mögliche Fehler später abzufangen. Ich stimme dir zu, dass das grausam aussieht <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>
<pre><code>struct NbtNode {
	TagType tag_type;
	int16_t tag_name_length;
	std::string  tag_name;

	NbtNode(std::ifstream&amp; is) : tag_type(TagType::TAG_UNKNOWN), tag_name_length(0)
	{
		deserialize(is);
	}

	std::ifstream&amp; deserialize(std::ifstream&amp; is) {
		is.read((char*)&amp;tag_type, 1);

		is.read((char*)(&amp;tag_name_length+1), 1); //Big Endian
		is.read((char*)&amp;tag_name_length, 1);

		tag_name.resize(tag_name_length);
		is.read(&amp;tag_name[0], tag_name_length);
		return is;
	}

};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2443757</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443757</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Sun, 22 Feb 2015 01:57:56 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sun, 22 Feb 2015 10:18:04 GMT]]></title><description><![CDATA[<p>Vivida schrieb:</p>
<blockquote>
<pre><code>is.read((char*)(&amp;tag_name_length+1), 1); //Big Endian
</code></pre>
</blockquote>
<p>Das kann nicht funktionieren. Du übergibst die Adresse von <code>tag_name_length</code> + <strong>2</strong> (sizeof int16_t) und liest dann 1 Byte.<br />
Für Big/Little-Endian swapping google nach <code>ntohs()</code> .</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443770</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443770</guid><dc:creator><![CDATA[osdt]]></dc:creator><pubDate>Sun, 22 Feb 2015 10:18:04 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sun, 22 Feb 2015 10:29:14 GMT]]></title><description><![CDATA[<p>osdt schrieb:</p>
<blockquote>
<p>Vivida schrieb:</p>
<blockquote>
<pre><code>is.read((char*)(&amp;tag_name_length+1), 1); //Big Endian
</code></pre>
</blockquote>
<p>Das kann nicht funktionieren. Du übergibst die Adresse von <code>tag_name_length</code> + <strong>2</strong> (sizeof int16_t) und liest dann 1 Byte.<br />
Für Big/Little-Endian swapping google nach <code>ntohs()</code> .</p>
</blockquote>
<p>Das wollte ich gerade hinterfrage. Hat wohl für das ein Beispiel geklappt (bei dem nächsten nicht mehr). Benutze jetzt auch ntohs, htonll etc. Ich verstehe nur noch nicht ganz warum das nicht funktioniert.</p>
<p>Ich dachte<br />
&amp;tag_name_length = 0xAdresse von int16_t<br />
&amp;tag_name_length + 1 = 0xAdresse von int16_t + 1 =&gt; Zweiter Byte im int16_t</p>
<p>und ich somit aus<br />
Original: 02 01<br />
Gelesen: 01 02 (int16_t)<br />
mache.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443771</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443771</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Sun, 22 Feb 2015 10:29:14 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sun, 22 Feb 2015 10:37:52 GMT]]></title><description><![CDATA[<p>Das Stichwort ist Pointerarithmetik. Addierst du n zu einem Pointer erhöhst du ihn um n * sizeof(T), in diesem Fall 1 * sizeof(int16_t). Du müsstest also erst nach char* casten und dann um 1 erhöhen, denn sizeof(char) ist per Definition 1.<br />
Der portablerere Weg ist allerdings folgender:</p>
<pre><code>char bytes[2];
is.read(bytes, 2);
tag_name_length = (bytes[0] &lt;&lt; 8) | bytes[1];
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2443774</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443774</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Sun, 22 Feb 2015 10:37:52 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sun, 22 Feb 2015 11:06:15 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>Der <strong>portablerere</strong> Weg ist allerdings folgender:</p>
<pre><code>char bytes[2];
is.read(bytes, 2);
tag_name_length = (bytes[0] &lt;&lt; 8) | bytes[1];
</code></pre>
</blockquote>
<p><strong>Portabel</strong> in dem Sinne, dass es nur auf Little-Endian Systemen das gewünschte Ergebnis liefert. Auf Big-Endian Systemen wäre ein swap ehr kontraproduktiv.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443777</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443777</guid><dc:creator><![CDATA[osdt]]></dc:creator><pubDate>Sun, 22 Feb 2015 11:06:15 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sun, 22 Feb 2015 11:41:16 GMT]]></title><description><![CDATA[<p>osdt schrieb:</p>
<blockquote>
<p><strong>Portabel</strong> in dem Sinne, dass es nur auf Little-Endian Systemen das gewünschte Ergebnis liefert. Auf Big-Endian Systemen wäre ein swap ehr kontraproduktiv.</p>
</blockquote>
<p>Nein. Unabhängig davon ob man auf einem Little oder Big-Endian System ist: Das zuerst gelesene Byte wird nach links geshiftet und bildet somit die oberen Bits, das zweite dann die unteren. Bit-Operationen sind da absolut portabel.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443780</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443780</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Sun, 22 Feb 2015 11:41:16 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Sun, 22 Feb 2015 13:12:29 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>osdt schrieb:</p>
<blockquote>
<p><strong>Portabel</strong> in dem Sinne, dass es nur auf Little-Endian Systemen das gewünschte Ergebnis liefert. Auf Big-Endian Systemen wäre ein swap ehr kontraproduktiv.</p>
</blockquote>
<p>Nein. Unabhängig davon ob man auf einem Little oder Big-Endian System ist: Das zuerst gelesene Byte wird nach links geshiftet und bildet somit die oberen Bits, das zweite dann die unteren. Bit-Operationen sind da absolut portabel.</p>
</blockquote>
<p>Wow, hast Recht. Keine Ahnung weshalb ich an einen simplen Byte-Swap gedacht habe ... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2443794</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2443794</guid><dc:creator><![CDATA[osdt]]></dc:creator><pubDate>Sun, 22 Feb 2015 13:12:29 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Mon, 02 Mar 2015 17:51:30 GMT]]></title><description><![CDATA[<p>Ich hook mal meinen eigenen Thread um keinen neuen zu eröffnen:</p>
<p>Ich habe die komplette &quot;Deserialisation&quot; implementiert und alles funktioniert fantastisch. Danke nochmal an dieser Stelle <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Um von der Datei zu lesen habe ich bis jetzt immer ifstream benutzt. Die Datei muss aber vorher entpackt werden da sie komprimiert ist.<br />
Datei lesen -&gt; Dekomprimieren -&gt; In einen Puffer speichern</p>
<p>Jetzt möchte ich quasi die ganze &quot;Deserialisation&quot; auf dem Puffer anwenden und nicht mehr auf der Datei. Online stand dass es relativ einfach sei, von ifstream auf istringstream zu wechseln. Bin mir aber nicht sicher inwiefern sich istringstream dafür eignet da die Datei ja kein Textformat ist.</p>
<p>Die ersten beiden bytes des Puffers sind &quot;0A 00&quot;</p>
<pre><code>char* newbuffer = new char[newbuffersize];
...
std::istringstream iss(newbuffer);
</code></pre>
<p>Ich bin mir sicher dass dort bereits das Problem liegt. Jedoch möchte ich schon mal fragen ob es generell möglich ist, hier mit istringstream zu arbeiten?</p>
<pre><code>iss.read(test,1)
</code></pre>
<p>liefert immer nur test = 0A und schreitet nie voran.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444946</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444946</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Mon, 02 Mar 2015 17:51:30 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Mon, 02 Mar 2015 17:56:00 GMT]]></title><description><![CDATA[<p>Wenn du direkt char* nimmst, hört der String beim ersten Nullbyte auf.<br />
Nutz den Längenkonstruktor von std::string, bzw. direkt std::string oder std::vector&lt;char&gt; als Buffer.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444947</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444947</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Mon, 02 Mar 2015 17:56:00 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Mon, 02 Mar 2015 18:20:22 GMT]]></title><description><![CDATA[<pre><code>std::vector&lt;char&gt; newbuffer(newbuffersize);
inflate(origbuffer, filesize, &amp;newbuffer[0], newbuffersize);	
std::istringstream iss(&amp;newbuffer[0]);
</code></pre>
<p>scheint nichts verändert zu haben hmm</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444957</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444957</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Mon, 02 Mar 2015 18:20:22 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Mon, 02 Mar 2015 18:25:20 GMT]]></title><description><![CDATA[<pre><code>std::istringstream iss(std::string(newbuffer.begin(), newbuffer.end()));
</code></pre>
<p>Funktioniert dafür aber. Danke <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2444958</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444958</guid><dc:creator><![CDATA[Vivida]]></dc:creator><pubDate>Mon, 02 Mar 2015 18:25:20 GMT</pubDate></item><item><title><![CDATA[Reply to Eleganteste Lösung für Dynamischen String on Mon, 02 Mar 2015 18:39:17 GMT]]></title><description><![CDATA[<p>BTW: Falls du die Boost Libraries zur Verfügung hast, könntest du auch Boost.Iostreams verwenden um die zlib-Dekomprimierung zu machen:<br />
<a href="http://www.boost.org/doc/libs/1_57_0/libs/iostreams/doc/classes/zlib.html" rel="nofollow">http://www.boost.org/doc/libs/1_57_0/libs/iostreams/doc/classes/zlib.html</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444961</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444961</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 02 Mar 2015 18:39:17 GMT</pubDate></item></channel></rss>