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

Anonymous

unregistriert

1

22.02.2004, 20:41

einfach verkettete Liste

Ich habe mir eine einfach verkettete Liste programmiert um eine beliebige Anzahl Direct3D-Materialien zu speichern. Damit hatte ich auch keine Probleme aber nun brauche ich eine Suchfunktion, die mir den Index des Materials zurückgibt, anhand des Materialnamens. Ich zeige euch jetzt einfach mal den Code, dann versteht mans wahrscheindlich besser:

Quellcode

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
#include <d3d9.h>

typedef struct _MATERIAL
{
    char         MaterialName[32];
    D3DMATERIAL9 Material;
    char         TextureName[24];
} MATERIAL;

typedef struct _MATERIALLIST
{
    MATERIAL             *data;
    struct _MATERIALLIST *next;
} MATERIALLIST;

typedef enum _RESULT
{
    LIST_ERROR=0,
    LIST_OK   =1,
} RESULT;

MATERIALLIST *Materialliste;

//Materialliste erzeugen mit RAM initialisierung
RESULT MaterialListCreate(void)
{
    Materialliste = (MATERIALLIST*)malloc(sizeof(MATERIALLIST));

    if(Materialliste == NULL)
        return LIST_ERROR;

    Materialliste->data = NULL;
    Materialliste->next = NULL;

    return LIST_OK;
}

//Einfügen am Anfang der Materialliste
RESULT MaterialListInsert(MATERIAL *data)
{
    MATERIALLIST *Newelement; //neues Listenelement

    //1. Fall: Einfügen in leere Liste
    if(Materialliste->data == NULL)
    {
        Materialliste->data = data;
        return LIST_OK;
    }

    //2. Fall: Einfügen in nicht-leere Liste
    Newelement = (MATERIALLIST*)malloc(sizeof(MATERIALLIST));

    //Fehler bei Initialisierung
    if(Newelement == NULL)
        return LIST_ERROR;

    else
    {
        //Daten speichern, Zeiger setzen
        Newelement->data = data;
        Newelement->next = Materialliste;
        Materialliste = Newelement;
        return LIST_OK;
    }
}

//Löschen an angegebener Position, Start bei index 0
RESULT MaterialListDelete(int index)
{
    MATERIALLIST *temp, *prev;

    //1. Fall: Leere Liste
    if((Materialliste == NULL) || (Materialliste->data == NULL))
        return LIST_ERROR;

    //2. Fall: Erstes Element löschen
    if(index == 0)
    {
        //Erstes Element übergehen und Speicher freigeben
        temp = Materialliste;
        Materialliste = Materialliste->next;
        free(temp);
        return LIST_OK;
    }

    //3. Fall: 2., 3., ... Element löschen
    temp = Materialliste;

    //Liste durchlaufen bis index erreicht oder Liste zu Ende
    while((Materialliste->next != NULL) && (index != 0))
    {
        //Vorgängerelement merken und weitergehen
        prev = Materialliste;
        Materialliste = Materialliste->next;
        index--;
    }

    //Index wurde nicht gefunden  ->  Liste zu kurz
    if(index != 0)
    {
        Materialliste = temp;
        return LIST_ERROR;
    }

    //Gefundenes Element übergehen und Speicher freigeben
    prev->next = Materialliste->next;
    free(Materialliste);
    Materialliste = temp;

    return LIST_OK;
}

//Länge der Materialliste
int MaterialListLength(void)
{
    MATERIALLIST *temp;
    int Lenght=0;

    if(Materialliste == NULL || Materialliste->data == NULL)
        return Lenght;

    Lenght=1;
    temp = Materialliste;
    while(temp->next != NULL)
    {
        Lenght++;
        temp = temp->next;
    }

    return Lenght;
}


