Gamestudio Links
Zorro Links
Newest Posts
Change chart colours
by 7th_zorro. 05/11/24 09:25
Data from CSV not parsed correctly
by dr_panther. 05/06/24 18:50
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
2 registered members (AndrewAMD, Ayumi), 1,405 guests, and 4 spiders.
Key: Admin, Global Mod, Mod
Newest Members
Hanky27, firatv, wandaluciaia, Mega_Rod, EternallyCurious
19051 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Wie greife ich auf ein Struct in einem Struct zu? #138949
06/30/07 17:09
06/30/07 17:09
Joined: Jun 2002
Posts: 85
Deutschland
Clockmaster Offline OP
Junior Member
Clockmaster  Offline OP
Junior Member

Joined: Jun 2002
Posts: 85
Deutschland
Ich habe folgendes Problem. Ich habe eine Struktur definiert, die eine weitere Struktur erhalten hat.

Hier der Code:
Code:

typedef struct
{
char tex_name[35];
var tex_id;
var tile_count;
}TEX_LAYER;

typedef struct
{
TEX_LAYER texinfo[10];
char vorschau[20];
char format[5];
}TEX_INFO;

TEX_INFO tex_info;



Wie kann ich jetzt in tex_info auf texinfo[0].tex_name zugreifen? Habe folgendes Probiert:
tex_info.texinfo[0].tex_name und tex_info.texinfo[0]->tex_name aber der Compiler wirft mir immer ne Fehlermeldung aus. Wie funktioniert das?


Do Your Best.
Gib dein Bestes.
Re: Wie greife ich auf ein Struct in einem Struct [Re: Clockmaster] #138950
06/30/07 22:52
06/30/07 22:52
Joined: Jul 2001
Posts: 6,904
H
HeelX Offline
Senior Expert
HeelX  Offline
Senior Expert
H

Joined: Jul 2001
Posts: 6,904
Ein bißchen beeinflusst von Objektorientierter Programmierung, neige ich dazu, immer eigene Konstruktor-Funktionen zu bauen, die sich darum kümmern, dass eine Struktur _richtig_ initialisiert wird. Dazu gehört dann auch Unterstrukturen zu initialsieren, etc. Desweiteren ist es immer nützlich, Zeiger von Strukturen zu definieren und dann auf den Zeigern die richtigen Strukturen zu erzeugen. Eine Implementation, die funktioniert, wäre z.B.:

Code:
typedef struct
{
char tex_name[35];
var tex_id;
var tile_count;
} TEX_LAYER;

TEX_INFO* getTEX_LAYER()
{
TEX_LAYER* temp = (TEX_LAYER*)(malloc(sizeof(TEX_LAYER)));
//hier kannst du irgendwas initialisieren
return(temp);
}

typedef struct
{
TEX_LAYER* texinfo[10];
char vorschau[20];
char format[5];
} TEX_INFO;


TEX_INFO* getTEX_INFO()
{
TEX_INFO* temp = (TEX_INFO*)(malloc(sizeof(TEX_INFO)));
temp->texinfo = getTEX_LAYER();
//hier kannst du irgendwas initialisieren
return(temp);
}

void main ()
{
TEX_INFO* test123 = getTEX_INFO();
test123->texinfo->tex_id = 12345;
}



Folgendes Schema ist immer ganz nützlich, wenn man neue Strukturen einführt (zumindestens handhabe ich das so):

  • Struktur definiere und per typedef zu einem Datentyp machen
  • mindestens eine Konstruktorfunktion schreiben, die die Struktur komplett initialisiert und evtl. Unterstrukturen erzeugt und initialisiert.
  • Eventuell andere alternative Konstruktoren schreiben, die eine Parameterliste enthalten, um bestimmte Attribute zu initialisieren
  • Auch Destruktoren schreiben, die eine Struktur komplett entfernen. Wenn du außergewöhnliche Datentypen als Attribute hast (bitmaps, texts, andere eigene Strukturen), dann soll der Destruktor natürlich die ganz besonders anfassen. Ein simpler free Befehl hilft da nicht weiter (Unterschied flaches löschen und tiefes löschen!)
  • Getter und Setter Funktionen für die Variablen. Durch die -> Syntax kann man zwar bequem auf die Attribute zugreifen, aber eventuell ändert sich ja was in der Struktur oder in der Verarbeitung und dann sitzt man da und ändert das im gesamten Code ab. Gemäß des Sichtbarkeitsprinzips aus der OOP hab ich mir angewöhnt getter/setter Funktionen auch für meine C Strukturen zu schreiben. Vor allem weil man dann bei nicht trivialen Attributen gesondert darauf zugreifen/schreiben kann


In der Regel reicht dass dann aus, um einigermaßen sicher, ohne Compilerfehler und ohne Abstürze zur Laufzeit ordentlich zu arbeiten.

Re: Wie greife ich auf ein Struct in einem Struct [Re: Clockmaster] #138951
07/01/07 06:57
07/01/07 06:57
Joined: Jun 2002
Posts: 85
Deutschland
Clockmaster Offline OP
Junior Member
Clockmaster  Offline OP
Junior Member

