<?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[Element aus verschachtelter Datenstruktur löschen.]]></title><description><![CDATA[<p>Hallo zusammen!</p>
<p>Ich will bestimmte Anwendungseinstellungen in einer Struktur speichern. Dabei soll es möglich sein, verschiedene Kategorien zu verwenden. Jede einzelne Einstellung beseht dabei aus einem Pair, wobei der Schlüssel vom Typ std::string ist und der Wert vom Typ boost::any ist. Mein Versuch sieht also folgendermaßen aus:</p>
<pre><code class="language-cpp">struct node 
{
	void append(const std::string&amp; rhs, const boost::any&amp; lhs)
	{
		content.insert(std::make_pair(rhs, lhs));
	}
	std::map&lt;std::string, boost::any&gt; content;
};
</code></pre>
<p>Jetzt will ich aber Extrafunktionen haben, die z.B. das Zugreifen oder das Löschen von Einstellungen vereinfachen. Um dabei den Pfad zu einer bestimmten Einstellung anzugeben, habe ich mir überlegt, ein Objekt AccessObject zu haben, dass lediglich dazu verwendet wird, den Pfad in einem Ausdruck angeben zu können:</p>
<pre><code class="language-cpp">class AccessObject
{
private:
	std::vector&lt;std::string&gt; path;

public:
	AccessObject&amp; append(const std::string&amp; rhs)
	{
		path.push_back(rhs);
	}

	std::vector&lt;std::string&gt; get()
	{
		return path;
	}
};
</code></pre>
<p>Man kann jetzt also einfach:</p>
<pre><code class="language-cpp">AccessObject().append(&quot;parent&quot;).append(&quot;child1&quot;).append(&quot;child2&quot;).append(&quot;name&quot;).get()
</code></pre>
<p>schreiben und erhält dadurch eine Liste der einzelnen Pfadelemente.<br />
Für den Zugriff auf ein Objekt will ich nun schreiben können:</p>
<pre><code class="language-cpp">access&lt;std::string&gt;(root, AccessObject(&quot;child1&quot;).append(&quot;child2&quot;).append(&quot;name&quot;).get());
</code></pre>
<p>Daher habe ich die Funktion folgendermaßen implementiert:</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
T access(const node&amp; root, const std::vector&lt;std::string&gt;&amp; path)
{
	node current = root;
	for(int i=0; i&lt;path.size(); ++i)
	{
		try
		{
			current = boost::any_cast&lt;node&gt;(current.content[path[i&rsqb;&rsqb;);
		}
		catch(std::exception&amp; e)
		{
			return boost::any_cast&lt;T&gt;(current.content[path[i&rsqb;&rsqb;);
		}
	}
	return T();
}
</code></pre>
<p>Das funktioniert so auch ganz wunderbar.<br />
Was mir jetzt allerdings Schwirigkeiten bereitet, ist die Funktion zum Löschen einer bestimmten Einstellung. Mein Versuch dazu sieht so aus:</p>
<pre><code class="language-cpp">void remove(node&amp; root, const std::vector&lt;std::string&gt;&amp; path)
{
	node&amp; current = root;
	for(int i=0; i&lt;path.size()-1; ++i)
	{
		current = boost::any_cast&lt;node&amp;&gt;(current.content[path[i&rsqb;&rsqb;); 
                // Wenn das letzte Element des nächste ist, dann lösche dieses nächste. 
		if(path[path.size()] == path[i+1])
			current.content.erase(current.content.find(path[i+1]));
	}
}
</code></pre>
<p>Das aber gibt mir einen Speicherzugriffsfehler <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f621.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--pouting_face"
      title=":rage:"
      alt="😡"
    />. Ich sitze nun schon einen halben Tag daran, und versuche nur, diese verdammte remove()-Funktion zu schreiben, scheitere aber jedesmal kläglich.</p>
<p>Danke für die Hilfe,</p>
<p>Niels</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/245308/element-aus-verschachtelter-datenstruktur-löschen</link><generator>RSS for Node</generator><lastBuildDate>Fri, 18 Sep 2026 17:32:11 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/245308.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 12 Jul 2009 16:04:54 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Sun, 12 Jul 2009 19:14:02 GMT]]></title><description><![CDATA[<p>Hallo zusammen!</p>
<p>Ich will bestimmte Anwendungseinstellungen in einer Struktur speichern. Dabei soll es möglich sein, verschiedene Kategorien zu verwenden. Jede einzelne Einstellung beseht dabei aus einem Pair, wobei der Schlüssel vom Typ std::string ist und der Wert vom Typ boost::any ist. Mein Versuch sieht also folgendermaßen aus:</p>
<pre><code class="language-cpp">struct node 
{
	void append(const std::string&amp; rhs, const boost::any&amp; lhs)
	{
		content.insert(std::make_pair(rhs, lhs));
	}
	std::map&lt;std::string, boost::any&gt; content;
};
</code></pre>
<p>Jetzt will ich aber Extrafunktionen haben, die z.B. das Zugreifen oder das Löschen von Einstellungen vereinfachen. Um dabei den Pfad zu einer bestimmten Einstellung anzugeben, habe ich mir überlegt, ein Objekt AccessObject zu haben, dass lediglich dazu verwendet wird, den Pfad in einem Ausdruck angeben zu können:</p>
<pre><code class="language-cpp">class AccessObject
{
private:
	std::vector&lt;std::string&gt; path;

public:
	AccessObject&amp; append(const std::string&amp; rhs)
	{
		path.push_back(rhs);
	}

	std::vector&lt;std::string&gt; get()
	{
		return path;
	}
};
</code></pre>
<p>Man kann jetzt also einfach:</p>
<pre><code class="language-cpp">AccessObject().append(&quot;parent&quot;).append(&quot;child1&quot;).append(&quot;child2&quot;).append(&quot;name&quot;).get()
</code></pre>
<p>schreiben und erhält dadurch eine Liste der einzelnen Pfadelemente.<br />
Für den Zugriff auf ein Objekt will ich nun schreiben können:</p>
<pre><code class="language-cpp">access&lt;std::string&gt;(root, AccessObject(&quot;child1&quot;).append(&quot;child2&quot;).append(&quot;name&quot;).get());
</code></pre>
<p>Daher habe ich die Funktion folgendermaßen implementiert:</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
T access(const node&amp; root, const std::vector&lt;std::string&gt;&amp; path)
{
	node current = root;
	for(int i=0; i&lt;path.size(); ++i)
	{
		try
		{
			current = boost::any_cast&lt;node&gt;(current.content[path[i&rsqb;&rsqb;);
		}
		catch(std::exception&amp; e)
		{
			return boost::any_cast&lt;T&gt;(current.content[path[i&rsqb;&rsqb;);
		}
	}
	return T();
}
</code></pre>
<p>Das funktioniert so auch ganz wunderbar.<br />
Was mir jetzt allerdings Schwirigkeiten bereitet, ist die Funktion zum Löschen einer bestimmten Einstellung. Mein Versuch dazu sieht so aus:</p>
<pre><code class="language-cpp">void remove(node&amp; root, const std::vector&lt;std::string&gt;&amp; path)
{
	node&amp; current = root;
	for(int i=0; i&lt;path.size()-1; ++i)
	{
		current = boost::any_cast&lt;node&amp;&gt;(current.content[path[i&rsqb;&rsqb;); 
                // Wenn das letzte Element des nächste ist, dann lösche dieses nächste. 
		if(path[path.size()] == path[i+1])
			current.content.erase(current.content.find(path[i+1]));
	}
}
</code></pre>
<p>Das aber gibt mir einen Speicherzugriffsfehler <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f621.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--pouting_face"
      title=":rage:"
      alt="😡"
    />. Ich sitze nun schon einen halben Tag daran, und versuche nur, diese verdammte remove()-Funktion zu schreiben, scheitere aber jedesmal kläglich.</p>
<p>Danke für die Hilfe,</p>
<p>Niels</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1741551</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1741551</guid><dc:creator><![CDATA[nielsp]]></dc:creator><pubDate>Sun, 12 Jul 2009 19:14:02 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Sun, 12 Jul 2009 19:13:10 GMT]]></title><description><![CDATA[<p>Weiß wirklich niemand irgendetwas?<br />
<img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1741677</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1741677</guid><dc:creator><![CDATA[nielsp]]></dc:creator><pubDate>Sun, 12 Jul 2009 19:13:10 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Sun, 12 Jul 2009 19:58:27 GMT]]></title><description><![CDATA[<p>Habe grad nicht viel Zeit, aber nur so schnell auf die Schnelle:</p>
<pre><code class="language-cpp">current = boost::any_cast&lt;node&amp;&gt;(current.content[path[i&rsqb;&rsqb;);
</code></pre>
<p>Kommt mir verdächtig vor. Sollte das nicht <code>boost::any_cast&lt;node&gt;</code> heissen?</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1741693</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1741693</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Sun, 12 Jul 2009 19:58:27 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Tue, 14 Jul 2009 17:44:18 GMT]]></title><description><![CDATA[<p>Endlich kam mir der Geistesblitz. Dazu habe ich allerdings jedem Knoten einen Zeiger auf sein Elternknoten hinzugefügt.</p>
<pre><code class="language-cpp">void remove(node&amp; root, const std::vector&lt;std::string&gt;&amp; path)
{
	node current = root;
	for(unsigned int i=0; i&lt;path.size(); ++i)
	{
		try
		{
			current = boost::any_cast&lt;node&gt;(current.content.find(path[i])-&gt;second);
		}
		catch(boost::bad_any_cast&amp; e)
		{
			std::cout &lt;&lt; e.what() &lt;&lt; std::endl;
		}

		if(i == path.size()-2)
		{
			for(std::map&lt;std::string, boost::any&gt;::iterator iter = current.content.begin(); iter != current.content.end(); ++iter)
				if(iter-&gt;first == path[i+1])
					current.content.erase(current.content.find(path[i+1]));

			for(int j=i; j&gt;=0; --j)
			{
				(*current.parent).content[path[j&rsqb;&rsqb; = current;
				current = *current.parent;
				if(!current.parent)
				{
					root = current;
					return;
				}
			}
			return;
		}
	}
}
</code></pre>
<p>Allerdings kommt mir das immer noch seltsam kompliziert vor für eine eigentlich doch triviale Angelegenheit. Ich wäre wirklich sehr erfreut, wenn einer, der sich etwas besser mit C++ auskennt als ich, sich das angucken könnte.</p>
<p>Vielen Dank!</p>
<p>Niels.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1742989</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1742989</guid><dc:creator><![CDATA[nielsp]]></dc:creator><pubDate>Tue, 14 Jul 2009 17:44:18 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Tue, 14 Jul 2009 21:51:03 GMT]]></title><description><![CDATA[<p>Ich hoffe mal, ich habe dein Problem richtig verstanden, und hier mein lösungsansatz:</p>
<pre><code>void remove(node&amp; root, const std::vector&lt;std::string&gt;&amp; path)
{

    node* current = &amp;root;  // man beachte das &quot;&amp;&quot;
    unsigned int i=0;
    for(i=0; i&lt;path.size()-1; ++i)
    {
        try
        {
            current = &amp;boost::any_cast&lt;node&gt;(current-&gt;content.find(path[i])-&gt;second);
        }
        catch(boost::bad_any_cast&amp; e)
        {
            std::cout &lt;&lt; e.what() &lt;&lt; std::endl;
        }

    }
    current-&gt;content.erase( path[i] ); // i== path.size()-1, also das letzte element in path
}
</code></pre>
<p>was ich in deinem Code noch nicht so ganz verstehe ist, wieso du über die Elemente iterierst wenn i==path.size()-2 ist.<br />
Bzw. ich verstehs schon, weil du wohl sicherstellen willst, ob es den key path[path.size()-1] überhaupt gibt, was viel schneller getan wäre mit</p>
<pre><code>if ( current.content.find(path[i+1]) != current.content.end() )
</code></pre>
<p>Aber noch eleganter ist die variante oben, indem man einfach erase mit dem pfad aufruft, und erase löscht einfach nix, wenns das nicht gibt. Wenn dich auch noch interessiert, ob es das gegeben hat, dann liefert die erase funktion 1 zurück, wenn das element gefunden wurde, ansonsten 0 (aber lies dazu einfach mal bei einer beliebigen C++ referenz nach).</p>
<p>Was ich hauptsächlich geändert habe: current ist nicht vom Typen node, sondern vom Typen node*, d.h. du kopierst nicht blöd deine gesamten maps unnötig, und was du an current veränderst, veränderst du natürlich automatisch an der gesamten struktur...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743109</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743109</guid><dc:creator><![CDATA[Jocker16]]></dc:creator><pubDate>Tue, 14 Jul 2009 21:51:03 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Wed, 15 Jul 2009 11:54:32 GMT]]></title><description><![CDATA[<p>Danke für die Antwort!</p>
<p>Dein Lösungsvorschlag scheint ja recht ähnlich mit meinem ersten. So gibt nämlich sowohl deine als auch meine Implementierung einen Speicherzugriffsfehler. Ich glaube, das Problem liegt in der folgenden Anweisung:</p>
<pre><code class="language-cpp">current = &amp;boost::any_cast&lt;node&gt;(current-&gt;content.find(path[i])-&gt;second);
</code></pre>
<p>Dadurch wird ja <code>root</code> auf <code>current</code> begrenzt, alle Elemente aus dem Baum davor gehen aber verloren. Ansonsten danke auch für den Hinweis für Erase. Jetzt sieht das ganze schon ein wenig weniger kompliziert aus :p</p>
<p>Niels.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743440</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743440</guid><dc:creator><![CDATA[nielsp]]></dc:creator><pubDate>Wed, 15 Jul 2009 11:54:32 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Wed, 15 Jul 2009 14:53:49 GMT]]></title><description><![CDATA[<p>Du glaubst, das problem liegt dort????<br />
Dann probiers doch aus, und sag genau, bei welcher zeile es abstürzt...<br />
Füge ein paar std::cout &lt;&lt; __FILE__ &lt;&lt; __LINE__ &lt;&lt; std::endl in deine remove Funktion und sag, wann es genau abstürzt. Bei welchem i und bei welcher zeile...</p>
<p>Und nein, wir haben vermutlich nicht den gleichen Fehler, denn du hattest in deiner ersten variante sowas wie: path[path.size()], was eigentlich zu einem absturz führen sollte, da es nur path[path.size()-1] gibt, aber kein nächstes element mehr.</p>
<p>Du veränderst root eigentlich nicht, sondern du veränderst worauf die Variable current zeigt. Am Anfang zeigt sie auf root, und in der for-schleife ändert sich ständig worauf current gerade zeigt. Aber damit veränderst du nicht, die Variable root selbst.<br />
Aber so wie du es am Anfang hattest hast du recht, du veränderst nämlich root selbst, da eine Referenz nur am anfang initialisiert werden kann. Danach sind alles zuweisungen, d.h. du veränderst ständig die root variable. Aber einen Pointer kannst du ständig neu &quot;initialisieren&quot;.<br />
hier vielleicht nochmal zum verständnis der unterschied:</p>
<pre><code>int a=1;
int &amp;b=a;
int c=2;
b=c;  // --&gt; a bekommt automatisch den 2, da b und a den selben speicherbereich referenzieren, diese zeile heißt nicht, dass b und c jetzt den selben speicherbereich referenzieren...
</code></pre>
<pre><code>int a=1;
int *b=&amp;a;
int c=1;
b=&amp;c;
*b=2;  // hier hat jetzt c den wert 2 bekommen, weil b auf den speicherbereich von c zeigt, aber a ist unverändert und hat noch immer den wert 1
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1743595</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743595</guid><dc:creator><![CDATA[Jocker16]]></dc:creator><pubDate>Wed, 15 Jul 2009 14:53:49 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Wed, 15 Jul 2009 20:43:12 GMT]]></title><description><![CDATA[<p>Ich glaube, verstanden zu haben, warum deine Implementierung fehlschlägt. Mit</p>
<pre><code class="language-cpp">&amp;boost::any_cast&lt;node&gt;(current-&gt;content.find(path[i])-&gt;second);
</code></pre>
<p>verweist du nämlich auf eine temporäre Variable (das kam eigentlich schon in den Compilerwarnungen: <code>warning: taking address of temporary</code> <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="🙄"
    />). Der Speicherzugriffsfehler kommt nämlich auch genau bei dieser Anweisung. Und nach Node* casten geht natürlich auch nicht, schließlich ist ja Node* nicht dasselbe wie Node (boost::bad_any_cast). Leider scheine ich nicht klug genug zu sein, herauszufinden, wie ich trotzdem auf <code>current-&gt;content.find(path[i])-&gt;second</code> richtig verweise. Ich hatte davor probiert: <code>&amp;(current-&gt;content.find(path[i])-&gt;second)</code> , aber dann kommt: <code>cannot convert node** to node* in assignment.</code></p>
<p>Ich wäre Für Hilfe sehr dankbar!</p>
<p>Niels</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743751</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743751</guid><dc:creator><![CDATA[nielsp]]></dc:creator><pubDate>Wed, 15 Jul 2009 20:43:12 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Wed, 15 Jul 2009 19:15:27 GMT]]></title><description><![CDATA[<pre><code>boost::any_cast&lt;node*&gt;( &amp;(current-&gt;content.find(path[i])-&gt;second) );
</code></pre>
<p>klappt das?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743754</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743754</guid><dc:creator><![CDATA[Jocker16]]></dc:creator><pubDate>Wed, 15 Jul 2009 19:15:27 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Wed, 15 Jul 2009 20:40:37 GMT]]></title><description><![CDATA[<p>Nein, eben das klappt nicht. Genau das wollte ich eigentlich mit dem vorhergehenden Post sagen (war wohl ein wenig unglücklich formuliert). Es kommt:<br />
<code>cannot convert 'node**' to 'node*' in assignment</code></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743796</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743796</guid><dc:creator><![CDATA[nielsp]]></dc:creator><pubDate>Wed, 15 Jul 2009 20:40:37 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Wed, 15 Jul 2009 20:54:23 GMT]]></title><description><![CDATA[<p>ok, wenn man die Doku von any_cast sich anguckt, dann ist hier die entscheidende Zeile:<br />
template&lt;typename ValueType&gt; ValueType * any_cast(any * operand);</p>
<p>damit ist klar, dass es lauten muss:</p>
<pre><code>boost::any_cast&lt;node&gt;( &amp;(current-&gt;content.find(path[i])-&gt;second) );
</code></pre>
<p>Sieht komisch aus (da man zunächst erwartet, dass eine node rauskommt, und nicht node*), aber es sollte funktionieren.</p>
<p>Die Access funktion würde ich auch auf pointer umstellen, da du ansonsten immer alles kopierst bei der zuweisung</p>
<pre><code>current = boost::any_cast.....
</code></pre>
<p>was bei einer tiefen Hierarchie schnell mal langsam werden kann.</p>
<p>So, ich hoffe, damit ist dir jetzt geholfen, und die lösch funktion geht so wie du es brauchst...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743805</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743805</guid><dc:creator><![CDATA[Jocker16]]></dc:creator><pubDate>Wed, 15 Jul 2009 20:54:23 GMT</pubDate></item><item><title><![CDATA[Reply to Element aus verschachtelter Datenstruktur löschen. on Wed, 15 Jul 2009 21:29:12 GMT]]></title><description><![CDATA[<p>Danke Jocker16! Jetzt haben sich alle Probleme in Luft aufgelöst.</p>
<p>Niels</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743817</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743817</guid><dc:creator><![CDATA[nielsp]]></dc:creator><pubDate>Wed, 15 Jul 2009 21:29:12 GMT</pubDate></item></channel></rss>