PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Verkettete Liste in Verketteter Liste



ufosworld
07-05-2007, 12:39
Folgendes Problem:

Ich habe eine Datei,

in ihr sind 0-x Funktionsnamen angegeben.
Zusätzlich zu den Funktionsnamen stehen bei jeder Funktion 0-xx Parameter dabei.

Nun sollen die Funktionsnamen in eine Verkettete Liste gespeichert werden.
solange bis keine Funktionsnamen mehr vorhanden sind.

Zu jedem Funktionsnamen sollen die kompletten Parameter als verkettete Liste angehängt werden..

Graphik 1 verdeutlicht das Prinzip

Mittlerweile speichert er auch schon die Funktionsnamen ab,
jedoch bei den Parametern habe ich anscheinend einen Fehler drin, diese speichert er auch ab, aber nicht zu jeder Funktion die entsprechenden Parameter, sondern komplett in einer verketteten Liste, was ja schwachsinn ist... da ich die Parameter so nie wieder einer entsprechenden Funktion zuordnen kann.

Die ganze Liste soll einmal eingelesen werden, nachträglich muss nichts mehr verändert werden. Sie dient dann nur dazu an die entsprechenden Funktionen mittels übergabe des Zeigers den Funktionsnamen und die Parameter zu liefern.

Hier mal die Datenfile.

<?xml version="1.0" encoding="UTF-8"?>
<SETTINGS>
<MODUL mod_id="0">
<MODULNAME mod_name="funktion1.so" />
<PARAMETER par="parameter1"/>
<PARAMETER par="dskjfsd2"/>
<PARAMETER par="33244"/>
<PARAMETER par="0"/>
</MODUL>
<MODUL mod_id="1">
<MODULNAME mod_name="funktion2.so" />
<PARAMETER par="test1_0"/>
<PARAMETER par="test1_1"/>
</MODUL>
<MODUL mod_id="2">
<MODULNAME mod_name="func3.so" />
<PARAMETER par=""/>
</MODUL>
....
<ENDE></ENDE>
</SETTINGS>

//------------------------------------------------------------------
Hier der Quellcode:

#include "tinyxml.h"
#include <list>
#include <string>
#include <map>
#include <iostream>

using namespace std;

struct TParaKnoten
{
string par; //Parameter
TParaKnoten *next; //Zeiger zum nächsten Parameter
};
TParaKnoten *ParAnk = 0;
TParaKnoten *ParOld;

struct TModulKnoten
{
int mod_id; // Mod_ID
string mod_name; // Mod_Name
TParaKnoten *para;
TModulKnoten *next; // Verknüpfung zum Nachfolger
};

TModulKnoten *Anker = 0; // Anfang der Liste
TModulKnoten *node, *old;
TModulKnoten *Start;

class SETTINGS
{
public:

string m_name;

SETTINGS() {}

void load(const char* pFilename);

};

void SETTINGS::load(const char* pFilename)
{
int MODID = 0;

int nummer=0;
int parnummer=1;

TiXmlDocument doc(pFilename);
if (!doc.LoadFile()) return;

TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(0);


// block: name
{
pElem=hDoc.FirstChildElement().Element();
// should always have a valid root but handle gracefully if it does
if (!pElem) return;
m_name=pElem->Value();


// cout << pElem->Value()<< endl; // Ausgabe : SETTINGS

// save this for later
hRoot=TiXmlHandle(pElem);
}


// Modul-ID Modul-Name speichern in node->mod_id, node->mod_name //

pElem=hRoot.ChildElement(nummer).Element();

m_name = pElem->Value();


while(m_name != "ENDE")
{
if (m_name == "MODUL")
{

// cout << "Modul "<<nummer <<" gefunden"<<endl;

//Hier speichern der Werte Mod_id und Mod_Name in Liste

TModulKnoten *node = new TModulKnoten;

if(!node)
{
cerr << "Kein Speicher verfügbar!" << endl;
exit(1);
}

//Speichern der MOD_ID
pElem->QueryIntAttribute("mod_id",&node->mod_id);


//Setzen von pElem auf Tag MODULNAME
pElem= hRoot.ChildElement(nummer).FirstChild("MODULNAME").Element();

//Speichern des MOD_NAMEN
node->mod_name=pElem->Attribute("mod_name");



//Hier Speichern der Parameter //da is noch der Wurm drin...

pElem = hRoot.ChildElement(nummer).ChildElement(parnummer) .Element();

// if (pElem)
// {
m_name = pElem->Value();

while(m_name == "PARAMETER")
{
if (m_name == "PARAMETER")
{

TParaKnoten *para = new TParaKnoten;

if(!node)
{
cerr << "Kein Speicher verfügbar!" << endl;
exit(1);
}

// Speichern des Parameters in die Liste an Speicherstelle para->par
para->par = pElem->Attribute("par");


para->next = ParAnk; // Hänge bisherige Liste an
ParAnk = para; // Setze Anfangspunkt hierher

// cout <<"Attribute: " <<pElem->Attribute("par")<<endl; //Ausgabe: Attribut: gespeichertes Attribute

parnummer++;
pElem = hRoot.ChildElement(nummer).ChildElement(parnummer) .Element();

if (pElem)
{ // Wenn weiterer Parameter dann m_name = PARAMETER
m_name = pElem->Value();
// cout <<"m_name: "<< m_name<<endl; //Ausgabe: PARAMETER
}
else
{ //Falls anderer Value, dann Ende Parameter einlesen
break;
}
}
}
// }
// else
// {
// break;
// }




node->next = Anker; // Hänge die bisherige Liste an
Anker = node; // Setze den Anfangspunkt hierher


//Parameternummer auf Anfang stellen
parnummer=1;
//Weiter zum nächsten Modul
nummer++;
pElem=hRoot.ChildElement(nummer).Element();
m_name = pElem->Value();
}
if (m_name =="ENDE")
{
// cout << "ENDE gefunden"<<endl<<endl;
}


} //Ende While




} //Ende Settings



