# CList<CString,CString> list;    einer Funktion übergeben ?



## Indian (20. Oktober 2004)

Hi

ich hab ein problem. Ich habe eine Klasse in dem Daten in einer Variable vom Typ 
CList<CString,CString> speichere. Diese heist 


```
CList<CString,CString> list;
```

wie kann ich diese Variable einer Funktion überben wie muss der Funktionskopf deklariert sein. Bin momentan echt ratlos, denn ich hab schon vieles versucht.

kann ich dann überhaupt 


```
"return list;"
```

machen 


Thx Indian


----------



## Endurion (20. Oktober 2004)

return list geht. 

Beim Übergeben würde ich wenn möglich Referenzen benutzen:


```
void FunktionTuWas( const CList<CString,CString>& liste )
{
  // dann einfach damit arbeiten
  liste.wullewatz();

}

// Aufruf
FunktionTuWas( list );
```

Wenn du die übergebene Liste ändern willst, entferne das const.


----------



## Indian (21. Oktober 2004)

danke 

1. aber wie initalsiert bzw. schreibt man denn Datentyp des Funktionkopfes ? so ?

CList<CString,CString> Funktion(int a)


2. wie kann ich eine CList<CString,CString> list z.B. zuweisen zu einer anderen CList<CString,CString list2  ?

list2= list;   

^ So geht das nicht da ich eine Fehlermeldung bekomme


----------



## Endurion (21. Oktober 2004)

1) So sollte das aussehen, aber da ich Punkt 2 sehe, denke ich, dass Punkt1 auch nicht geht. Hat CList keinen Zuweisungsoperator? (Hab nachgesehen, hat tatsächlich keinen)

Ohne Zuweisungsoperator wird Punkt 2 nicht, oder wenn, dann nur fehlerhaft funktionieren (Vom Compiler erzeugter Zuweisungsoperator gibt einfach die Pointer per Wert weiter, wenn dann eine der Listen zerstört wird, hat die andere nur noch Schrott).

In dem Fall würde ich das zurückgeben als Returnwert komplett vergessen.

Wenn du eine Liste in einer Funktion füllen willst, mach es so:


```
void FunktionTuWas( CList<CString,CString>& liste )
{
  // dann einfach damit arbeiten
  liste.AddHead( ... );
}


// Aufruf:

CList<CString,CString>   meineListe;

FunktionTuWas( meineListe );

// meineListe ist jetzt gefüllt..
```

Nachtrag zu Punkt 2:

Es scheint ja nicht mal einen Copy-Befehl für CList zu geben. Wenn du eine zweite Liste mit den Werten füllen willst, musst du wohl die Elemente einzeln rüberpacken.

Versuch doch mal die STL std::list, die kann das alles. Die Handhabung ist zwar manchmal besch......eiden, aber dafür kann sie die wichtigen Dinge für Zuweisung.


----------



## Indian (21. Oktober 2004)

vielen dank, eine frage noch 

CList<CString,CString> list;

list ermöglicht mir doch das ich 2 Strings abspeichern kann oder ? kann ich auch CList<CString> list benutzen ?


Denn ich habe ein CListCtrl Steuerelement, wo ich jedes Spalte bzw Zeilde editieren kann (ausgenommen der ersten). Deshalb möchte ich denn index, welcher in der ersten Spalte steht, merken bzw. zwischenspeichern. Ziel ist es denn Speichervorgang in die Datenbank zu beschleunigen. Es wird nur das abgespeichert was verändert wurde.


----------



## dorado (21. Oktober 2004)

Nein,

CList<CString, CString> ist ein Template einer Liste mit String Objekten. Das erste CString gibt den Typ an, der in der Liste verwaltet wird, das zweite den Argumenttyp, den du z.B. bei AddHead als Argument an die Methode übergibst.


Übrigens gibt es die Klasse CStringList mit derselben Funktionalität, aber nicht als Template.


----------