Ich habe die Suchfunktion geschreiben und Tage lang daran rum gefeilt aber sie funktioniert einfach nicht:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Suchen des Materialindex mithilfe des Namens
int MaterialListSearch(char Name[32])
{
    MATERIALLIST *temp;
    int          Index=0;

    //Leere Liste
    if(Materialliste == NULL || Materialliste->data==NULL)
        return -1;

    temp = Materialliste;

    while(temp->next != NULL)
    {
        if(temp->data->MaterialName==Name)
            return Index;
        Index++;
        temp = temp->next;
    }

    return -1;
}


Ich hoffe ihr könnt mir helfen.

CuTeX0r

Treue Seele

Beiträge: 174

Wohnort: Deutschland

  • Private Nachricht senden

2

23.02.2004, 11:50

Quellcode

1
      if(temp->data->MaterialName==Name) 


ich denke da liegt der fehler. so wird denke ich nur das erste char verglichen o.ä. ehrlich gesagt weiß ich gar nich was so passiert ;) ;D

also übergib der funktion besser nicht

Quellcode

1
char Name[32]
sondern

Quellcode

1
const char* Name
und dann vergleichst du in der if abfrage nicht mit == sondern mit strcmp:

Quellcode

1
      if(strcmp(temp->data->MaterialName,Name)==0) ...


Außerdem würde ich in der Struktur für die Materialien dem Textur und dem Materialnamen ein paar chars mehr geben, da ich finde dass 24 / 32 bisschen wenig ist ;) kannst denk ich ruhig 128 drauß machen :)

hoffe ich konnte helfen,
mfg CuTeX0r

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

3

23.02.2004, 12:09

" if(temp->data->MaterialName==Name)" vergleicht die Zeiger. Also, in der Tat str(i)cmp benutzen

Ausserdem verhindert das

Zitat


while(temp->next != NULL)
{
...
}


dass der letzte Listeneintrag untersucht wird.

Eine Sache, die m.E. häufig unterschätzt wird sind Variablen- und Typ-Namen.

Dein MATERIALLIST Typ ist für mich eher ein MATERIALLISTENTRY.

Dass dann die Materiallist ein Zeiger zu einem MATERIALLISTENTRY ist, ist klar.

Anonymous

unregistriert

4

23.02.2004, 13:32

Das ganze sieht jetzt so aus ...

Quellcode

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
//Suchen des Materialindex mithilfe des Namens 
int MaterialListSearch(const char* Name) 
{ 
    MATERIALLIST *temp; 
    int          Index=0; 

    //Leere Liste 
    if(Materialliste == NULL || Materialliste->data==NULL) 
        return -1; 

    if(strcmp(Materialliste->data->MaterialName,Name)==0)
        return Index;

    temp = Materialliste; 

    while(temp->next != NULL) 
    { 
        Index++; 
        temp = temp->next; 
        if(strcmp(temp->data->MaterialName,Name)==0)
            return Index; 
    } 

    return -1; 
}


... funktioniert aber immer noch nicht.

Die Funktion liefert immer -1 zurück. Auch wenn sie mit sicherheit irgend einen Index zurückliefern müsste.

5

23.02.2004, 18:15

Ich könnte mir gut Vorstellen das du vieleicht die Groß- und Kleinschreibung mißachtet hast. Oder du hast den Namen deines Materials nicht in MaterialName kopiert.
Durchlaufe mal die Liste und schreib die Werte in eine einfache Text Datei. Natürlich in Klartext ;D. Dann siehtst du vieleicht eher wo der Fehler liegt.

Tipp: Der Vergleich über den Namen sollte man möglichst nicht zur Laufzeit machen. Das ist schlicht zu langsam.
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

6

23.02.2004, 18:31

Ich schätze auch, der Fehler liegt in Deinem Test code. Du solltest versuchen, das Programm zu Debuggen, dann siehst Du genau die Werte und welchen "Pfad" beim ausführen durch Dein Programm genommen wird. Welchen Compiler hast Du?

big_muff

Alter Hase

Beiträge: 460

Wohnort: Schweiz

