View Full Version : [c] scorrimento di liste tramite un iteratore- help!!
ho un problema nel far scorrere un elemento di tipo iteratore lungo una lista. l'elemento di tipo iteratore non è altro in pratica che pun puntatore alla lista.
le strutture sono queste:
struct NodoLista {
void *value;
struct NodoLista *next;
};
typedef struct NodoLista *list;
struct nodoIt {
list *punt;
};
typedef struct nodoIt *iterator;
tramite la funzione get_iterator si assegna a un iteratore una lista
iterator get_iterator(list l) {
iterator I;
I = malloc(sizeof(struct nodoIt));
if (!l) return NULL;
I->punt = l;
return I;
}
ora a me serve una funzione che faccia semplicemente scorrere l'iteratore di una posizione avanti. L'ho fatta in qyesto modo:
void *next(iterator i) {
list t = NULL;
t = (list *) i->punt;
if (t->next == NULL) return NULL;
t = t->next;
i->punt = t;
}
effettivamente la funzione mi fa scorrere l'iteratore avanti pero quando la lista finisce mi va in segmentation default.. come posso fare??
CIAO TECNOLOGIA INFORMATICA O INFROMATICA PROGETTO PROGRAMMAZIONE 2, TI VA MALE è?
abbastanza male via.. eheh
anche a vedere su twiki sta funzione next ha dato piu di qualche problemino...
mi sai dare qualche suggerimento?
Io avrei fatto così (codice non testato!):
typedef struct node
{
void *value;
struct node *next;
} NODE, *PNODE;
typedef struct
{
PNODE head;
} LIST, *PLIST;
typedef struct
{
PNODE node;
} ITERATOR, *PITERATOR;
PITERATOR getIterator (PLIST pl)
{
PITERATOR pi;
pi = (PITERATOR) malloc (sizeof (ITERATOR));
if (pi != NULL)
pi->node = pl->head;
return pi;
}
PNODE next (PITERATOR pi)
{
PNODE pn;
pn = pi->node;
if (pn != NULL)
pi->node = pn->next;
return pn;
}
Ci provo :D
Con l'istruzione t = (list *) i->punt; stai assegnando a t (di tipo list) il valore di una variabile di tipo puntatore a list.
Quindi se non sbaglio dovresti fare t=*(i->punt), e alla fine, al posto di i->punt = t; dovrebbe esserci i->punt = &t;
Inoltre la funzione next in un caso ritorna qualcosa (se t->next==NULL), nell'altro caso non ritorna niente!
Comunque non ho provato a farlo girare con queste modifiche... fammi sapere
ho provato a fare le modifiche che mi hai detto, che tra l'altro mi sebrano correttissime..la funzione diventa cosi..
void *next(iterator i) {
// sposta l'iteratore avanti di una posizione sulla lista
list t = NULL;
t=*(i->punt);
if (t->next == NULL) i->punt = NULL;
else {
t = t->next;
i->punt = &t;
}
}
pero in questo modo m va in segmentation default alla sua prima chiamata, mentre prima mi ci andava solo quando era a fine lista... :muro:
Io avrei fatto così (codice non testato!):
typedef struct node
{
void *value;
struct node *next;
} NODE, *PNODE;
typedef struct
{
PNODE head;
} LIST, *PLIST;
typedef struct
{
PNODE node;
} ITERATOR, *PITERATOR;
PITERATOR getIterator (PLIST pl)
{
PITERATOR pi;
pi = (PITERATOR) malloc (sizeof (ITERATOR));
if (pi != NULL)
pi->node = pl->head;
return pi;
}
PNODE next (PITERATOR pi)
{
PNODE pn;
pn = pi->node;
if (pn != NULL)
pi->node = pn->next;
return pn;
}
non posso cambiare i prototipi delle funzioni perche sono obbligato dalle specifiche del prof... :cry:
che stia sbagliando la get_itarator in principio? la cosa strana è che cmq finche non si è a fine lista l'iteratore pare funzionare.. è come se non mi riconoscesse il NULL finale...
in teoria per far spostare avanti di una posizione l'iteratore non basterebe fare la seguetne istruzione?
i->punt = (list *) (*(i->punt))->next;
ps: faccio il casting perche i->punt dev'essere di tipo list, o meglio puntatore a list..
dov'è che sbaglio??? :muro:
aaaaaa ho risolto.. la funzione next mi funziona..riesco a scorrere correttamente la lista fino alla fine e non avere errori..
sinceramente non ho ben capito come ho fatto perche la funzione non mi pare di averla cambiata.. (anche se dopo ore e un fine sett ad alto tasso alcolico, tutto è possibile)
:D
ora peròmi sorge un altro problema :(
nel main che fornisce il prof c'è un ciclo while fatto cosi:
i = get_iterator(l);
int cont=0;
/* deve stampare "a, b, c, d, e," */
while(has_next(i))
{
cont++;
char *s = (char *)next(i);
printf("%s,", s);
}
printf("\nlunghezza lista: %d\n",cont);
usando le mie funzioni, l'iteratore scorre correttamente la lista (la lunghezza fornita è quella giusta) pero non mi stampa i caratteri giusti (quelli nel commento, che sono inseriti sempre nel main) ma dei caratteri che non c'entrano nulla.
mi chiedo.. come puo funzionare quella conversione di stringhe? la next ritorna un void (obbligatorio),e il prof a priori non sa come è fatta la struttura dell'iteratore.. che nel mio caso è:
struct nodoIt {
list *punt;
};
typedef struct nodoIt *iterator;
il fatto è che se gli faccio ritornare il puntatore poi non mi funziona piu.. cmq essendo una funzione di tipo void è obbligatorio far ritornare qualcosa? io pensavo che fosse sufficente modificare il mio puntatore dentro alla funzione, in modo che la modifica fosse permanente.. senza pero tornare nulla con il return..
AnonimoVeneziano
06-05-2007, 23:27
void *next(iterator i) {
list t = NULL;
t = (list *) i->punt;
if (t->next == NULL) return NULL;
t = t->next;
i->punt = t;
}
Ma sta roba ti si compila??
t = (list *) i->punt; è sbagliato perchè t è di tipo list e i->punt è di tipo list , quindi dovrebbe essere :
t = i->punt;
Inoltre la tua funzione ha poco senso. Non si capisce se vuoi ritornare un valore di ritorno o meno .
il prototipo è del tipo :
void *next(iterator) , dal quale sembrerebbe tu voglia ritornare un tipo "puntatore a tipo sconosciuto" , il problema è che dentro la funzione tu non ritorni proprio nulla , tranne NULL in caso la lista passata alla funzione sia non valida. Inoltre dal fatto che tu passi un tipo "iterator" come parametro che è un puntatore a tipo "struct NodoIt" sembra che tu voglia modificare dalla funzione il valore dei campi della struct puntata da iterator e non ritornare un puntatore al nodo successivo (come invece il valore di ritorno farebbe intendere) .
La mia proposta per la nuova funzione next è :
void next(iterator i) {
if (i->punt == NULL) return;
i->punt = i->punt->next;
}
Ciao
PS : Ho appena letto che hai risolto e a quanto sembra la tua funzione deve ritornare qualcosa e sembra un char .... in tal caso bisogna cambiare un bel po' di cose. Guardando il main mi verrebbe in mente :
void *next(iterator i) {
void *p = NULL;
if (i->punt == NULL) return NULL;
p = i->punt->value;
i->punt = i->punt->next;
return p;
}
In pratica questa funzione restituisce il valore contenuto nel nodo corrente della lista e come SIDE EFFECT manda in avanti la lista di 1.
Ciao
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.