## Indian (21. Oktober 2004)

d.h. ich kann dann für meine obige Anwendung CStringList verwenden...


----------



## dorado (21. Oktober 2004)

Ja, tut dasselbe.

Zu deinem Index zurück. 
Wenn es sich um lange Listen handelt und du dir den Index der geänderten Einträge merken willst, solltest du CMap verwenden, anstelle von CList. Dann kannst du schnell eindeutige Einträge darin ablegen ohne auf Duplikate prüfen zu müssen.


----------



## Indian (21. Oktober 2004)

geil

dass muss man schon wissen.. und wie ist das mit denn Datentypen für CMap ? 
Die Index die ich benutze sind vom Typ CString.. funktioniert das mit CMap ?

ich hab eine klasse in der die CStringList gefüllt werden soll. CMap sieht kompliziert aus und hab auch keine Ahnung wie ich das hier mit CMap realisieren soll.

Initialisierung

```
..
public: 
       CStringList Index;
..
```

Code:

```
void Funktion (CString string)
{
Index.AddTail(string);
}
```

Ein Object dieser Klasse wird schliesslich in meine anderen klasse erzeugt. Das problem ist .. wie habe ich zugriff dann auf CMap  Wie kann ich nun auf Index in einer anderen Klasse zugreifen ?

Am besten ich baue ne Funktion die mir Index zurückliefert oder ?


```
CStringList GetIndex()
{
   return Index;
}
```


----------



## dorado (22. Oktober 2004)

CList und CMap besitzen keinen Copykonstruktor und keinen Copy Operator. Das heisst, du kannst diese Objekte nicht bei value übergeben bzw zurückgeben.

Entweder du gibst eine Referenz auf das Objekt zurück oder du kopierst es um.

const CStringList &GetIndex(void)
{
  return Index;
}

oder

void GetIndex(CStringList &ndx)
{
  ndx.AddTail(Index);
}



Wenn du in diesem Index **eindeutige** Strings speichern musst, würde ich mit CMap arbeiten und erst beim zurückgeben diese CMap in eine Stringlist kopieren.

z.B. mit CMapStringToPtr wobei du den Ptr Anteil nicht brauchst.

CMapStringToPtr Index;

OnIndexChanged(const CString &str)
{
   Index.SetAt(str, NULL);   // Duplikate werden ersetzt, Ptr Anteil nicht genutzt
}

void GetIndex(CStringList &ndx)
{
   CString str;       // index string
   void *ptr = NULL;  // dummy

   // hole alle eingetragenen Strings und kopiere sie in die Stringliste
   for(POSITION pos = Index.GetStartPosition(); pos != NULL; Index.GetNextAssoc(pos, str, ptr))
   {
       ndx.AddTail(str); 
   }
}

In der Map könntest du zu jedem String weitere Daten speichern, da der String ein weiteres Objekt bestimmt. Das ist abhängig von der Art der Map. CMapStringToOb, CMapStringToString ...
Mit der Templateversion kannst du dir auch eigene Maps erstellen, was aber meistens nicht notwendig ist.


----------



## Indian (26. Oktober 2004)

Vielen dank für die ausführliche Erklärung. Ich habe es genauso gemacht wie du es hier geschildert hast.

Bis hier her wird der wert richtig übergeben. Jedoch kann ich beim Debuggen nicht feststellen ob der mit SetAt auch richtig abgespeichert wird. Wenn ich Index im Debug überwache steht unter Objekt -	__vfptr	CXX0030: Fehler: Ausdruck kann nicht ausgewertet werden	*



```
OnIndexChanged(const CString &str)
{
         Index.SetAt(str, NULL); // Duplikate werden ersetzt, Ptr Anteil nicht genutzt
}
```

Beim Aufruf bekomme ich die Werte auch nicht zurück. 
Mein Aufruf