Beruf: Informatikstudent (4. Semester)

  • Private Nachricht senden

7

23.02.2004, 18:39

Ich habe Visual C++ 6.0

Und das wegen Laufzeit und so: Das ganze ist für einen Modelleditor. Und in dem Modelleditor hat es einen Materialmanager, wo man neue Materialien erstellen, welche löschen, bearbeiten oder von einer Modelldatei importieren kann. Und dieser Test erfolgt immer dann wenn man den "Hinzufügen" oder "Ändern" Knopf drückt. Und mit dieser Funktion prüfe ich ob ein Material mit diesem Namen schon vorhanden ist. Und wenn ich nun 2 Materialien mit dem Namen "Test" einfüge geht das Problemlos obwohl eigentlich eine Fehlermeldung kommen solte.

Ich probier jetzt mal eure Tipps aus und schonmal Danke für die Bemühung mir zu helfen! ;)

big_muff

Alter Hase

Beiträge: 460

Wohnort: Schweiz

Beruf: Informatikstudent (4. Semester)

  • Private Nachricht senden

8

23.02.2004, 22:59

Ich habe mal das mit der Textdatei probiert. In der Funktion MaterialListSearch() habe ich in jedem Schleifendurchlauf und nach dem Test des Ersten Elements den aktuellen Materialnamen in die Textdatei geschrieben. Ich habe die Materialien Test1, ..., Test9 kreiert und habe mir dann die Textdatei angeschaut:

Quellcode

1
2
3
4
5
6
7
8
0: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ
1: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ
2: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ
3: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ
4: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ
5: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ
6: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ
7: ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌtõ


Erstens mal sind das nur 8 Elemente. Ich habe aber 9 eingefügt und zweitens ........... die Materialnamen sehen ein bisschen komisch aus.

Ich zeige euch nun mal den Code für das, was passiert wenn der Benutzer den "Hinzufügen"-Knopf drückt. Vielleicht liegt da ja das Problem:

Quellcode

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
MATERIAL AktMaterial;
[b]char     MaterialName[32];[/b]
char     TextureShortName[24]; //Wurde bereits definiert
DWORD    DiffuseColor;         //Wurde bereits definiert
DWORD    AmbientColor;         //Wurde bereits definiert
DWORD    SpecularColor;        //Wurde bereits definiert
DWORD    EmissiveColor;        //Wurde bereits definiert

[b]MaterialName[0]=32;
SendDlgItemMessage(hDlg, ROM_MM_NAME, EM_GETLINE, 0, (LPARAM)(MaterialName));
if(MaterialListSearch(MaterialName)!=-1)
{
    MSGERR(NULL, "Ein Material mit diesem Namen ist schon vorhanden. Bitte ändern sie den Namen des Materials.");
    break;
}[/b]
AktMaterial.Material.Diffuse.r=(float)(GetRValue(DiffuseColor))/255;
AktMaterial.Material.Diffuse.g=(float)(GetGValue(DiffuseColor))/255;
AktMaterial.Material.Diffuse.b=(float)(GetBValue(DiffuseColor))/255;
AktMaterial.Material.Diffuse.a=(float)(SendDlgItemMessage(hDlg, ROM_MM_DIFFUSE_ALPHA_CHOOSE, TBM_GETPOS, 0, 0))/255;
AktMaterial.Material.Ambient.r=(float)(GetRValue(AmbientColor))/255;
AktMaterial.Material.Ambient.g=(float)(GetGValue(AmbientColor))/255;
AktMaterial.Material.Ambient.b=(float)(GetBValue(AmbientColor))/255;
AktMaterial.Material.Ambient.a=(float)(SendDlgItemMessage(hDlg, ROM_MM_AMBIENT_ALPHA_CHOOSE, TBM_GETPOS, 0, 0))/255;
AktMaterial.Material.Specular.r=(float)(GetRValue(SpecularColor))/255;
AktMaterial.Material.Specular.g=(float)(GetGValue(SpecularColor))/255;
AktMaterial.Material.Specular.b=(float)(GetBValue(SpecularColor))/255;
AktMaterial.Material.Specular.a=(float)(SendDlgItemMessage(hDlg, ROM_MM_SPECULAR_ALPHA_CHOOSE, TBM_GETPOS, 0, 0))/255;
AktMaterial.Material.Emissive.r=(float)(GetRValue(EmissiveColor))/255;
AktMaterial.Material.Emissive.g=(float)(GetGValue(EmissiveColor))/255;
AktMaterial.Material.Emissive.b=(float)(GetBValue(EmissiveColor))/255;
AktMaterial.Material.Emissive.a=(float)(SendDlgItemMessage(hDlg, ROM_MM_EMISSIVE_ALPHA_CHOOSE, TBM_GETPOS, 0, 0))/255;
AktMaterial.Material.Power=(float)(SendDlgItemMessage(hDlg, ROM_MM_SHARPNESS_CHOOSE, TBM_GETPOS, 0, 0)/255);
[b]strcpy(AktMaterial.MaterialName, MaterialName);[/b]
strcpy(AktMaterial.TextureName, TextureShortName);
[b]MaterialListInsert(&AktMaterial);
SendDlgItemMessage(hDlg, ROM_MM_LIST, LB_ADDSTRING, 0, (LPARAM)(MaterialName));[/b]
break;


