<?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[Verkettete Objekte rekursiv ausgeben]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe ein kleines Testprojekt erstellt, das eine Xml Datei ausliest, und diese als verkettete Struktur speichert.</p>
<p>Ich weiß nicht, ob ich schon einen Fehler beim einlesen bzw. erstellen der verketteten Struktur gemacht habe, oder ob beim Ausgeben auf der Konsole etwas nicht stimmt.</p>
<p>Im Wesentlichen gehts um die Datei XmlReader.cpp, in welcher die beiden Methoden &quot;readElement&quot; und &quot;printNodes&quot; zu finden sind.</p>
<p>Zum Xml-lesen verwende ich TinyXML.</p>
<p>Wenn sich das bitte jemand ansehen könnte, es sind nicht viele Zeilen. Ich bekomme in der Methode &quot;printNodes&quot; nach einer gewissen Rekursionstiefe immer die Fehlermeldung: &quot;&lt;error reading variable: Cannot access memory at address 0x9&gt;&quot;</p>
<p>//EDIT:<br />
Hier die Source Files, da Download nicht gewünscht:</p>
<p>main.cpp</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &quot;XmlReader.h&quot;

int main(int argc, char *argv[])
{
	if(argc &lt; 2)
	{
		std::cout &lt;&lt; &quot;No xml file set!&quot; &lt;&lt; std::endl;
		return 1;
	}

	std::string file_name = argv[1];

	XmlReader reader(file_name);
	reader.parse();

	return 0;
}
</code></pre>
<p>XmlReader.h</p>
<pre><code class="language-cpp">#ifndef XMLREADER_H_
#define XMLREADER_H_

#include &lt;string&gt;

using namespace std;

class TiXmlNode;
class TiXmlElement;
class XmlNode;

class XmlReader
{
	public:
		XmlReader(const string&amp; fileName);
		virtual ~XmlReader();

		void parse();

	private:
		void readDocument(TiXmlNode* doc);
		void readElement(TiXmlNode* node, XmlNode* data);
		void readAttributes(TiXmlElement* element, XmlNode* data);

		void printNodes(XmlNode* node);

		string p_fileName;
		XmlNode* root;
};

#endif /* XMLREADER_H_ */
</code></pre>
<p>XmlReader.cpp</p>
<pre><code class="language-cpp">#include &quot;XmlReader.h&quot;

#include &lt;iostream&gt;
#include &lt;tinyxml.h&gt;

#include &quot;XmlNode.h&quot;

using namespace std;

XmlReader::XmlReader(const string&amp; fileName) :
	p_fileName(fileName)
{
	root = NULL;
}

void XmlReader::parse()
{
	TiXmlDocument doc(p_fileName);

	if (!doc.LoadFile())
	{
		cout &lt;&lt; &quot;Xml file cannot be loaded!&quot; &lt;&lt; endl;
		return;
	}

	readDocument(&amp;doc);

	printNodes(root);

	delete root;
}

void XmlReader::readDocument(TiXmlNode* doc)
{
	if (!doc)
		return;

	TiXmlNode* child;

	for (child = doc-&gt;FirstChild(); child != 0; child = child-&gt;NextSibling())
		readElement(child, root);
}

void XmlReader::readElement(TiXmlNode* node, XmlNode* data)
{
	if (!node)
		return;

	XmlNode* node_child = NULL;

	switch (node-&gt;Type())
	{
		case TiXmlNode::TINYXML_ELEMENT:
		{
			if (!data)
			{
				root = new XmlNode();
				root-&gt;setName(node-&gt;ValueStr());
				readAttributes(node-&gt;ToElement(), root);
			}
			else
			{
				node_child = new XmlNode();
				data-&gt;addChild(node_child);

				node_child-&gt;setName(node-&gt;ValueStr());
				readAttributes(node-&gt;ToElement(), node_child);
			}

			TiXmlNode* child;
			for (child = node-&gt;FirstChild(); child != 0; child = child-&gt;NextSibling())
			{
				if (node_child)
					readElement(child, node_child);
				else
					readElement(child, root);
			}

			break;
		}
		case TiXmlNode::TINYXML_TEXT:
		{
			TiXmlText *text = node-&gt;ToText();
			data-&gt;setValue(text-&gt;ValueStr());
			break;
		}
	}
}

void XmlReader::readAttributes(TiXmlElement* element, XmlNode* data)
{
	if (!element)
		return;

	TiXmlAttribute* attribute = element-&gt;FirstAttribute();
	while (attribute)
	{
		data-&gt;addAttribute(attribute-&gt;NameTStr(), attribute-&gt;ValueStr());
		attribute = attribute-&gt;Next();
	}
}

