Problem mit QList: Einfügen eines eigenen Datentyps

Du bist neu in der Welt von C++? Dann schau hier herein!
erpheus
Beiträge: 46
Registriert: 18. November 2008 11:55
Wohnort: Stuttgart

Beitrag von erpheus »

du könntest vor deinen for-Schleifen mal schauen welches Ergebnis die size()-Funktionen überhaubt liefern. Ich vermute das deine Listen einfach leer sind.

Übrigens solltest Du es so wie du es jetzt machst die Abbruchbedingung in deinen Schleifen immer mit einer size()-Funktion machen. Es sei denn du bist dir 1000000000% sicher das entsprechend viele Elemente drinn sind.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

hi jo das hab cih! die tupel interne liste ist wirklich leer! habs mit isEmpty() überprüft und ich weis nich woran das liegt! ich hab

Code: Alles auswählen

while(result.next()){
				tupel current(temp_serial);
				for(int y=0; y<meta_result.count(); y++)
				{
					qDebug() << result.value(y);
					QVariant temp(result.value(y));
					current.getAttributes().append(temp);
				}
				objekte.append(current);
				temp_serial++;
			}
mal versucht ein neues objekt anzulegen und dass dann in die liste zu packen, aber das funktioniert auch nciht. hatte vermutet, dass es vllt an den zeigern liegt...

Code: Alles auswählen

#pragma once
#include <QList>
#include <QVariant>

class tupel
{


public:
	tupel(void);
	tupel(int);
	~tupel(void);
	
	QList<QVariant> getAttributes(void) const;
	int getSerial() const;

private:
	int serial;
	QList<QVariant> attributes;
ist vllt was an der initialisierung falsch???
erpheus
Beiträge: 46
Registriert: 18. November 2008 11:55
Wohnort: Stuttgart

Beitrag von erpheus »

Verbesser bitte meine Kommentare!

Code: Alles auswählen

while(result.next()){ 
            tupel current(temp_serial); //neues Tubelobejct mit serial=temp_serial
            for(int y=0; y<meta_result.count(); y++)//meta_result ist was für eine Liste? Die tubel-Liste in result oder die Liste w die tubelobjekte drinn sind? woher weiss dein program das hier?
            {
               qDebug() << result.value(y); //was ist der unterschied zwischen result.next() und result.value(y) ?
               QVariant temp(result.value(y)); //mir scheint du holst ein tubel objekt
               current.getAttributes().append(temp); //und hängst dieses an dessen interne liste selbst an *rekursiv den kopf verdreh
            }
            objekte.append(current);//jetzt blick ich es nicht mehr
            temp_serial++;//ich hoffe temp_serial wurde vor der schleife auf null gesetzt
         }
kurz gesagt poste deinen Code nochmal mit deinen Kommentaren dahinter und zusätzlich noch die stellen wo die jeweils verwendeten Variablen deklariert werden.

Schau dir mal noch im Assistent die stelen an wo erklärt wird wie man durch ne Liste läuft. anstatt next() und while geht auch

Code: Alles auswählen

QList<Typ> list;
.....
for(int i=0; i<list.size(); ++i)
{
      Typ element = list[i]; 
}
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

Code: Alles auswählen


/* Eigentliches Abfangen der Ergebnistupel
		*/
		QSqlQuery result;
		result.exec(sql_anfrage); //Absetzen der Anfrage
		
