Newsgroup: it.comp.programmare
Titolo: Funzione che non funziona (...come voglio io)

Ciao a tutto il NG.
Come da oggetto, ho scritto una funzione che non funziona come vorrei io...
e non riesco a capire perché...
Il suo compito è quello di calcolare le frequenze dei dati che si ripetono
all'interno di un file ( più facile a farsi che a dirsi ).
Il mio problema però è che da qualche parte mi perdo il valore del dato,
cioè memorizzo la frequenza con cui si ripete l'informazione ma perdo il
valore dell'informazione.
Ho allegato il file zippato è ridotto all'osso ( solo la funzione e un mini
'main()' per chi volesse magari compilarlo...) sicuro che sia una svista da
poco, ma per me così ovvia da non essere notata... =<
Grazie per l'attenzione, in attesa di una risp. ( lo so che siete tutti
bravi ;-)  )
------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#define NOMEFILE "Il nome del file per fare le prove"
struct albero { unsigned char dato;        // informazione principale
    unsigned long int frequenza;        //quante volte si ripete nel file
    albero *next;        //puntatore alla struttura successiva
    albero *sin;         // viene utilizzato in un'altra funzione
    albero *des;        //idem
     };
albero *root=NULL;        //puntatore all'inizio della coda
FILE fp1=NULL;  //puntatore al file da leggere;
int leggi_freq()
{
 albero *primo=NULL,*prec=NULL;
 unsigned char info=NULL;
 int fine=1,alt=0;
 do
 {
  fine=fread(&info,sizeof(info),1,fp1);
  if (fine!=0)
  {
   if (root==NULL)        //se la coda non esiste la creo
   {
    root=(albero *)malloc(sizeof(albero));
    if (root==NULL) return 21;
    root->dato=info;
    root->sin=NULL;
    root->des=NULL;
    root->next=NULL;
    root->frequenza=1;
   }
   else        //in caso contrario vedo se l'informazione è già incodata e
ne aumento la frequenza
   {
    primo=root;
    while (primo!=NULL)
    {
     prec=primo;
     if (primo->dato==info)
     {
      alt=1;
      primo->frequenza=(primo->frequenza)+1;
     }
     primo=primo->next;
    }
   }
   if (alt==0)        //se  non è incodata me ne occupo ora
   {
    primo=(albero *)malloc(sizeof(albero));
    if (primo==NULL) return 22;
    prec->next=primo;
    primo->next=NULL;
    primo->dato=info;
    primo->frequenza=1;
    primo->des=NULL;
    primo->sin=NULL;
   }
   else
    alt=0;
  }
 }while(fine!=0);        //abbiamo finito di leggere il file e la funzione
dovrebbe aver funzionato
 while(root!=NULL)        //questa è la verifica
 {
  printf("\n %u %u",root->frequenza,root->dato);        //ma quello che è
stato memorizzato è solo  il campo frequenza, mentre dato è sempre NULL...
  root=root->next;
 }
return 0;
}
void main()
{
 fp1=fopen(NOMEFILE,"wb");
 leggi_freq();
 fclose(fp1);
}

   printf("\n %u %u",root->frequenza,root->dato);        file://ma quello



Anch'io ho fatto cosě la prima volta senza nessun problema, xň non voglio
allocare la memoria in modo statico, ma dinamico... e poi cosě, faccio in
modo che la coda diventi pian piano un albero grazie agli altri 2
puntatori... senza sprechi
Grazie lo stesso...

 }
con queste modifiche funziona perfettamente su VC6 SP5

 il mode non e' "wb" ma "rb"!!!
Ragione, ma queste le ho aggiunte al volo, invece l' "alt=1", non me lo
ricordo, forse manca veramente ora prova.
Thanks
ps: ma non è che forse è un prob di compilatore??? borland c/c++ 3 per
dos...

Ho ricompilato con la modifica... infatti "alt=1;" non c'era, ed
effettivamente ci vuole... xò il problema persiste, ma è un prob di
compilazione della verifica penso.
Infatti ho fatto il debug ( ho perso un pomeriggio per capire come
funzionava il turbo debugger della borland ) e l'area di memoria root->dato
( man mano che root=root->next ) contiene un volore non nullo, ed esatto...
xò a me la funzione while stampa sempro degli 0 sulla 2° colonna, così l'ho
modifica in "printf("\n %c",root->dato)" e stampa i caratteri ascii
contenuti nel file.
Perchè "printf("\n %u %c",primo->frequenza,primo->dato)" non funziona???
ba...
Biez e grazie

      };