Joined: Jun 2002
Posts: 85
Deutschland
Das sind super Tips HellX, werde versuchen mich daran zu halten. Habe auch schon daran gedacht gehabt mit Pointern in Structs zu arbeiten, wusste aber nicht wie ich das angehen sollte. Werde es auf jedenfall versuchen. Danke für deine Antwort.

Edit: Ah, hab in deinem kleinen Beispiel einen Fehler gefunden. Du erstellst im ersten Konstrukt eine Funktion, die ein TEX_INFO Objekt zurückgibt, muss es nicht ein TEX_LAYER Objekt sein?

Edit2: Du hast da jetzt geschrieben, das du eigene Destruktoren schreibst, weil free nicht wirklich effizient ist. Wie kann man das machen?

Edit3: Mir ist noch etwas aufgefallen, wo ich nochmal nachfragen muss. In der Struktur TEX_INFO ist ja ein Array von TEX_LAYER Objekten definiert. In deinen Konstrukt ist wird aber nur ein Objekt Initialisiert. Das kann man aber auch mit einer schleife machen, die alle Array Objekte initialisiert, oder?

Edit4: Das mit den Konstrukten funzt nicht. Wenn ich auf das Objekt in einer funjtion zugreifen möchte, stürzt das Programm ab ( also versucht auf einen leeren Pointer zuzugreifen. Habe aber das Konstrukt zugewiesen. Hier der Code:

Code:
  
typedef struct
{
char tex_name[35];
int tex_id;
int tile_count;
}TEX_LAYER;

typedef struct
{
TEX_LAYER* tex_layer[layer_count];
char vorschau[20];
char format[5];
}TEX_INFO;

TEX_LAYER* getTEX_LAYER()
{
TEX_LAYER* temp = (TEX_LAYER*)(malloc(sizeof(TEX_LAYER)));
temp->tex_name = " ";
temp->tex_id = 0;
temp->tile_count = 16;
return(temp);
}

TEX_INFO* getTEX_INFO()
{
var count_var = layer_count-1;
TEX_INFO* temp = (TEX_INFO*)(malloc(sizeof(TEX_INFO)));

while(count_var > 0)
{
temp->tex_layer[count_var] = getTEX_LAYER();
count_var -= 1;
}

temp->vorschau = "_vorschau";
temp->format = ".dds";

return(temp);
}

...
tex_info = getTEX_INFO();
...

//Und hier crash es und nicht nur da, bei allen zugriffen auf das Objekt crashed es.

function get_tex_enter( var x, var y, TEXT* text_p, TEX_INFO* tinfo, var index, STRING* enter, BMAP* pre_map, PANEL* layer_tx)
{
...
tinfo->tex_layer[index]->tex_id = index;
...
return;
}
...
//die aufgerufene function hat folgende Parameter:
get_tex_enter(920, 90, eingabetext,tex_info, button_number, eingabe, test, layer1);
...



Wie kann ich das besser machen?

Last edited by Clockmaster; 07/01/07 08:57.

Do Your Best.
Gib dein Bestes.
Re: Wie greife ich auf ein Struct in einem Struct [Re: Clockmaster] #138952
07/01/07 09:14
07/01/07 09:14
Joined: Jul 2001
Posts: 6,904
H
HeelX Offline
Senior Expert
HeelX  Offline
Senior Expert
H

Joined: Jul 2001
Posts: 6,904
Ahh! Sorry.. das kommt davon, wenn man nachts kurz vorm Einpennen aus dem Gedächtnis sourcecode schreibt

Quote:

Du erstellst im ersten Konstrukt eine Funktion, die ein TEX_INFO Objekt zurückgibt, muss es nicht ein TEX_LAYER Objekt sein?




Richtig!

Quote:

Du hast da jetzt geschrieben, das du eigene Destruktoren schreibst, weil free nicht wirklich effizient ist. Wie kann man das machen?





Indem du für jeden Datentyp eine Funktion dafür schreibst! Wenn ein struct Unterstructs besitzt, müssen die nämlich evtl. gesondert verarbeitet werden. Weil du nämlich in TEX_INFO ein array von pointern hast, würde free(..) nur die Pointer löschen - und nicht das, was dahinter steckt. Oder wenn du z.B. strings in einem struct hast, musst du ja str_remove aufrufen - da wird free(..) dann nicht das gewünschte Ergebnis bringen.

Code:
void freeTEX_LAYER(TEX_LAYER* _obj)
{
//TEX_LAYER hat nur Standardvariablen, also können wir free benutzen!!!
free(_obj);
}

void freeTEX_INFO (TEX_INFO* _obj)
{
static int i;
for (i = 0; i < 10; i++)
freeTEX_LAYER(_obj->texinfo[i]);

free(_obj);
}



Quote:

In der Struktur TEX_INFO ist ja ein Array von TEX_LAYER Objekten definiert. In deinen Konstrukt ist wird aber nur ein Objekt Initialisiert. Das kann man aber auch mit einer schleife machen, die alle Array Objekte initialisiert, oder?




Ja, sicher. Aber du brauchst dafür noch nicht einmal eine Schleife.

Code:
//Schleifenvariante:
TEX_INFO* getTEX_INFO()
{
TEX_INFO* temp = (TEX_INFO*)(malloc(sizeof(TEX_INFO)));

static int i;
for(i = 0; i < 10; i++)
temp->texinfo[i] = getTEX_LAYER();

//hier kannst du irgendwas initialisieren

return(temp);
}

//Mallocvariante:
TEX_INFO* getTEX_INFO()
{
TEX_INFO* temp = (TEX_INFO*)(malloc(sizeof(TEX_INFO)));

temp->texinfo = (TEX_INFO**)malloc(sizeof(TEX_INFO*[10]));

//hier kannst du irgendwas initialisieren

return(temp);
}



Die zweite Variante ist einerseits effizienter, weil du mit einem Schlag den Speicherbereich allozierst - aber dann verstößt du auch wieder gegen den Versuch, das alles mit Konstruktoren zu lösen. Du könntest dir jetzt eine Funktion schreiben, die das erledigt (somit wird dein Code auch schlanker, bzw. lesbarer (ich persönlich mag es nicht wenn Allozierungszeug irgendwo in meinem gamecode steht).

Nun, wenn du aber das Erzeugen eines Arrays von Objekten auslagerst und das mit einem Schlag mit malloc(..) machst, dann hast du das Problem, dass die Objekte nicht initialisiert werden. Diesen Code hast du aber bereits in der Funktion stehen, die EIN Objekt von TEX_LAYER erzeugt. Nun ist es am besten den Initialsierungscode auszulagern - sodass alle Konstruktoren diesen code sharen. Beispiel:

Code:
TEX_LAYER* initTEX_LAYER(TEX_LAYER* _obj)
{
//hier kannst du irgendwas initialisieren
return(_obj);
}

TEX_LAYER* getTEX_LAYER()
{
TEX_LAYER* temp = (TEX_LAYER*)(malloc(sizeof(TEX_LAYER)));
return(initTEX_LAYER(temp)); //initialisierung und Rückgabe
}

TEX_LAYER** getTEX_LAYER_array (int _size)
{
TEX_LAYER** temp = (TEX_LAYER**)(malloc(sizeof(TEX_LAYER*[_size])));

//initialisierung
static int i;
for (i = 0; i < _size)
initTEX_LAYER((TEX_LAYER*)(temp[i]));

return(temp);
}



Wie du nun einen Destruktor für das Löschen von Arrays von Objekten baust, kannst du nun von den Beispielen relativ einfach ableiten.

Kein Gewähr auf die Lauffähigkeit des codes bin grad aufgestanden

Viel Erfolg,
Christian

Re: Wie greife ich auf ein Struct in einem Struct [Re: HeelX] #138953
07/01/07 13:34
07/01/07 13:34
Joined: Jun 2002
Posts: 85
Deutschland
Clockmaster Offline OP
Junior Member
Clockmaster  Offline OP
Junior Member

Joined: Jun 2002
Posts: 85
Deutschland
Nochmals Danke für deine Hilfe. Leider habe ich trotzdem noch Probleme und sehe einfach noch nicht, warum sie da sind. Habe eigentlich alles soweit erstellt, wie du es mir erklärt hast. Doch wenn ich in anderen Funktionen versuche, den Objekt nen Wert zuzuweisen, crashed das Programm. Das Passiert ja normalerweise, wenn man versucht auf einen nicht initialisierten Zeiger zuzugreifen. Hier ist der Code:

Code:


typedef struct
{
char tex_name[35];
int tex_id;
int tile_count;
}TEX_LAYER;

typedef struct
{
TEX_LAYER* tex_layer[layer_count];
char vorschau[20];
char format[5];
var testvar;
}TEX_INFO;

TEX_LAYER* getTEX_LAYER()
{
TEX_LAYER* temp = (TEX_LAYER*)(malloc(sizeof(TEX_LAYER)));
temp->tex_name = " ";
temp->tex_id = 0;
temp->tile_count = 16;
return(temp);
}

TEX_INFO* getTEX_INFO()
{
var count_var = layer_count-1;
TEX_INFO* temp = (TEX_INFO*)(malloc(sizeof(TEX_INFO)));

static int i;
for(i = 0; i < 10; i++)
temp->tex_layer[count_var] = getTEX_LAYER();

temp->vorschau = "_vorschau";
temp->format = ".dds";
temp->testvar = 0;

return(temp);
}

...
TEX_INFO* tex_info = getTEX_INFO();
...

//Und hier crash es und nicht nur da, bei allen zugriffen auf das Objekt crashed es.

function get_tex_enter( var x, var y, TEXT* text_p, TEX_INFO* tinfo, var index, STRING* enter, BMAP* pre_map, PANEL* layer_tx)
{
...
tinfo->tex_layer[index]->tex_id = index;
...
return;
}
...
//die aufgerufene function hat folgende Parameter:
get_tex_enter(920, 90, eingabetext,tex_info, button_number, eingabe, test, layer1);
...




Ich weiss da einfach nicht, was da falsch sein soll.


Do Your Best.
Gib dein Bestes.

Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1