Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Lemming

Alter Hase

  • »Lemming« ist der Autor dieses Themas

Beiträge: 550

Beruf: Schüler

  • Private Nachricht senden

1

09.11.2005, 23:20

in std::map überprüfen, ob ein eintrag bereits existiert...

Hi,
mir ist nicht ganz klar, wie ich in einer std::map überprüfen kann, ob ein Eintrag schon existiert. Denn die Methode std::map::find() bringt mir wenn se zu dem eingegebenen key nüscht findet nen iterator auf das letzte element. Und da die map ja irgendwie automatisch sortiert kann ich mich ja nich darauf verlassen, dass das letzte Element das ist, dass ich als erstes eingespeichert hab.
Wie kann ich jetzt in ner Liste zB ne beliebige Art von Resourcen speichern. Mit dem Hintergedanken, dass Resourcen niemals doppelt geladen werden, kann man ja für alles mögliche gebrauchen.

danke im vorraus Lemming
Es gibt Probleme, die kann man nicht lösen.
Für alles andere gibt es C++...

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

2

10.11.2005, 00:11

Jetzt mal abgesehen davon, dass ich selber nicht mit std::map arbeite. Ich hab mir n Manager auf template Basis geschrieben, der genau für solche Aufgabenstellungen verwendet werden kann. Hier ein bisschen Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
Klassen

template <class T>
struct STListEntry
{
    T*                      Object;
    char*                   pcObjectPath;
    char*                   pcAddInf1;
    char*                   pcAddInf2;

    inline STListEntry() {Object = NULL; pcObjectPath = NULL, pcAddInf1 = NULL, pcAddInf2 = NULL;}
    inline ~STListEntry() {delete Object; delete[] pcObjectPath; delete[] pcAddInf1; delete[] pcAddInf2;}
};

template <class T>
class TMemoryManager
{
private:
    static STListEntry<T>** pObjectList;
    static int              iObjectCount;

protected:
    static T* GetListMember(char* pcObjectPath = NULL, char* pcAddInf1 = NULL, char* pcAddInf2 = NULL)
    {
        //Sind die ZusatzInfos identisch, bzw egal (== NULL)

        //Die Liste durchgehen

        for (int i = 0; i < iObjectCount; i++)
                //Angabe ist egal

            if ((pcObjectPath == NULL || 
                //oder nicht egal, Information existiert und ist identisch

                (pObjectList[i]->pcObjectPath   != NULL && strcmp(pObjectList[i]->pcObjectPath, pcObjectPath)   == 0)) &&               
                //Angabe ist egal

                (pcAddInf1 == NULL || 
                //oder nicht egal, Information existiert und ist identisch

                (pObjectList[i]->pcAddInf1      != NULL && strcmp(pObjectList[i]->pcAddInf1,    pcAddInf1)      == 0)) &&
                //Angabe ist egal

                (pcAddInf2 == NULL || 
                //oder nicht egal, Information existiert und ist identisch

                (pObjectList[i]->pcAddInf2      != NULL && strcmp(pObjectList[i]->pcAddInf2,    pcAddInf2)      == 0)))
                    //dann gefundenes Objekt zurückgeben

                    return pObjectList[i]->Object;
        //ansonsten kein Objekt übereinstimmend:

        return NULL;
    }

public:
    static void InsertEntry(T* Object, char* pcObjectPath = NULL, char* pcAddInf1 = NULL, char* pcAddInf2 = NULL)
    {
        iObjectCount++;
        pObjectList = (STListEntry<T>**)tbMemReAlloc(pObjectList, iObjectCount*sizeof(STListEntry<T>*));
        pObjectList[iObjectCount-1] = new STListEntry<T>;
        pObjectList[iObjectCount-1]->Object = Object;

        //Zuweisen der Strings:

        
        if (pcObjectPath != NULL)
        {
            pObjectList[iObjectCount-1]->pcObjectPath = new char[255];
            strcpy(pObjectList[iObjectCount-1]->pcObjectPath, pcObjectPath);
        }
        if (pcAddInf1 != NULL) 
        {
            pObjectList[iObjectCount-1]->pcAddInf1 = new char[255];
            strcpy(pObjectList[iObjectCount-1]->pcAddInf1, pcAddInf1);
        }
        if (pcAddInf2 != NULL) 
        {
            pObjectList[iObjectCount-1]->pcAddInf2 = new char[255];
            strcpy(pObjectList[iObjectCount-1]->pcAddInf2, pcAddInf2);
        }

    }