quei puntatori next, sin e des non mi piacciono molto: ho l'impressione che 
mischi impropriamente alberi e liste concatenate. Dico bene?
Ciao anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 ha scritto nel messaggio
news:9mgla2$2vm$1...@lacerta.tiscalinet.it...

io la printf non l'ho cambiata e funziona... i don't know! :-)
cmq l'importante e' che funzioni l'algo, il resto sono boiate.... magari
prova con un altro compilatore!
l'unica nota e' quella di Cuni, che ci fanno insieme una lista ed un
albero???
ciao by beppe


non so se e' del tutto corretto (forse vale solo per DOS 16bit), ma
forse perche' primo->frequenza e' un "unsigned long"
e quindi dovresti usare "%lu" nella printf.
Prova, ma declino ogni responsabilita'  :-))
ciao
donCiccio

 Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it
Ciao e grazie.
Ps: Ma sei della provincia di Messina, magari puoi risp. in privato a
ie...@tiscalinet.it

 donCiccio
Ciao e grazie


Ciao e di nuovo grazie

 ha scritto nel messaggio
news:2G4j7.38695$vC1.5...@news1.tin.it...
Avevi ragione... entrambi i compilatori fanno differenza tra %u e %lu , ma
anche stesso io ignoravo l'esistenza di %lu...
Thanks

Allora per chi ne vorrebbe sapere di più e per chi mi volesse aiutare ancora
ecco la funzione che fa diventare la lista un albero ( che dite funziona
solo per caso o sono stato bravo? ^____^ )
struct albero { unsigned char dato;
    unsigned long int frequenza;
    albero *next;        //questo lo sapete già
    albero *sin;        //foglia/nodo sinistro
    albero *des;        //foglia/nodo sinistro
     };
albero *root=NULL;        //puntatore all'inizio della lista ( globale )
int crea_albero()
{
 albero *pmin1,*pmin2,*corr,*prec=NULL,*prec1,*tmp;
 unsigned long int min1=NULL,min2=NULL;
 while ((root->next)->next!=NULL)        //fino a quando non restano 2
elementi
 {
  min1=min2=root->frequenza;        //inposto nelle variabili un valore di
comodo
  pmin1=pmin2=NULL;
  corr=root;
  while(corr!=NULL)        //inzio col cercare la frequenza + piccola
  {
   if (min1>=(corr->frequenza))        //faccio i mie confronti
 {
  min1=corr->frequenza;
  pmin1=corr;        //e la punto con pmin1
 }
   corr=corr->next;
  }
  corr=root;
  prec=NULL;
  while(corr!=NULL)        //ora cerco la seconda
  {
   if ((min2>=(corr->frequenza))&&(corr!=pmin1))        //ma non deve
coicidere con la 1° ^____^
   {
    min2=corr->frequenza;
    pmin2=corr;        //e la punto con pmin2
    prec1=prec;
   }
   prec=corr;
   corr=corr->next;
  }
  tmp=(albero *)malloc(sizeof(albero));
  if (tmp==NULL) return 41;
  if (pmin2==root)        // se pmin2 è all'inizio lo sgancio
   root=root->next;        //così
  else        //altrimenti
   prec1->next=pmin2->next;        //devo agganciare il precedente di pmin2
al successivo di pmin2
  tmp->frequenza=pmin1->frequenza;        //ora ricopio un elemento in
quello appena creato
  tmp->dato=pmin1->dato;
  tmp->next=NULL;
  tmp->des=pmin1->des;
  tmp->sin=pmin1->sin;
  pmin2->next=NULL;        //do una pulitina al secondo elemento
  pmin1->frequenza=(tmp->frequenza)+(pmin2->frequenza);        //memorizzo
nel primo elemento la somma delle frequenze( è ancora attaccato alla lista )
  pmin1->sin=tmp;        //ora gli attacco la nuova struttura ( elemento dei
più piccoli )
  pmin1->dato=NULL;        //imposto NULL come informazione ( tanto è
inutile... )
  pmin1->des=pmin2;        //ora gli attacco anche la seconda dei più
piccoli
 }        // quando esco sono rimasti solo due elementi nella lista
 tmp=(albero *)malloc(sizeof(albero));        //creo una nuova radice
 if (tmp==NULL) return 42;
 tmp->des=root->next;        //attacco alla nuova radice il successivo della
vecchia radice
 root->next=NULL;        //stacco il successivo della vecchia radice
 tmp->sin=root;        //attacco alla nuova radice quella vecchia
 tmp->dato=NULL;        //imposto come al solito come dato NULL
 tmp->frequenza=((tmp->sin)->frequenza)+((tmp->des)->frequenza);        //e