void delete_all()
{
//Hier liste wieder löschen damit keine Speicherlecks entstehen

while (Anker) // ungleich 0! Die Liste ist nicht leer!
{
cout << Anker->mod_id << endl;
cout << Anker->mod_name << endl;

while(ParAnk)
{
cout << ParAnk->par <<endl;
ParOld = ParAnk;
ParAnk = ParAnk->next;
delete ParOld;
ParOld = NULL;// Setze Zeiger auf Null
}

old = Anker; // Sichere zum späteren Löschen
Anker = Anker->next; // Ziehe nächstes Element nach vorn
delete old; // Lösche das ausgelesene Element
old = NULL; //setze Zeiger auf NULL
}
Anker = NULL; //setze Zeiger auf NULL
ParAnk = NULL; //setze Zeiger auf NULL

}





// ----------------------------------------------------------------------
// main()
// ----------------------------------------------------------------------

int main(int argc, char* argv[])
{
SETTINGS settings;

settings.load("test2.xml");


// cout << Start->mod_name << endl;

delete_all();

return 0;
}

//-------------------------------------------------------------------

Eventl kann mir ja jemand nen Tip geben, wie ich das so umbaue, das er mir für jede neue Parameterliste unter einer Funktion einen neue erstellt und nicht immer alles an eine Liste hinhängt....