```
CStringList EditedRows;
		m_IDCList.GetEditedRowIndexList(EditedRows);
		for(POSITION pos = EditedRows.GetHeadPosition(); pos != NULL; )
			CString articelNr = EditedRows.GetNext(pos); //get index of edited row
```


----------



## dorado (26. Oktober 2004)

CMapStringToPtr hat ein Member m_pHashTable, das deine Objekte verwaltet und ein m_nCount anhand dessen du siehst wieviele Objekte eingetragen sind.
Wenn du das nicht siehst, ist die Map dort, wo du sie im Debugger betrachtest, nicht mehr gültig.
Ich nehm mal an, dass du in der m_IDCList die geänderten Strings in einer Map speicherst.
Wenn du diese Liste mit GetEditedRowIndexList(EditedRows) holst, musst du sie dort in die Stringliste kopieren.
...::GetEditedRowIndexList(CStringList &EditedRows)
{
   CString str;
   void *ptr = NULL;
   for(pos = Index.GetStartPosition(); pos != NULL; )
   {
      Index.GetNextAssoc(pos, str, ptr);
      EditedRows.AddTail(str);
   }
}


----------



## Indian (26. Oktober 2004)

also ich habs sie so kopiert


```
void CSortListCtrl::GetEditedRowIndexList(CStringList &strList)
{
	CString str; // index string
	void *ptr = NULL; // dummy

	// hole alle eingetragenen Strings und kopiere sie in die Stringliste
	for(POSITION pos = Index.GetStartPosition(); pos != NULL; Index.GetNextAssoc(pos, str, ptr))
	{
		strList.AddTail(str); 
	}
}//end GetEditedRowIndexList
```

irgendwas läuft schief und beim Debuggen bekomme ich auch keine Werte angezeigt. Auch in der Hash Tabelle nicht.


```
void CSortListCtrl::SetEditedRowIndex(const CString &str)
{
	Index.SetAt(str, NULL);


// eingebaut wegen debug
String test;
test = "Hallo";
test = test + "du";

}//end SetEditedRowIndex
```

leider bekam ich hier unter debug auch keine werte angezeigt


----------



## Indian (26. Oktober 2004)

ich denk das die geänderten Strings nicht abgespeichert werden.

Ich denke das hier evtl etwas falsch läuft.

void CSortListCtrl::SetEditedRowIndex(const CString &str)
{
	Index.SetAt(str, NULL);
}//end SetEditedRowIndex


----------



## Indian (26. Oktober 2004)

weist du was. Ich denke das ich hier etwas falsch machen wenn ich versuche die Werte von dem Objekt, des Typs CStringList, abzufragen.

 CStringList EditedRows;
m_IDCList.GetEditedRowIndexList(EditedRows);
for(POSITION pos = EditedRows.GetHeadPosition(); pos != NULL; )
CString articelNr = EditedRows.GetNext(pos); //


----------



## dorado (26. Oktober 2004)

Ist im Prinzip schon OK. Nur beim Holen der Liste  aus CSortListCtrl darfst du das GetNextAssoc nicht am Ende der for Anweisung schreiben, da dies ja erst nach dem ersten Schleifendurchlauf ausgeführt wird.

void CSortListCtrl::GetEditedRowIndexList(CStringList &strList)
{
	CString str; // index string
	void *ptr = NULL; // dummy

	// hole alle eingetragenen Strings und kopiere sie in die Stringliste
	for(POSITION pos = Index.GetStartPosition(); pos != NULL; )
	{
                Index.GetNextAssoc(pos, str, ptr)
 	strList.AddTail(str); 
	}
}//end GetEditedRowIndexList

Was mich nur etwas wundert, dass du im Debugger die Objekte nicht ordentlich siehst.
An der Stelle mt dem SetAt solltest du eigentlich das Index Objekt ansehen können.

Wenn die Speicherung funktioniert (was ich mal schwer annehme), erhöht sich nach dem Index.SetAt() der Zähler Index.m_nCount um 1.


----------