Ich habe die Stellen die wichtig sind mal fett markiert!

9

24.02.2004, 01:38

Das kann nicht klappen :) Mich wunderts nur das dein Programm keinen Absturtz verursacht :) Du speicherst in deiner Liste die Daten mittels eines Zeigers. In deiner Case-Anweisung die für das Hinzufügen eines neuen Materials zuständig ist, erzeugt aber nur ein Temporäres Objekt. Dessen Adresse speicherst du in deiner Liste. Ich denke das ist auch der Grund warum es keinen Absturzt gibt ;D

Mach folgendes. Bau deine Liste so um das sie statt einen Zeiger auf die Daten, die Daten selber speicher. Deinen Funktionskopf kannst du lassen. Du kopierst die Daten einfach mit memcpy in den Datenblock deines Listen Eintrags.
Wichtig! Ich übernehme keinerlei Verantwortung für eventl. Datenverlust oder Schäden am Rechner ;D

big_muff

Alter Hase

Beiträge: 460

Wohnort: Schweiz

Beruf: Informatikstudent (4. Semester)

  • Private Nachricht senden

10

24.02.2004, 11:21

Es funktioniert jetzt. Vielen Dank an alle die mir dabei geholfen haben! :yelclap:
Hier noch mal de Code der neuen MaterialListInsert()-Funktion.
Ich habe die MATERIALLIST-Struktur so belassen wie sie oben ist (mit Zeiger auf die Daten):

Quellcode

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
//Einfügen am Anfang der Materialliste 
RESULT MaterialListInsert(MATERIAL *data) 
{ 
    MATERIALLIST *Newelement; //neues Listenelement 
    MATERIAL     *Material;

    Material = (MATERIAL*)malloc(sizeof(MATERIAL));

    //1. Fall: Einfügen in leere Liste 
    if(Materialliste->data == NULL) 
    { 
        memcpy(Material, data, sizeof(MATERIAL));
        Materialliste->data = Material; 
        return LIST_OK; 
    } 

    //2. Fall: Einfügen in nicht-leere Liste 
    Newelement = (MATERIALLIST*)malloc(sizeof(MATERIALLIST)); 

    //Fehler bei Initialisierung 
    if(Newelement == NULL) 
        return LIST_ERROR; 

    else 
    { 
        //Daten speichern, Zeiger setzen 
        memcpy(Material, data, sizeof(MATERIAL));
        Newelement->data = Material; 
        Newelement->next = Materialliste; 
        Materialliste = Newelement; 
        return LIST_OK; 
    } 
}

Werbeanzeige