rapidxml: Probleme beim Speichern



  • Hallo Community,

    ich arbeite gerade in eine Speicherung von Schachnotationen. Um mehr Informationen speichern zu können,habe ich beschlossen nicht das Format PGN zu nutzen.

    FileReader.hpp

    #ifndef _FILEREADER_HPP
    #define _FILE_READER_HPP
    
    #include<fstream>
    #include"rapidxml.hpp"
    #include"Notation.h"
    
    namespace pgnx
    {
    	class FileWriter
    	{
    		std::map<unsigned int, Tournament> data;
    		std::ofstream file;
    		std::string fn;
    		rapidxml::xml_document<> doc;
    	protected:
    		void save();
    	public:
    		FileWriter(char* filename);
    		FileWriter();
    		~FileWriter(){}
    		void prepare();
    		void insertTournament(Tournament);
    		//Operators
    		FileWriter& operator+(Tournament rhs);
    		FileWriter& operator=(std::map<unsigned int, Tournament> rhs);
    		FileWriter& operator=(pgnx::FileWriter rhs);
    		Tournament& operator[](unsigned int index);
    	};
    }
    
    #endif
    

    FileReader.cpp (in Auszügen)

    void FileWriter::prepare()
    {
    	using namespace rapidxml;
    	xml_node<>* decl = doc.allocate_node(node_declaration);
    	decl->append_attribute(doc.allocate_attribute("version", "1.0"));
    	decl->append_attribute(doc.allocate_attribute("encoding", "utf-8"));
    	doc.append_node(decl);
    
    	xml_node<>* pgnx = doc.allocate_node(node_element, "pgnx");
    	pgnx->append_attribute(doc.allocate_attribute("version", _VERSION_));
    	doc.append_node(pgnx);
    
    	for (unsigned int i = 0; i < this->data.rbegin()->first + 1; i++)
    	{
    		xml_node<>* child = doc.allocate_node(node_element, "Tournament");
    		child->append_attribute(doc.allocate_attribute("ID", (const char*)i));
    		child->append_attribute(doc.allocate_attribute("Name", me[i].getName()));
    		for (unsigned int j = 0; j < me[i].getLength(); j++)
    		{
    			xml_node<>* game = doc.allocate_node(node_element, "Game");
    			game->append_attribute(doc.allocate_attribute("White", (me[i])[j].getNameW()));
    			game->append_attribute(doc.allocate_attribute("Black", (me[i])[j].getNameB()));
    			game->append_attribute(doc.allocate_attribute("Result", (const char*)(me[i])[j].getResult()));
    			for (unsigned int k = 0; k < (me[i])[j].getLength(); k++)
    			{
    				xml_node<>* move = doc.allocate_node(node_element, "move");
    				move->append_attribute(doc.allocate_attribute("Number", (const char*)k));
    				move->append_attribute(doc.allocate_attribute("White", ((me[i])[j])[k].getMoveW()));
    				move->append_attribute(doc.allocate_attribute("White", ((me[i])[j])[k].getMoveB()));
    				game->append_node(move);
    			}
    			child->append_node(game);
    		}
    		pgnx->append_node(child);
    	}
    
    	this->file.open(fn.c_str());
    
    	this->save();
    
    	file.close();
    	doc.clear();
    }
    
    void FileWriter::insertTournament(Tournament x)
    {
    	if (this->data.empty())
    		this->data[0] = x;
    	else
    		this->data[this->data.rbegin()->first + 1] = x;
    }
    
    void FileWriter::save()
    {
    	file << this->doc.value();
    	file.close();
    }
    

    Ich habe schon file << this->doc; probiert, aber das klappte nicht, MSVC hat den Operator<< rot markiert, obwohl bei Google dies vorgeschlagen hat.

    Kennt sich jemand mit RapidXML aus?

    Vielen Dank



  • darf ich fragen, was man mit PGN nicht speichern kann? 🙂
    ich versuche mich auch gerade an einer schachengine und biete dieses feature auch an, sehe aber nicht inwiefern PGN nicht ausreicht. soll kein vorwurf und auch keine belehrung oder sowas sein, ich frage nur aus neugier und interesse.

    edit: http://rapidxml.sourceforge.net/manual.html#namespacerapidxml_1printing
    musst - damit der operator<< definiert ist - rapidxml_print.hpp inkludieren.



  • Sepultura schrieb:

    MSVC hat den Operator<< rot markiert

    Wen interessiert, was Intelisense rot markiert? Benutze den Compiler. Wenn im Code Fehler sind, sagt er dir, was ihm nicht passt. Wenn du die Meldungen nicht verstehst, kopierst du sie hier zusammen mit dem Code rein. Dann kann man dir vielleicht helfen.



  • danke, das Problem mit dem Operator ist gelöst.

    Habe aber ein Problem bei der Schleife in der Funktion FileWriter::prepare()

    for (unsigned int k = 0; k < (me[i])[j].getLength(); k++)
    			{
    				xml_node<>* move = doc.allocate_node(node_element, "move");
    				move->append_attribute(doc.allocate_attribute("Number", ((const char*)k)));
    				move->append_attribute(doc.allocate_attribute("White", ((me[i])[j])[k].getMoveW()));
    				move->append_attribute(doc.allocate_attribute("White", ((me[i])[j])[k].getMoveB()));
    				game->append_node(move);
    			}
    

    Beim zweiten umlauf gibt er beim ersten move->append_attribute eine Zugriffsverletzung aus.

    meine Main Funktion:
    Quelle.cpp

    #include"filereader.hpp"
    
    int main(int argc, char** argv)
    {
    	using namespace pgnx;
    	Tournament test;
    	test.setName("Mein Turnier");
    	test.insertGame();
    	test[0].insertMove("c8c7", "c7c8");
    	test[0].insertMove("c8c7", "d7c8");
    	test[0].insertMove("c8c7", "c7e8");
    	test[0].insertMove("c8c7", "c7f8");
    	test[0].setNameW("Benjamin");
    	test[0].setNameB("Philip");
    	FileWriter t("me");
    	t.insertTournament(test);
    	t.prepare();
    	system("pause");
    }
    

    Meine Klassen haben keine Kontrolle, ob züge möglich (laut Schachregeln) sind.
    Desweiteren will er die strings von getMoveW und getMoveB richtig speichern und die Integer wandelt er gar nicht um, die bleiben frei. o.O

    Zur Beantwortung der Frage warum PGNX:
    ich habe mir überlegt, dass auch Media Dateien reinkommen sollen, zum Beispiel könnte jemand die Spiele mit Audio Kommentare verfassen. diese würden in der XML als Pfad innerhalb des kompromierten Datei sein.



  • Du castest ein int nach char* und wundesrt dich, dass das Programm abschmiert? Wirklich?



  • manni66 schrieb:

    Du castest ein int nach char* und wundesrt dich, dass das Programm abschmiert? Wirklich?

    Ich mache morgen (weil die Dateien auf einem anderen PC liegen) eine Funktion per Switch-Case INT2CHAR



  • Mit C++11 gibt es std::to_string .


Log in to reply