void XmlReader::printNodes(XmlNode* node)
{
	if (!node)
		return;

	cout &lt;&lt; node-&gt;getName() &lt;&lt; &quot; --&gt; &quot; &lt;&lt; node-&gt;getValue() &lt;&lt; endl;

	if (node-&gt;getChildren().size() &gt; 0)
	{
		list&lt;XmlNode*&gt;::iterator it = node-&gt;getChildren().begin();

		while (it != node-&gt;getChildren().end())
		{
			printNodes((*it));
			it++;
		}
	}
	else
		return;
}

XmlReader::~XmlReader()
{
	delete root;
}
</code></pre>
<p>XmlNode.h</p>
<pre><code class="language-cpp">#ifndef XMLNODE_H_
#define XMLNODE_H_

#include &lt;string&gt;
#include &lt;map&gt;
#include &lt;list&gt;

using namespace std;

class XmlNode
{
	public:
		XmlNode();
		virtual ~XmlNode();

		void setName(const string &amp;name);
		string getName() const { return pName; }

		void setValue(const string &amp;value);
		string getValue() const { return pValue; }

		void addChild(XmlNode* child);
		void setChildren(const list&lt;XmlNode*&gt;&amp; children);
		list&lt;XmlNode*&gt; getChildren() const { return pChildren; }

		void addAttribute(const string &amp;key, const string &amp;value);
		void setAttributes(const map&lt;string, string&gt;&amp; attributes);
		map&lt;string, string&gt; getAttributes() const { return pAttributes; }

	private:
		string pName;
		string pValue;
		list&lt;XmlNode*&gt; pChildren;
		map&lt;string, string&gt; pAttributes;
};

#endif /* XMLNODE_H_ */
</code></pre>
<p>XmlNode.cpp</p>
<pre><code class="language-cpp">#include &quot;XmlNode.h&quot;

XmlNode::XmlNode()
{

}

XmlNode::~XmlNode()
{
	pChildren.clear();
	pAttributes.clear();
}

void XmlNode::setChildren(const list&lt;XmlNode*&gt; &amp; children)
{
	pChildren = children;
}

void XmlNode::addAttribute(const string &amp; key, const string &amp; value)
{
	if(pAttributes.count(key) == 0)
		pAttributes[key] = value;
}

void XmlNode::setValue(const string &amp; value)
{
	pValue = value;
}

void XmlNode::setAttributes(const map&lt;string,string&gt; &amp; attributes)
{
	pAttributes = attributes;
}

void XmlNode::addChild(XmlNode *child)
{
	pChildren.push_back(child);
}