    //Setzt vorraus, dass die chars zugewiesenen Speicher haben, im Normalfall char* = new char[255]

    static void GetChars(T* Object, char* pcObjectPath = NULL, char* pcAddInf1 = NULL, char* pcAddInf2 = NULL)
    {
        for (int i = 0; i < iObjectCount; i++)
            if (Object == pObjectList[i]->Object)
            {
                if (pcObjectPath != NULL && pObjectList[i]->pcObjectPath != NULL)   
                    strcpy(pcObjectPath, pObjectList[i]->pcObjectPath);
                if (pcAddInf1 != NULL && pObjectList[i]->pcAddInf1 != NULL)
                    strcpy(pcAddInf1, pObjectList[i]->pcAddInf1);
                if (pcAddInf2 != NULL && pObjectList[i]->pcAddInf2 != NULL)
                    strcpy(pcAddInf2, pObjectList[i]->pcAddInf2);
                break;
            }
    }

    static void Release()
    {
        tbMemFree(pObjectList);
    }
};
template <class T>
int TMemoryManager<T>::iObjectCount = 0;
template <class T>
STListEntry<T>** TMemoryManager<T>::pObjectList = NULL;
//*******************************************************

class CEffectManager : public TMemoryManager<tbEffect>
{
public:
    static tbEffect* GetEntry(char* pcEffectPath = NULL, char* pcAddInf1 = NULL, char* pcAddInf2 = NULL)
    {
        tbEffect* Effect = GetListMember(pcEffectPath, pcAddInf1, pcAddInf2);
        if (Effect == NULL)
        {
            Effect = new tbEffect;
            Effect->Init(pcEffectPath);
            InsertEntry(Effect, pcEffectPath, pcAddInf1, pcAddInf2);
        }
        return Effect;
    }
};

class CModelManager : public TMemoryManager<tbModel>
{
public:
    static tbModel* GetEntry(char* pcModelPath = NULL, char* pcTexPrefix = NULL, char* pcTexPostfix = NULL)
    {
        tbModel* Model = GetListMember(pcModelPath, pcTexPrefix, pcTexPostfix);
        if (Model == NULL)
        {
            Model = new tbModel;
            Model->Init(pcModelPath, pcTexPrefix, pcTexPostfix);
            InsertEntry(Model, pcModelPath, pcTexPrefix, pcTexPostfix);
        }
        return Model;
    }
};

class CFontManager : public TMemoryManager<tbFont>
{
public:
    static tbFont* GetEntry(char* pcTGAPath = NULL, char* pcTBFPath = NULL, char* pcAddInf2 = NULL, bool bAlwaysCreateNew = false)
    {
        tbFont* Font = NULL;
        if (!bAlwaysCreateNew)
            Font = GetListMember(pcTGAPath, pcTBFPath, pcAddInf2);
        if (Font == NULL)
        {
            Font = new tbFont;
            Font->Init(pcTGAPath, pcTBFPath);
            InsertEntry(Font, pcTGAPath, pcTBFPath, pcAddInf2);
        }
        return Font;
    }
};

Aber mit Vorsicht zu genießen, ich hab den noch nicht bis ins letzte Detail getestet! Die ersten beiden Klassen sind der allgemeine Manager, die 3 danach Beispielklassen.

Also im Klartext: Ich kann dir nicht helfen, aber ich biete ne Alternative an^^

Anonymous

unregistriert

3

10.11.2005, 08:24

Gucke mal da: http://www.germangamedev.de/index.php?site=article&id=11 :)

Lemming

Alter Hase

  • »Lemming« ist der Autor dieses Themas

Beiträge: 550

Beruf: Schüler

  • Private Nachricht senden

4

11.11.2005, 20:12

@nix da

Zitat von »"www.germangamedev.de"«

C-/C++-Quelltext

1
if (surfaces_.find (fileName) == surfaces_.end())

auf die idee hätt ich auch kommen können. Das einzige, was man dabei noch beachten muss is, dass der eintrag den man sucht ja tatsächlich der letzte sein könnte... aber damit sollts gehen

C-/C++-Quelltext

1
if(surfaces_.end()->first == fileName)
oder?

und mal ne andere sache: verwendest du eigentlich nie mal typedefs oder so? die parameter listen deiner funktionen sind zum teil allein wegen der typen entsetzlich lang...



Zitat von »"Spik)evil("«