die Ausgabe sieht nämlich dann so aus... und das ist ja falsch...
(auch im Debugger sieht man das er alle Parameter in eine Liste speichert ...)
(ausserdem speichert er mir die Liste verkehrt herum ab... kann man das auf die Schnelle ändern???..

- wie ich es verstanden habe, hängt er einen neuen Datensatz immer vorne an die Liste an.... ist das korrekt?

- feste Zeiger die auf Start und Ende zeigen wären auch von Vorteil.




2
func3.so

test1_1
test1_0
0
33244
dskjfsd2
parameter1

1
funktion2.so
0
funktion1.so

:(
danke schon mal UFO

anda_skoa
07-05-2007, 14:15
Ich gehe mal davon aus, daß du die verkette Liste selbst machen mußt, weil das eine akademische Aufgabenstellung ist, richtig?

In diesem Fall rate ich dir, nicht nur die Knoten Struktur als eigenen Datentyp zu definieren, sondern auch die Liste selbst, d.h. das was derzeit deine globalen Variablen sind. Dann wäre nämlich beim Erzeugen der Parameterliste kein Problem wie hier aufgetreten (ParAnk wird beim Erzeugen des Modulknotens nicht zurückgesetzt, zeigt daher auf die Liste des Modul Vordgängers)

Ciao,
_

ufosworld
07-05-2007, 15:39
Ja muss die selbst machen. Also kein List oder Vector ...

Sorry aber das zweite check ich jetzt nicht auf Anhieb...
Soll ich die verkettete Liste nochmal in eine verkettete Liste packen???

Kannst du mal ein Beispiel schreiben, wie die Struktur aussehen müsste?

danke schon mal

UFO

bischi
07-05-2007, 16:03
Soll ich die verkettete Liste nochmal in eine verkettete Liste packen???
Jep - es sei denn, du hast ne bessere Idee...

MfG Bischi

anda_skoa
07-05-2007, 18:49
Sorry aber das zweite check ich jetzt nicht auf Anhieb...
Soll ich die verkettete Liste nochmal in eine verkettete Liste packen???

Kannst du mal ein Beispiel schreiben, wie die Struktur aussehen müsste?


Eine Liste ist von außen gesehen ein Objekt. Daß jedes Element wieder ein Objekt ist, ist praktisch ein internes Detail der Liste.

D.h. das eigentlichen Listenobjekt hat einen Zeiger auf das erste Element und im Idealfall Methoden für Hinzufügen, Entfernen, usw.

In etwa so



struct TParaListe
{
TParaListe();
~TParaListe();

TParaKnoten* first;
};

TParaListe::TParaListe() : first(0)
{
}

TParaListe::~TParaListe()
{
while (first != 0)
{
TParaKnoten* node = first;
first = first->next;
delete node;
}
}

Analog für die Modulliste

Wenn man dann einen Modulknoten erzeugt, kann man gleich dafür ein TParaList Objekt anlegen und im Modulknoten verankern (idealerweise im Konstruktor von TModulKnoten)
Damit hat jeder Modulknoten ganz sicher seine eigene Parameterliste.

Ciao,
_

ufosworld
07-05-2007, 23:05
und wo speichert der jetzt in dem Code von dir den Parameter ab?

muss ich doch irgendwo

string par;

angeben oder etwa nicht...

Nachtrag... achso ich muss das ergänzend zu meinem Code hinzufügen....

ufosworld
08-05-2007, 11:09
Sorry, aber hab das jetzt irgendwie hinzugefügt... aber im Endeffekt sitz ich hier wie der Ochs vorm Berg...

stimmt das erstmal soo??

------------------
// bleibt TParaKnoten soo`?
struct TParaKnoten
{
string par; //Parameter
TParaKnoten *next; //Zeiger zum nächsten Parameter
};
//Brauche ich die Zeiger noch?
TParaKnoten *ParAnk = 0;
TParaKnoten *ParOld;


struct TParaListe
{
TParaListe(); // Konstruktor
~TParaListe(); // Destruktor

TParaKnoten *first;
};

// Konstruktor: Erzeugen der Parameterliste
TParaListe::TParaListe() : first(0)
{
}

//Destruktor: Löschen der Parameterliste
TParaListe::~TParaListe()
{
while (first != 0)
{
TParaKnoten* node = first;
first = first->next;
delete node;
}
}

//ist das der konstruktor des TModulKnoten??
struct TModulKnoten
{
int mod_id; // Mod_ID
string mod_name; // Mod_Name
TParaKnoten *para; //benötige ich das noch??
TModulKnoten *next; // Verknüpfung zum Nachfolger brauche ich den noch???
TParaListe *first; //muss ich das hier soo einfügen??

};

// was ist mit den Zeigern hier... brauche ich die noch??
TModulKnoten *Anker = 0; // Anfang der Liste
TModulKnoten *Work = 0; // Arbeitsknoten der Liste
TModulKnoten *node, *old;




struct TModulListe
{
TModulListe(); // Konstruktor
~TModulListe(); // Destruktor

TModulKnoten* first;
};

// Konstruktor: Erzeugen der Modulliste
TModulListe::TModulListe() : first(0)
{
};

//Destruktor: Löschen der Modulliste
TModulListe::~TModulListe()
{
while (first != 0)
{
TModulKnoten* node = first;
first = first->next;
delete node;
}
};
----------------

was muss ich nun nacheinander aufrufen das er mir die gewünschte Liste erzeugt...
ich bin hier echt am verzweifeln.... Scheiss Listen...

anda_skoa
08-05-2007, 14:03
// bleibt TParaKnoten soo`?
struct TParaKnoten
{
string par; //Parameter
TParaKnoten *next; //Zeiger zum nächsten Parameter
};

Es wäre sauber, auch dort einen Konstruktor zu machen und den "next" Pointer auf "0" zu initialisieren.



//Brauche ich die Zeiger noch?
TParaKnoten *ParAnk = 0;
TParaKnoten *ParOld;

Nein. Wenn du zusätzlich Zeiger brauchen solltest, kommen die jetzt nach TParaListe, d.h. keine globalen Variablen, jede Liste ist für sich selbst funktionsfähig.



//ist das der konstruktor des TModulKnoten??
struct TModulKnoten

Nein, das ist nur die Struktur ohne eigenen Konstruktor. Ein Konstruktor würde aber Sinn machen, um die Pointer zu initialisieren



TParaKnoten *para; //benötige ich das noch??

Nein, am seine Stelle dritt der TParaList Pointer



TModulKnoten *next; // Verknüpfung zum Nachfolger brauche ich den noch???

Natürlich, die Modulliste ist ja weiterhin eine Liste. Das ist absolut analog zur Parameter Liste. Die Listen unterscheiden sich lediglich im Dateninhalt der Knoten (ein String bei Parameterknoten; ein int, ein String und eine Parameterliste bei Modulknoten)



TParaListe *first; //muss ich das hier soo einfügen??

Ja, allerdings wäre ein anderer Variablenname passender, vielleicht "paramlist"



// was ist mit den Zeigern hier... brauche ich die noch??
TModulKnoten *Anker = 0; // Anfang der Liste
TModulKnoten *Work = 0; // Arbeitsknoten der Liste
TModulKnoten *node, *old;

Siehe oben.



was muss ich nun nacheinander aufrufen das er mir die gewünschte Liste erzeugt...
ich bin hier echt am verzweifeln.... Scheiss Listen...

Listen sind ansich sehr einfach, du machst nur zu viel auf einmal.

Man kann zum Beispiel zuerst eine Liste mit all ihren Operationen ohne Daten machen und dann einfach für entsprechende Datenknoten anpassen. Der Code der Listen Objekte bleibt quasi unverändert (bis auf den Typ der Knoten)

Ciao,
_