void XmlNode::setName(const string &amp; name)
{
	pName = name;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/305992/verkettete-objekte-rekursiv-ausgeben</link><generator>RSS for Node</generator><lastBuildDate>Sat, 08 Aug 2026 12:07:23 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/305992.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 14 Jul 2012 13:58:08 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Verkettete Objekte rekursiv ausgeben on Sat, 14 Jul 2012 14:22:10 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe ein kleines Testprojekt erstellt, das eine Xml Datei ausliest, und diese als verkettete Struktur speichert.</p>
<p>Ich weiß nicht, ob ich schon einen Fehler beim einlesen bzw. erstellen der verketteten Struktur gemacht habe, oder ob beim Ausgeben auf der Konsole etwas nicht stimmt.</p>
<p>Im Wesentlichen gehts um die Datei XmlReader.cpp, in welcher die beiden Methoden &quot;readElement&quot; und &quot;printNodes&quot; zu finden sind.</p>
<p>Zum Xml-lesen verwende ich TinyXML.</p>
<p>Wenn sich das bitte jemand ansehen könnte, es sind nicht viele Zeilen. Ich bekomme in der Methode &quot;printNodes&quot; nach einer gewissen Rekursionstiefe immer die Fehlermeldung: &quot;&lt;error reading variable: Cannot access memory at address 0x9&gt;&quot;</p>
<p>//EDIT:<br />
Hier die Source Files, da Download nicht gewünscht:</p>
<p>main.cpp</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &quot;XmlReader.h&quot;

int main(int argc, char *argv[])
{
	if(argc &lt; 2)
	{
		std::cout &lt;&lt; &quot;No xml file set!&quot; &lt;&lt; std::endl;
		return 1;
	}

	std::string file_name = argv[1];

	XmlReader reader(file_name);
	reader.parse();

	return 0;
}
</code></pre>
<p>XmlReader.h</p>
<pre><code class="language-cpp">#ifndef XMLREADER_H_
#define XMLREADER_H_

#include &lt;string&gt;

using namespace std;

class TiXmlNode;
class TiXmlElement;
class XmlNode;

class XmlReader
{
	public:
		XmlReader(const string&amp; fileName);
		virtual ~XmlReader();

		void parse();

	private:
		void readDocument(TiXmlNode* doc);
		void readElement(TiXmlNode* node, XmlNode* data);
		void readAttributes(TiXmlElement* element, XmlNode* data);

		void printNodes(XmlNode* node);

		string p_fileName;
		XmlNode* root;
};

#endif /* XMLREADER_H_ */
</code></pre>
<p>XmlReader.cpp</p>
<pre><code class="language-cpp">#include &quot;XmlReader.h&quot;

#include &lt;iostream&gt;
#include &lt;tinyxml.h&gt;

#include &quot;XmlNode.h&quot;

using namespace std;

XmlReader::XmlReader(const string&amp; fileName) :
	p_fileName(fileName)
{
	root = NULL;
}

void XmlReader::parse()
{
	TiXmlDocument doc(p_fileName);

	if (!doc.LoadFile())
	{
		cout &lt;&lt; &quot;Xml file cannot be loaded!&quot; &lt;&lt; endl;
		return;
	}

	readDocument(&amp;doc);

	printNodes(root);

	delete root;
}

void XmlReader::readDocument(TiXmlNode* doc)
{
	if (!doc)
		return;

	TiXmlNode* child;

	for (child = doc-&gt;FirstChild(); child != 0; child = child-&gt;NextSibling())
		readElement(child, root);
}

void XmlReader::readElement(TiXmlNode* node, XmlNode* data)
{
	if (!node)
		return;

	XmlNode* node_child = NULL;

	switch (node-&gt;Type())
	{
		case TiXmlNode::TINYXML_ELEMENT:
		{
			if (!data)
			{
				root = new XmlNode();
				root-&gt;setName(node-&gt;ValueStr());
				readAttributes(node-&gt;ToElement(), root);
			}
			else
			{
				node_child = new XmlNode();
				data-&gt;addChild(node_child);

				node_child-&gt;setName(node-&gt;ValueStr());
				readAttributes(node-&gt;ToElement(), node_child);
			}

			TiXmlNode* child;
			for (child = node-&gt;FirstChild(); child != 0; child = child-&gt;NextSibling())
			{
				if (node_child)
					readElement(child, node_child);
				else
					readElement(child, root);
			}

			break;
		}
		case TiXmlNode::TINYXML_TEXT:
		{
			TiXmlText *text = node-&gt;ToText();
			data-&gt;setValue(text-&gt;ValueStr());
			break;
		}
	}
}

void XmlReader::readAttributes(TiXmlElement* element, XmlNode* data)
{
	if (!element)
		return;

	TiXmlAttribute* attribute = element-&gt;FirstAttribute();
	while (attribute)
	{
		data-&gt;addAttribute(attribute-&gt;NameTStr(), attribute-&gt;ValueStr());
		attribute = attribute-&gt;Next();
	}
}

void XmlReader::printNodes(XmlNode* node)
{
	if (!node)
		return;

	cout &lt;&lt; node-&gt;getName() &lt;&lt; &quot; --&gt; &quot; &lt;&lt; node-&gt;getValue() &lt;&lt; endl;

	if (node-&gt;getChildren().size() &gt; 0)
	{
		list&lt;XmlNode*&gt;::iterator it = node-&gt;getChildren().begin();

		while (it != node-&gt;getChildren().end())
		{
			printNodes((*it));
			it++;
		}
	}
	else
		return;
}

XmlReader::~XmlReader()
{
	delete root;
}
</code></pre>
<p>XmlNode.h</p>
<pre><code class="language-cpp">#ifndef XMLNODE_H_
#define XMLNODE_H_

#include &lt;string&gt;
#include &lt;map&gt;
#include &lt;list&gt;

using namespace std;

class XmlNode
{
	public:
		XmlNode();
		virtual ~XmlNode();

		void setName(const string &amp;name);
		string getName() const { return pName; }

		void setValue(const string &amp;value);
		string getValue() const { return pValue; }

		void addChild(XmlNode* child);
		void setChildren(const list&lt;XmlNode*&gt;&amp; children);
		list&lt;XmlNode*&gt; getChildren() const { return pChildren; }

		void addAttribute(const string &amp;key, const string &amp;value);
		void setAttributes(const map&lt;string, string&gt;&amp; attributes);
		map&lt;string, string&gt; getAttributes() const { return pAttributes; }

	private:
		string pName;
		string pValue;
		list&lt;XmlNode*&gt; pChildren;
		map&lt;string, string&gt; pAttributes;
};

#endif /* XMLNODE_H_ */
</code></pre>
<p>XmlNode.cpp</p>
<pre><code class="language-cpp">#include &quot;XmlNode.h&quot;

XmlNode::XmlNode()
{

}

XmlNode::~XmlNode()
{
	pChildren.clear();
	pAttributes.clear();
}

void XmlNode::setChildren(const list&lt;XmlNode*&gt; &amp; children)
{
	pChildren = children;
}

void XmlNode::addAttribute(const string &amp; key, const string &amp; value)
{
	if(pAttributes.count(key) == 0)
		pAttributes[key] = value;
}

void XmlNode::setValue(const string &amp; value)
{
	pValue = value;
}

void XmlNode::setAttributes(const map&lt;string,string&gt; &amp; attributes)
{
	pAttributes = attributes;
}

void XmlNode::addChild(XmlNode *child)
{
	pChildren.push_back(child);
}

void XmlNode::setName(const string &amp; name)
{
	pName = name;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2232736</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2232736</guid><dc:creator><![CDATA[HerbertB]]></dc:creator><pubDate>Sat, 14 Jul 2012 14:22:10 GMT</pubDate></item><item><title><![CDATA[Reply to Verkettete Objekte rekursiv ausgeben on Sat, 14 Jul 2012 14:16:46 GMT]]></title><description><![CDATA[<p>HerbertB schrieb:</p>
<blockquote>
<p>Das programm befindet sich im Anhang.</p>
</blockquote>
<p>Nein...</p>
<p>edit: sachen runterladen kommt hier im forum ganz schlecht an. poste den entsprechenden source code hier...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2232742</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2232742</guid><dc:creator><![CDATA[Skym0sh0]]></dc:creator><pubDate>Sat, 14 Jul 2012 14:16:46 GMT</pubDate></item><item><title><![CDATA[Reply to Verkettete Objekte rekursiv ausgeben on Sat, 14 Jul 2012 17:42:45 GMT]]></title><description><![CDATA[<p>Hallo Herbert,</p>
<p>in der Datei XmlNode.h Zeile 24 gibst Du <code>std::list&lt;XmlNode*&gt;</code> per Value zurück. D.h. in der Funktion <code>XmlReader::printNodes</code> Datei XmlReader.cpp Zeile 112 wird eine Kopie der Liste auf den Stack gelegt, dort der Iterator auf begin abgeholt und mit Verlassen der Zeile 112 ist die Liste gelöscht und 'it' ist ein Iterator auf einen Container, der nicht mehr da ist. Alles weitere mündet in undefiniertem Verhalten.<br />
Ein schneller Fix in XmlReader.cpp wäre</p>
<pre><code class="language-cpp">void XmlReader::printNodes(XmlNode* node)
{
    if (!node)
        return;

    cout &lt;&lt; node-&gt;getName() &lt;&lt; &quot; --&gt; &quot; &lt;&lt; node-&gt;getValue() &lt;&lt; endl;

    list&lt;XmlNode*&gt; childs = node-&gt;getChildren(); // Kopie anlegen und nur auf der Kopie arbeiten
    for( list&lt;XmlNode*&gt;::iterator iNode = childs.begin(); iNode != childs.end(); ++iNode )
        printNodes(*iNode);
}
</code></pre>
<p>Weiter gehst Du sehr großzügig mit dem Member <code>XmlReader::root</code> um. Füge mindestens in der Methode <code>XmlReader::parse</code> hinter dem <code>delete root</code> in Zeile 30 ein <code>root=0;</code> ein, sonst stürzt das Programm im Destruktor in Zeile 126 ab. Aber ich würde Dir wärmstens einen Smartpointer (z.B.: <a href="http://en.cppreference.com/w/cpp/memory/unique_ptr" rel="nofollow">std::uniqe_ptr</a>) empfehlen.</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2232811</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2232811</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Sat, 14 Jul 2012 17:42:45 GMT</pubDate></item><item><title><![CDATA[Reply to Verkettete Objekte rekursiv ausgeben on Sun, 15 Jul 2012 17:55:18 GMT]]></title><description><![CDATA[<p>Vielen dank für die hilfe, ich werde das mit den smart-pointer auch umsetzen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2233012</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2233012</guid><dc:creator><![CDATA[HerbertB]]></dc:creator><pubDate>Sun, 15 Jul 2012 17:55:18 GMT</pubDate></item></channel></rss>