Also im Klartext: Ich kann dir nicht helfen, aber ich biete ne Alternative an^^
ich danke trotzdem für die mühe :)
Es gibt Probleme, die kann man nicht lösen.
Für alles andere gibt es C++...

helium

Treue Seele

Beiträge: 180

Wohnort: NRW, Burscheid (nahe Köln)

  • Private Nachricht senden

5

11.11.2005, 21:04

Zitat von »"Lemming"«

@nix da

Zitat von »"www.germangamedev.de"«

C-/C++-Quelltext

1
if (surfaces_.find (fileName) == surfaces_.end())

auf die idee hätt ich auch kommen können. Das einzige, was man dabei noch beachten muss is, dass der eintrag den man sucht ja tatsächlich der letzte sein könnte... aber damit sollts gehen

C-/C++-Quelltext

1
if(surfaces_.end()->first == fileName)
oder?


end() verweist aber nicht auf das letzte Element!!!!!!!! (nein, meine Tastatur klemmt nicht)
Es verweist hinter das letzte Element. Deshalb funktioniert das ganze. find() liefert entweder einen iterator auf den gefundenen Eintrag, oder eben end(), was kein gültiger Eintrag ist.
Why is 6 afraid of 7?
Because 7 8 9

Lemming

Alter Hase

  • »Lemming« ist der Autor dieses Themas

Beiträge: 550

Beruf: Schüler

  • Private Nachricht senden

6

12.11.2005, 10:33

Zitat von »"helium"«

end() verweist aber nicht auf das letzte Element!!!!!!!! (nein, meine Tastatur klemmt nicht)

echt...
das wusst ich nich, danke!!! hätt mich wahrscheinlich viele stunden gekostet heraus zu finden was das problem is...
Es gibt Probleme, die kann man nicht lösen.
Für alles andere gibt es C++...

Anonymous

unregistriert

7

12.11.2005, 11:33

Lemming
Typedefs? niemals ;) Lieber lang und eindeutig als ein ugly typedef oder using namespace!

Wie helium schon sagte: Hinter dem letzten Element. Will man das letzte macht mans so:

(--map_.end())->irgendwas();

Lemming

Alter Hase

  • »Lemming« ist der Autor dieses Themas

Beiträge: 550

Beruf: Schüler

  • Private Nachricht senden

8

12.11.2005, 15:23

Zitat von »"nix da"«

Lemming
Typedefs? niemals ;) Lieber lang und eindeutig als ein ugly typedef oder using namespace!
Is der Grund dafür dein persönlicher Geschmack, oder zieht das ganze ernste Nachteile mit sich?
Ich hab bislang immer DWORD verwendet, weil mir das sonst zu lang wird. und ich schreib auch lieber einfach irgendwo using namespace std; statt mich jedes mal mit dem std:: rumzuärgern...
Sollte das allerdings ernste Nachteile haben würd ichs umstellen.
Es gibt Probleme, die kann man nicht lösen.
Für alles andere gibt es C++...

helium

Treue Seele

Beiträge: 180

Wohnort: NRW, Burscheid (nahe Köln)

  • Private Nachricht senden

9

13.11.2005, 11:52

Nachteile hat's nicht. Ich "typedeffe" auch.
Why is 6 afraid of 7?
Because 7 8 9

Anonymous

unregistriert

10

13.11.2005, 12:13

Lemming & Helium
Die Nachteile liegen auf der Hand für Namespaces:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace math
{
namespace std
{
template<typename T> vector
{
public: 
    vector (void) {}
    ~vector (void) {}

    T value;
};
}
}


#include <vector>

using namespace math;
using namespace std;

int main (void)
{
    vector<unsigned long> test; // Welcher vector wird benutzt?


    return 0;
}


Kann sehr gut ins Auge gehen, mit genuss sogar! Vorallem wenn es auch noch Funktionen gibt die der einer API Funktion vom Namen her identisch ist.

Thema Typedefs: Ich möchte es klar und deutlich haben! z.B. DWORD hat den Nachteil das es in älteren SDKs ein #define war, dazu in diversen Platform SDKs hat es noch ein _w64 bekommen, bei anderen SDKs fehlt es. Kann Kompatibilitätsprobleme mit sich führen.

Außerdem wenn ich einen Code von jemanden vor meinen Augen haben möchte ich wissen was das für ein Datentyp ist und nicht erst fragen, geschweige auf dieses Typedef umzudenken. Wenn dann richtig klar oder gar nicht. Halben Kram kann ich nicht ab.

Werbeanzeige