		QSqlRecord meta_result = result.record();	 //meta_result dient dazu, die Anzahl der Attribute festzustellen
		if(result.size()!=-1)						//wenn ein Tupel zurückgeliefert wird, dann..
		{
			int temp_serial=0;						//"Seriennummer" des Tupels beginnend bei 0
			while(result.next()){					//solange noch ein (von der DB zurückgeliefertes )Tupel vorhanden ist
				tupel current(temp_serial);			//wird ein "Tupel" mit der neuen Seriennummer erstellt
				for(int y=0; y<meta_result.count(); y++)
				{
					qDebug() << result.value(y);	//testweises Ausgeben des aktuellen(y) Attributs des Tupels
					(current.getAttributes()) << result.value(y);  //Attribut wird dem aktuellen Tupel zugefügt
					
				}
				
				objekte << current;					// das Element Tupel wird nachdem seine interne Attributsliste gefüllt wurde in eine eigene Liste gespeichert
				temp_serial++;						// die Seriennummer wird erhöht 
			}
		}
Ich will also diese reellen Tupel, die mir das Datenbanksystem zurückliefert, in ein Element "tupel" welches von mir in C++ definiert wurde, "umspeichern". Dazu besitzt dieses element tupel eine interne liste vom Typ QVariant, in das die ganzen Attribute (id, name, hausnummer,...) einfach reingespeichert werden.
Und ich hab das so verstanden, dass QsqlQuery result mir sozusagen jeweils immer ein Ergebnistupel zurückliefert, also ein Datensatz einer Tabelle. Also iterier ich in der while(result.next()) Schleife mit einem zusätzlichen Zähler durch die attribute durch und werf sie nacheinander in die Liste.
erpheus
Beiträge: 46
Registriert: 18. November 2008 11:55
Wohnort: Stuttgart

Beitrag von erpheus »

Code: Alles auswählen

qDebug() << result.value(y);   //testweises Ausgeben des aktuellen(y) Attributs des Tupels 
das funktioniert oder?

Code: Alles auswählen

(current.getAttributes()) << result.value(y);  //Attribut wird dem aktuellen Tupel zugefügt 
So wie du getAttributes() geschrieben hast, liefert dir diese Methode eine Kopie der Liste des Objekts current. In diese Kopie fügst du nun den neuen Wert result.value(y) ein.

Wenn Du nun später die Liste des Objekts ausgeben willst ist diese leer. Weil du die Objekte ja in derren Kopie eingefügt hast.

Das heißt getAttributes muss dir einen Pointer auf die Liste zurückgeben und mit dessen Hilfe fügst du dann dort den wert ein.
Das heisst deine obige Zeile würde dann so aussehen:

Code: Alles auswählen

current.getAttributes()->append(result.value(y))
Ich weiß nicht ob der <<-Operator bei Pointern funktioniert daher hab ich es jetzt mal mit append() gemacht.

Ist übrigens klasse wie du Dein Problem beschreiben konntest vor allem mit den Kommentaren im Code.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

geht leider nicht...

Code: Alles auswählen

QSqlQuery result;
		result.exec(sql_anfrage); //Absetzen der Anfrage
		
