Newsgroup: it.comp.lang.c
Titolo: ritorna sempre NULL

Ciao ragazzi, sapete dirmi perché questa funzione mi ritorna sempre il
valore null? ci sarà un errore concettuale che ha del mostruoso... ma
proprio non lo vedo :-(
void* addnode(tnode* t, char* word, unsigned int nline)
{
 tnode *z;
 unsigned int cond;
 z=t;
 while(z!=NULL)
 {
  if((cond=strcmp(z->w, word))==0)
  {
   if(chkline(z->nlines, nline)==STATUS_OK)
    z->nlines[z->current++]=nline;
   else
    return (void*) STATUS_ALREADY_IN;
  }
  else if(cond<0)
   z=z->left;
  else
   z=z->right;
 }
 if(z==NULL)
 {
  z=(tnode*) malloc(sizeof(tnode));
  z->w=strdup(word);
  z->current=0;
  z->nlines[z->current]=nline;
  z->left=z->right=NULL;
 }
 return t;
}

}
Ci sono 2 cosette che non fanno.
Primo per una funzione del genere e' piu' appropriato passare un tnode
** t (sara' la root immagino), modificarla se e' il caso all'interno
della funzione e come valore di ritorno un int o simulare un boolean.
Questo ti semplifica la gestione dell'inserimento.
La seconda e' che fai:
z = t;
/* lavori solo su z senza mai alterare t */
ritorni t.
Questo funziona solo se t e' diverso da null, in tal caso alteri
l'albero senza cambiare la root, ma se t e' la root ed e' a NULL non
potra' mai essere modificato.
Questo si riconnette alla prima cosa che ti ho detto su come cambiare
il la sintassi della funzione.
-- 
Mox
"Trust the programmer."
"Don't prevent the programmer from doing what needs to be done."
"Keep the language small and simple."
"Provide only one way to do an operation."

ti ringrazio, ora funziona
ciao!

scusa se rompo ancora.. nn chiedermi il perché prima funzionava e adesso non
+, perché nn l'ho capito nemmeno io:-S cmq ho cercato di modificare la
funzione così che mi hai detto, ma non va uguale, ecco la funzione:
/* Funzione per modificare il nodo da inserire nell'albero */
int add(tnode **t, const char *w)
{
 if((*t)==NULL)
 {
  if(!((*t)=(tnode*) malloc(sizeof(tnode))))
   return STATUS_MEM_EXHAUSTED;
  (*t)->w=strdup(w);
  (*t)->counter=1;
  (*t)->left=(*t)->right=NULL;
  return STATUS_WORD_OK;
 }
 return STATUS_NODE_NOT_NULL;
}
/* Funzione per inserirlo nella posizione corretta */
int addnode(tnode **t, const char *word)
{
 int cond;
 tnode *z=(*t);
 if((*t)==NULL)
  if(add(t,word)==STATUS_WORD_OK)
  {
   (*t)=z;
   return STATUS_NODE_ADDED;
  }
 while((*t)!=NULL)
 {
  if((cond=strcmp((*t)->w,word))==0)
  {
   (*t)->counter++;
   (*t)=z;
   return STATUS_NODE_ADDED;
  }
  else if(cond<0)
   (*t)=(*t)->left;
  else
   (*t)=(*t)->right;
 }
 if((*t)==NULL)
 {
  cond=add(t,word);
  (*t)=z;
  if(cond==STATUS_WORD_OK)
   return STATUS_NODE_ADDED;
  return cond;
 }
 return STATUS_UNKNOWN_ERROR;
}
il problema è che se tento di stampare in ordine tutti gli elementi
dell'albero tramite una funzione del genere
void treeprint(tnode *t)
{
 if(t!=NULL)
 {
  printf("%s\n", t->w);
  treeprint(t->left);
  treeprint(t->right);
 }
}
mi stampa solo il primo elemento!! è come se ogni elemento fosse "isolato"
dagli altri... Se non ci fosse quel  " (*t)=z " il valore di (*t) diverrebbe
quello dell'ultimo elemento, per tanto ho memorizzato l'indirizzo del primo
elemento in Z e al termine di ogni inserimento l'ho ripristinato a T, ma
pare che non funzioni:-S in cosa sbaglio?
 vi ringrazio ancora!

}
Questa mi pare giusta.
Ho provato a seguire la tua funzione ma non ho capito come usi z e t:
se t e' il nodo che passi come root non dovresti mai toccarlo a meno
che non sia nullo, mentre z dovrebbe diventare una sorta di iteratore
per scorrere tutto l'albero.
Provo a riscriverla (okkio che non l'ho provata, e' un parziale
cut-n-paste da una funzione che uso per gestire l'ADT albero binario,
rimodificata per l'occasione), sequento i criteri che ti ho appena
detto.
Guardala e vedi se ti piace come e' strutturata.
/* inserimento in un albero binario di ricarca */
int insert (tnode **t, const char *word)
{
  int cond;
  tnode *i;
  if (*t == NULL) {
    /* inserisci al posto della root */
    if (add(t*, const char *word) == STATUS_WORD_OK)
      return 1;
    else
      return 0;
  }
  /* Entro qui se la root non e' nulla */
  else {
    /* posiziono l'iteratore sulla root */
    i = t;
    /* il ciclo verra' interrotto da una return prima o poi */
    for(;;) {
      cond = strcmp(i->w, word);
      /* duplicato: aggiorno il contatore */
      if (cond == 0) {
        i->conter++;
        return 1;
      }
 
      /*
       * word maggiore di i->w, quindi word va' messa
       * nel ramo destro
       */
      else if (cond < 0) {
        if (i->right == NULL) {
          if (add(i->right, const char *word) == STATUS_WORD_OK)
            return 1;
          else
            return 0;
        }
        else
          i = i->right;
      }
      /*
       * word minore di i->w, quindi word va' messa
       * nel ramo sinistro
       */
      else {
        if (i->left == NULL) {
          if (add(i->left, const char *word) == STATUS_WORD_OK)
            return 1;
          else
            return 0;
        }
        else
          i = i->left;
      }
    } /* fine del for(;;)



perché?:-O

perché?:-O
C'era un post di Kronos che lo spiegava molto bene, ti invito a
ricercarlo su google per leggerlo, io ti faccio un breve riassunto: il
C e' un linguaggio non fortemente tipato, ovvero esiste il concetto di
tipo, ma si puo' passare facilmente da un tipo all'altro.
Ovviamente il C fa' dei controlli sui tipi per evitare errori
grossolani, ma non puo' farli se tu usi il cast.
Quindi in tutti i casi in cui il cast non e' necessario (e i void *
vengono castati implicitamente a qualunque tipo), se lo usi uccidi
inutilmente il controlli sui tipi.


 C'era un post di Kronos che lo spiegava molto bene
il post d kronos č stato piuttosto esasustivo, non credevo che il C fosse
tanto flessibile con i tipi...
d'altro canto la tecnica del  "casting" me la ritrovo sempre nelle prime
pagine dei manuali, pensavo fosse praticamente indispensabile:-S
vabbč,  t ringrazio ancora, ciao!