Newsgroup: it.comp.lang.c
Titolo: problema con lista

Salve a tutti
ho un problema e non riesco a capire dove stia l'inghippo. Se scrivo una
funzione che trova l' n-esimo elemento della lista e restituisce la
posizione all'interno della lista tipo:
int trova(simplistptr lis,int s)
{
int i=0;
simplistptr corr;
corr=lis;
while((curr->value!=n)||(curr!=NULL))
{curr=curr->next;
i++;}
return i;
}
il programma non va e sembra che il while non funzioni... sconfina oltre la
lista e non so per quale motivo.
Avete qualche idea?
Grazie
Ciao
Tony
*******************************
#include <stdio.h>
#include <stdlib.h>
struct nodolista {
 int value;
 struct nodolista *next;
};
typedef struct nodolista elemsim_list;
typedef elemsim_list *simplistptr;
typedef int boolean;
void crea_lista(simplistptr*);
void Vuota(simplistptr*);
boolean vuota(simplistptr);
simplistptr crea_nodo();
simplistptr singleton(int);
void catenate(simplistptr*,simplistptr*);
int size(simplistptr);
int abs(int);
simplistptr chop(simplistptr,int);
void stampalista(simplistptr);
int trova(simplistptr*, int);
void crea_lista(simplistptr*);
main()
{
simplistptr e=NULL,g=NULL;
crea_lista(&e);
stampalista(e);
printf("%d\n",size(e));
crea_lista(&g);
stampalista(g);
printf("%d\n",size(e));
catenate(&e,&g);
stampalista(g);
printf("%d\n",size(g));
boolean vuota(simplistptr a)
{
 return (a==NULL);
}
void Vuota(simplistptr *a)
{
 simplistptr temp=NULL,corr;
 corr=*a;
 if(!vuota(*a)) {
     while(corr!=NULL) {
     temp=corr;
     corr=corr->next;
     free(temp);}
 }
else return;
}
simplistptr crea_nodo()
{
 simplistptr p;
 p=(struct nodolista*)malloc(sizeof(struct nodolista));
 if(p==NULL) printf("Mem insuff.\n");
 return p;
}
simplistptr singleton(int val)
{
 if(val>-1) {
 simplistptr sin;
 sin=crea_nodo();
 sin->value=val;
 sin->next=NULL;
 return sin;}
 else return NULL;
}
void catenate(simplistptr *a,simplistptr *b)
{
 simplistptr curr;
 curr=*a;
 if(curr==NULL) {*a=*b; return;}
 while(curr->next!=NULL) curr=curr->next;
 curr->next=*b;
 *b=*a;
}
int size(simplistptr lis)
{
int i=0;
while(lis!=NULL) {lis=lis->next;i++;}
return i;
}
void stampalista(simplistptr a)
{
 simplistptr curr;
 curr=a;
 if(vuota(a)) printf("lista vuota\n");
 else { while(curr!=NULL){
  printf("%d ->",curr->value);
  curr=curr->next;
  } printf("\n");
 }
}
void crea_lista(simplistptr *e)
{
 simplistptr single;
 int valore;
 single=*e;
 while(valore!=-1)
 {printf("inserisci un intero diverso da -1\n");
 scanf("%d[\n^]",&valore);
 single=singleton(valore);
 catenate(e,&single);}
 return;
}

Tony wrote:
L'errore è nella condizione del while(): 
 deve essere (curr->value!=n && curr!=NULL) e non in OR.
Facendo un piccolo ragionamento con l'OR:
 finchè curr->value != n (ovvero non trovo l'elemento) ripeti while
 quando e sottolineo SOLO QUANDO il valore è n il while verifica che curr
 sia non NULL.
Spero sia abbastanza chiara come spiegazione, comunque basta ricordarsi
che le condizioni vengono valutate da sinistra a destra e secondo la
tabella di verità 1 OR DONTCARE restituisce sempre vero
Ciao
Luca


  sia non NULL.
Luca, non mi torna, l'OR dovrebbe garantire che quando almeno una delle due
condizioni non si verifica (cioč che non sia diverso da n o da NULL) allora
si esce dal loop,
ed č quello che voglio(vorrei): quando trovo n OR quando raggiungo la fine
allora esco dal loop.
Ciao
Tony

 while((curr->value!=n)||(curr!=NULL))
while(curr != NULL && curr->value != n)
La correzione di Luca era giusta (a parte l'ordine delle condizioni: 
essendo, per l'appunto, che vengono valutate da sinistra a destra, se io 
le mettessi nell'ordine inverso rischio di valutare un curr->value con 
curr=NULL, che mi da un undefined behaviour, ovvero segfault ;D)
Il tuo commento alla sua risposta:
"l'OR dovrebbe garantire che quando almeno una delle due
condizioni non si verifica (cioè che non sia diverso da n o da NULL) 
allora si esce dal loop"
non e' giusto - l'or mi dice: se (e solo se) almeno una delle condizioni 
*si verifica*, allora *continuo*. Se ribalti la frase, devi ricordare 
che gli "almeno" diventano "tutti", come insegna la logica del 
prim'ordine (la negazione di un quantificatore esistenziale e' un 
universale) :); e quindi ho: se (e solo se) *tutte* le condizioni *non 
si verificano*, allora *smetto*. Perche' tutte le condizioni non si 
verifichino, devo avere che curr==NULL e che curr->value==n... una 
coppia non raccomandabile da valutare assieme :)
Detta piu' semplicemente: la condizione che tu hai scritto dice che il 
ciclo va avanti sia quando curr non e' NULL (vero sempre tranne che per 
l'ultimo elemento), sia quando curr->value non e' n. Ora, ho sempre, 
tranne che per l'ultimo elemento, che curr!=NULL, e quindi vado _sempre_ 
avanti fino alla fine, perche' almeno una delle due condizioni e' 
rispettata (all'OR basta una delle due condizioni) - e questo e' gia' 
sbagliato. Per di piu', arrivato in fondo, non ho piu' che curr!=NULL, 
pero' a questo punto mi rimane l'altra condizione. Il programma calcola 
curr->value (che gia' di per se' e' quasi assicurazione di un 
segfault/errore nel programma/quelchee' nel tuo SO); e dato che va a 
pigliare dati a casaccio, molto probabilmente questo valore non sara' n, 
ed andro' ancora oltre, causando dei bei pasticci.
Spero che la mia prolissa spiegazione sia ok per te ;)
-- 
/**
  * Mattia Belletti - Undergraduate student @ 
cs.unibo.it
  * ICQ: 33292311   - email: 
mbel...@cs.unibo.it
  * IRC: BluShine   - site(s): 
http://cs.unibo.it/~mbellett
  * Linux registered user 299762 @ Linux registered machine 213003
  */

> Spero che la mia prolissa spiegazione sia ok per te ;)
Sě grazie, ho risolto.
Ciao
Tony

Mattia Belletti wrote:
In effetti è vero... basta una condizione...
stavo pensando a chissà cosa quando l'ho scritto...
Luca