		QSqlRecord meta_result = result.record();	 //meta_result dient dazu, die Länge der Attribute festzustellen
		if(result.size()!=-1)						//wenn ein Tupel zurückgeliefert wird, dann..
		{
			int temp_serial=0;						//"Seriennummer" des Tupels beginnend bei 0
			while(result.next())
			{										//solange noch ein Tupel vorhanden ist
				tupel current(temp_serial);			//wird ein "Tupel" mit der neuen Seriennummer erstellt
				for(int y=0; y<meta_result.count(); y++)
				{
					qDebug() << result.value(y);	//testweises Ausgeben des aktuellen(y) Attributs des Tupels
					current.getAttributes()->append(result.value(y));  //Attribut wird dem aktuellen Tupel zugefügt
				}
				objekte << current;					// das Element Tupel wird nachdem seine interne Attributsliste gefüllt wurde in eine eigene Liste gespeichert
				temp_serial++;						// die Seriennummer wird erhöht 
			}
da kommt nun folgender fehler:

Code: Alles auswählen

\dbvis.cpp(116) : error C2819: Der Typ 'QList<T>' hat keinen überladenen Elementoperator '->'
1>        with
1>        [
1>            T=QVariant
1>        ]
1>        Wollten Sie stattdessen '.' verwenden?
1>.\dbvis.cpp(116) : error C2232: '->QList<T>::append': Der linke Operand ist vom Typ 'class', verwenden Sie '.'
1>        with
1>        [
1>            T=QVariant
1>        ]
das testweise ausgeben der einzelnen attribute auf der debugconsole klappt einwandfrei

So wie du getAttributes() geschrieben hast, liefert dir diese Methode eine Kopie der Liste des Objekts current. In diese Kopie fügst du nun den neuen Wert result.value(y) ein.

Code: Alles auswählen

QList<QVariant> tupel::getAttributes() const
{
	return this->attributes;
}
wieso liefert mir das eine kopie zurück? is das ne c++ eigenheit?`weil java würde mir da die originalliste liefern?
erpheus
Beiträge: 46
Registriert: 18. November 2008 11:55
Wohnort: Stuttgart

Beitrag von erpheus »

mach aus

Code: Alles auswählen

QList<QVariant> tupel::getAttributes() const
{
   return this->attributes;
}
das da und vergiss das h-file nicht

Code: Alles auswählen

QList<QVariant>* tupel::getAttributes() const
{
   return *(this->attributes);
}
damit deine getter auch nen Zeiger zurück gibt
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

erpheus hat geschrieben:mach aus

Code: Alles auswählen

QList<QVariant> tupel::getAttributes() const
{
   return this->attributes;
}
das da und vergiss das h-file nicht

Code: Alles auswählen

QList<QVariant>* tupel::getAttributes() const
{
   return *(this->attributes);
}
damit deine getter auch nen Zeiger zurück gibt
Definitiv nicht. Wenn dann muss er die Adresse zurückgeben, also aus dem "*" ein "&" machen.
Trotzdem ist das der falsche Ansatz, er muss halt einfach beim Zugriff das "-> mit dem "." ersetzen, so wie es in der Meldung steht.
Außerdem würde ich sowieso eine nackte Liste erstellen, diese mit den Werten füttern, und nach der inneren (die mit dem "y") Schleife mit einem "setAttributes()" setzen.
erpheus
Beiträge: 46
Registriert: 18. November 2008 11:55
Wohnort: Stuttgart

Beitrag von erpheus »

dann test doch auch so.
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

hi, also -> hab ich erst auf den rat hin gemacht, aber das mit dem setter is allerdings keine schlechte idee! darauf bin ich gar nicht gekommen!!
danke werds glei ausprobieren!!!
erpheus
Beiträge: 46
Registriert: 18. November 2008 11:55
Wohnort: Stuttgart

Beitrag von erpheus »

Glaub zwar du weist das schon aber sicherheitshalber hier noch ne Erklärung:
Es gibt zwei verschiedene Notationen einmal '->' und '.'
den angedeudeten Pfeil/Zeiger verwendest du wenn es sich um einen Pointer handelt und den Punkt bei einem normalen member.

Bespiel:

Typ a();
Typ *b = new Typ();

wenn Typ jetzt einen Member z hat greifst du folgendermaßen drauf zu:
a.z
und
b->z

daher musstest du vorhin deiner getter-Methode anpassen damit '->' funktioniert.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Prinzipiell kannst du dir auch noch überlegen, ob du statt der QVariantList eine QMap<QString, QVariant> nimmst, dann kannst du als key (->QString) den Spaltennamen einsetzen.
So weißt du auch nachher noch, was der variant überhaupt genau repräsentiert (z.B. "Vorname", "Nachname" oder "Geschlecht" etc...)
Illuminatus
Beiträge: 84
Registriert: 3. Dezember 2008 12:48

Beitrag von Illuminatus »

hi also vielen dank für den tipp mit dem setter ;) klappt einwandfrei! werd morgen mal die zeit nutzen um das ganze mit ner map, wie dus vorgeschlagen hast, zu machen =)

thx =)
Antworten