PDA

Visualizza la versione completa : [C] Strutture dati e loro allocazione


jacopos81
01-05-2007, 12:51
se io ho una struttura di questo tipo:



struct node {
char *name;
list children;
node_type type; // node_type un enum
int id;
};

typedef struct node *node;

e devo fare una funzione che crea un nuovo oggetto di tipo node, di cui ho il prototipo obligato cos:

int new_text_node(node *n, char *text, int x);

io l'ho fatta in questo modo:


int new_text_node(node *n, char *text, int x) {
node t = malloc(sizeof(struct node));
node t;
t->id = x;
t->name = (char *)malloc(sizeof(char) * strlen(text) + 1);
strcpy(t->name,text);
t->type = TEXT_NODE;
t->children = NULL;
*n = t;
return 0;
}

ma mi chiedo, l'allocazione di memoria per il nodo t, va fatta o non va fatta? ho provato in tutte e due i modi, e funziona in entrambe le situazioni...ma una delle due evidentemente sar sagliata...

Xaratroom
01-05-2007, 13:34
Un'oggetto si realizza con class e non con struct, una struttura solo un nuovo dato di tipo record...
Per quanto riguarda il codice, tu passi alla funzione un puntatore, allochi un nodo e il suo indirizzo lo assegni al puntatore..

jacopos81
01-05-2007, 13:46
Originariamente inviato da Xaratroom

Per quanto riguarda il codice, tu passi alla funzione un puntatore, allochi un nodo e il suo indirizzo lo assegni al puntatore..


quindi va bene no?

Xaratroom
01-05-2007, 18:37
No, t un puntatore a nodo...
Lo stesso puntatore che ti viene fornito come parametro, quindi devi allocare lo spazio di tipo node e assegnare il suo indirizzo a t...

Prova cos:

void new_text_node(node *t, char *text, int x)
{
t = malloc(sizeof(struct node));
t->id = x;
t->name = (char *)malloc(sizeof(char) * strlen(text) + 1);
strcpy(t->name,text);
t->type = TEXT_NODE;
t->children = NULL;
}

... Volendo puoi anche fare n = t (non *n = t se t un puntatore e se n punta a NULL)

jacopos81
02-05-2007, 11:34
se metto n = t e non *n = t non mi funziona. Mi va in segmentation default. Riporto la mia versione funzionante della funzione (di cui non posso cambiare il prototipo):


int new_text_node(node *n, char *text, int x) {
node t = malloc(sizeof(struct node));
t->id = x;
t->name = (char *)malloc(sizeof(char) * strlen(text) + 1);
strcpy(t->name,text);
t->type = TEXT_NODE;
int a = new_list(&t->children);
*n = t;
return 0;
}

oregon
02-05-2007, 11:57
Prima di entrare nel problema, mi sembra strana la dichiarazione della struttura

struct node ...

seguita da

typedef struct node *node;

ovvero dai alla struttura lo stesso nome del nuovo tipo di dato che e' il puntatore alla struttura stessa ... e questo non va bene ... non so quale compilatore te lo ha compilato ma, se lo ha fatto senza errori, ti consiglieri di passare ad un altro ...

Per il resto, se la funzione deve accettare un puntatore alla struttura, allora non puoi allocarla internamente e restituirne il puntatore perche' ci vorrebbe un doppio puntatore come parametro. Non ti resta quindi che allocarla esternamente e fornirne il puntatore alla funzione per l'assegnazione dei valori ...

jacopos81
02-05-2007, 12:16
Originariamente inviato da oregon
Prima di entrare nel problema, mi sembra strana la dichiarazione della struttura

struct node ...

seguita da

typedef struct node *node;

ovvero dai alla struttura lo stesso nome del nuovo tipo di dato che e' il puntatore alla struttura stessa ... e questo non va bene ... non so quale compilatore te lo ha compilato ma, se lo ha fatto senza errori, ti consiglieri di passare ad un altro ...



la struttura cosi definita dalle specifiche che ci da il prof.. forse lo fa per complicarci la vita..
per quanto riguarda la compilazione uso il classico gcc di linux..



Non ti resta quindi che allocarla esternamente e fornirne il puntatore alla funzione per l'assegnazione dei valori ...

non posso allocarla esternamente, perche vorrebbe dire allocarla nel main.. e anche il main fornito dal prof e non c' l'allocazione..
il prof nel main fa semplicemente:

node n;
int err = new_text_node(&n,"nodo"...... bla bla

oregon
02-05-2007, 12:21
Originariamente inviato da jacopos81
la struttura cosi definita dalle specifiche che ci da il prof.. forse lo fa per complicarci la vita..
per quanto riguarda la compilazione uso il classico gcc di linux..

No ... forse c'e' qualcosa che ti e' sfuggito perche' la struttura non si puo' chiamare node come il nuovo tipo di dato ...

Cioe'

struct node ...

e

typedef struct node *node

non e' compilabile ...!



non posso allocarla esternamente, perche vorrebbe dire allocarla nel main.. e anche il main fornito dal prof e non c' l'allocazione..
il prof nel main fa semplicemente:

node n;
int err = new_text_node(&n,"nodo"...... bla bla

Allora ... se node e' un "puntatore" alla struttura, allora stai passando il puntatore al puntatore e quindi l'allocazione interna alla funzione puo' andare ...

Se node e' invece, una struttura allocata staticamente, allora non esiste motivo di allocarla ...

Io penso che l'ipotesi corretta sia la prima, ma allora la dichiarazione della struttura e del tipo dati deve essere qualcosa come questa ...

struct _node ...

typedef struct _node *node;

In questo caso, tutto potrebbe funzionare ...

jacopos81
02-05-2007, 12:53
ti copio e incollo la struttura cosi come definita nelle specifiche:


typedef enum {
TEXT_NODE,
TAG_NODE
} node_type;

struct node {
char *name;
list children;
node_type type;
list attributes;
int id;
};

typedef struct node *node;

oregon
02-05-2007, 12:59
E allora ti copio-incollo l'errore di Visual C++

... error C2040: "node": "node *" differisce da "node" nei livelli dei riferimenti indiretti

e di DevCpp

... conflicting types for `typedef struct node*node'
... previous declaration as `struct node'

(per la verita', se il progetto e' in C e non in C++, il DevCpp lo compila ...)

:madai!?:

In ogni caso non mi sembra una buona idea chiamare la struttura e il tipo di dato "puntatore alla struttura" nella stessa maniera ...

Ovviamente ... se fosse cosi' invece

typedef struct {
...
} *node;

andrebbe bene ...

Loading