la somma delle frequenze
 root=tmp;        //e faccio si che root sia la nuova radice
 return 0;
}
Allora che ve ne pare? Vi è scappata qualche risata o può andare?

 
ie...@tiscalinet.it
sono di Genova, ma che c'entra?
E poi credo che possiamo tranquillamente continuare qua sul ng: siamo in 
topic, quindi non ci sono problemi, anzi, rivitalizziamo un po' il ng che 
da qualche tempo e' un po' moscio.
Ciao Anto


 Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it
Ciao

 nella prov. di ME
strano, il mio cognome ha origine bergamasche...


   while(corr!=NULL)        //inzio col cercare la frequenza + piccola
---- fine cut ----

 strano, il mio cognome ha origine bergamasche...
Non lo metto in dubbio, ma per esempio ho due colleghi ( anzi uno è un ex
collega) che vanno di
cognome Cuni


 Sarò cocciuto ma non mi va di sprecare di memoria.
allora usa l'array....


 Ciao Anto
Ciao ciao

 addirittura li farebbe diventare più grandi... )
non e' vero quello che affermi. Questo algoritmo funziona bene quando ci 
sono forti disparita' nelle frequenze dei singoli byte, non quando ci sono 
pochi byte usati.
Se non sbaglio questo e' l'algoritmo usato da tutti i software di 
compressione non data-loss, che operano molto bene su molti file diversi, 
senza richiedere che debbano usare solo pochi valori diversi per i byte...
Anto
PS: cmq questa discussione mi sta annoiando: se vuoi usare un metodo piu' 
difficile da implementare, non ortodosso, piu' lento e che potenzialmente 
usa piu' RAM fallo pure, cercavo solo di darti dei suggerimenti...


 usa piu' RAM fallo pure, cercavo solo di darti dei suggerimenti...
No problema, ma non eri tu quello che diceva che il ng era un po' moscio?
Cmq. non penso sia così ( ad eccezione per la lentezza, quello è vero... )

 Ma che cosa sarebbe un trie ( semplice curiosità, magari mi potrebbe
essere
Un trie (pronuncia "trai") e` una struttura dati che permette
veloci inserimenti, cancellazioni e ricerche di chiavi che
sono stringhe (senza chiavi duplicate), con tempi costanti
rispetto al numero di chiavi gia` presenti nella struttura.
(Eventualmente si possono memorizzare informazioni extra in
corrispondenza a ciascuna chiave).
E` in pratica un albero (il nome e` un gioco di parole fra
"tree" e "retrieval") che usa come indice ad ogni livello
il carattere corrente delle chiavi (stringhe) di indice.
In Python 2.2, ad esempio:
class trie:
    def __init__(self):
        self.radice = {}
    def __vai(self, parola, metodo, dato):
        dove = self.radice
        for carattere in parola:
            dove = metodo(dove, carattere, {})
        return metodo(dove, None, dato)
    def inserisci(self, parola, dato):
        return self.__vai(parola, dictionary.setdefault, dato)
    def trova(self, parola, default=None):
        return self.__vai(parola, dictionary.get, default)
Naturalmente l'approccio e` ancora piu` benefico in linguaggi
di basso livello, che NON dispongano gia` dei dictionary del
Python, in quanto permette di _implementare_ "dizionari" (con
la limitazione di usare stringhe distinte come chiavi) nei
termini dei tipici costrutti di basso livello come gli array.
Inoltre si presta ad ottimizzazione quando le chiavi siano
composte da un alfabeto limitato; ad esempio, considerando
solo lettere minuscole, bastano 26 nodi ad ogni livello,
ognuno composto da un record di due puntatori (puntatore al
prossimo livello, o 0 se non vi e` un prossimo livello;
puntatore al dato corrispondente alla chiave che qui
termina, o 0 se non vi e` alcuna chiave che qui termina).
Ancora una volta, si tratta di un approccio molto adatto
ad un linguaggio di basso livello, come assembler, C o
Pascal.
Alex

 > Ma che cosa sarebbe un trie ( semplice curiosità, magari mi potrebbe
ecc ecc
Grazie ma era stato già spiegato =D

 wrote in message
news:9n2ktv$545$1...@lacerta.tiscalinet.it...

*CON* un esempio completo e funzionante in 12 righe...?-)
Alex

 Alex
Ciao

 wrote in message
news:9n5j0l$280$1...@pegasus.tiscalinet.it...

Che cosa "si potrebbe fare lo stesso"?  Non seguo la frase...
Alex

*CON* un esempio completo e funzionante in 12 righe...?-)
Infatti il mio problema non è scorrere l'albero, ma memorizzarne il percorso
in buffer per poter scrivere a lunghezza fissa i dati sul disco.
Biez!