Help for my code

T

TC

Hi.
I write a program in c language that read a text file and extrapolate
the word. for all word the program calculate the number of the times
that word is present in the text.
The problem is the REALLOC that on my pc at times it produces error.
Someone can help me for this error?
Thank you


/*Inclusione librerie*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>

/*Definizione della strutura Elemento*/
typedef struct
{
char *parola;
unsigned int freq;
}Elem;

/*Definizione della lista delle parole trovate*/
struct Albero
{
Elem Elemento;
struct Albero *s;
struct Albero *d;
};

/*Definizione variabili*/
//Albero ordinato per alfabeto
struct Albero *treeA = NULL;
//Albero ordinato per frequenze
struct Albero *treeF = NULL;

unsigned int count = 0;

/*Definizione funzioni*/
//Funzione di scansione del file costruzione delle parole e chiamata
//della funzione di inseriento nell'albero ordinato per alfabeto
void Scansione(FILE *pf);
//Aggiungi nodo all'albero ordinato per alfabeto
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola);
//Stampa albero
void Print(struct Albero *nodo);
//Crea un nuovo albero ordinato per frequenza utilizzando come sorgente
l'albero
//ordinato per alfabeto
void CreaAlberoF(struct Albero *sorg);
//Aggiunge un nuovo nodo all'albero ordinato pre frequenze copiando i
valori dal
//nodo passato come sorgente
struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest);


main (void)
{
int fOK;
//Nome del file di testo
char *NF;
//Puntatore al file
FILE *pf;
/*MAIN*/
printf("\n Avvio del programma \n");

do
{
printf("\nInserire il nome del file di testo che si desidera
utilizzare (Esempio: Testo.txt) \n");

NF = (char*)malloc(sizeof (char));
NF[0]='\0';

do
{
scanf("%s",NF); //Lettura del nome del file
}
while (strlen(NF)<4);

pf=fopen(NF, "r"); //Apertura del file in modalità di lettura

//Controllo apertura del file
if (pf==NULL)
{
//Restituzione del messaggio di errore in caso di mancata
apertura
perror("ERRORE nell'apertura del file");
fOK = 0;
}
else
{
fOK = 1;
}
}while(fOK != 1);

printf("\n\n");

int iScelta = 0;

do
{
/*Menù*/
printf("\n 1- Scansione del file di testo \n");
printf("\n 2- Creazione del file delle parole ordinato per
frequenza \n");
printf("\n 3- Stampa a video del file delle parole ordinato per
frequenza \n");
printf("\n 4- Stampa a video del file delle parole ordinato per
ordine alfabetico \n");
printf("\n 5- Esci \n");

do
{
scanf("%d", &iScelta);
}while(iScelta!= 1 && iScelta!= 2 && iScelta!= 3 && iScelta!= 4
&& iScelta!= 5);

//Blocco di scelta
switch(iScelta)
{
case (1):
Scansione(pf);
printf("\n Scansione EFFETTUATA! \n");
break;
case (2):
CreaAlberoF(treeA);
printf("\n Lista delle parole ordinata per
frequenza creata! \n");
break;
case (3):
count=0;
Print(treeF);
break;
case(4):
count=0;
Print(treeA) ;
break;
default:
exit(0);
}
}while(iScelta!=5);
}

/*Funzione che effettua la scansione del file per individuare le parole
e richiama la funzione di aggiunta di un nuovo elemento all'albero
alfabeto*/
void Scansione (FILE *pf)
{
char *parola; //Parola
char c; //Variabile per la letura dei caratteri dal file di testo
char *carattere; //Variabile utilizzatata per la concatenazione
int lung; //Lunghezza della parola

//Istanziazione e inizializzazione della variabile carattere
carattere = (char*)malloc(2*sizeof(char));
carattere[0]='\0';

//Istanziazione e inizializzazione della variabile parola
//parola = (char*)malloc(1*sizeof(char));
// parola[0]='\0';

while(!feof(pf)) //Ripete fino alla fine del file
{

fread(&c,1*sizeof(char),1,pf); //Lettura del carattere
printf("\n carattere letto->%c",c);
//Controllo se il carattere è presente nell'alfabeto
if (isalpha(c))
{
printf("\n carattere valido");
//Calcolo della lunghezza della parola
lung=strlen(parola);
//Assgnamento del valore alla variabile carattere
carattere[0]=c;
carattere[1]='\0';
parola=(char*)realloc(parola,(lung+1)*sizeof(char));
//lowercase
*carattere = tolower(*carattere);
//Concatenzazione dei caratteri per formare la parola
parola = strcat(parola,carattere);
printf("\n valore attuale di parola->%s",parola);
}
else
{
//Inserimento della parola
if ((parola[0]!='\0'))
{
//printf("%s",parola);
//Richiamo della funzione che aggiunge le parole
nell'albero
//ordianto per alfabeto
if (treeA == NULL)
{
//Aggionamemto della radice
treeA = AggNodo_TreeA(treeA,parola);
}
else
{
AggNodo_TreeA(treeA,parola);
}
//Reinizializzazione della variabile parola
//parola=NULL;
parola=(char*)realloc(parola,sizeof(char));
parola[0]='\0';
}
}
}
//Chiusura file
fclose(pf);
}

//Funzione di aggiunta di un nodo all'albero
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola)
{
if (nodo == NULL)
{
//Creazione nuovo nodo dell'albero
nodo = (struct Albero*) malloc(sizeof(struct Albero));
//Imposto il valore dei puntatori ai nodi figli
nodo->d = NULL;
nodo->s = NULL;
//Impostazione della frequenza
nodo->Elemento.freq = 1;
//Allocazione della memoria per la stringa contenete la parola
if(!(nodo->Elemento.parola =
(char*)malloc(strlen(parola)*sizeof(char))))
{
printf("\n Errore di allocazione della memoria.\n");
}
//Copia della stringa
strcpy(nodo->Elemento.parola,parola);
//Se è il primo inserimento aggiorno il puntatore alla radice
dell'albero
printf("\n Parola inserita nel nodo: %s",nodo->Elemento.parola);
}
else
{
//Variabile che restituisce il valore della comparazione parola
int conf;
//Comparazione della parola
conf = strcmp(nodo->Elemento.parola,parola);
printf("\n S1: %s S2: %s Ris: %d",nodo->Elemento.parola,parola,conf);
//printf("%d",conf);

switch(conf)
{
case (1):
nodo->s = AggNodo_TreeA(nodo->s,parola);
break;
case (-1):
nodo->d = AggNodo_TreeA(nodo->d,parola);
break;
default:
//Se le parole sono uguali incremento il valore della
frequenza
nodo->Elemento.freq = nodo->Elemento.freq + 1 ;
}
}
return nodo;
}

//Funzione di stampa dell'albero passato in input
void Print(struct Albero *nodo)
{

if (nodo != NULL)
{

//Richiamo della funzione sul ramo sinistro
Print(nodo->s);

if (count == 10 )
{
printf("\n Premere un tasto per continuare...\n");
getchar();
count = 0;
}
else
{
count++;
}
//Stampa della parola
printf("\n PAROLA: %s ", nodo->Elemento.parola);
printf(" FREQUENZA: %d ", nodo->Elemento.freq);

//Richiamo della funzione sul ramo destro
Print(nodo->d);
}
}

struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest)
{
if (dest == NULL)
{
//Creazione nuovo nodo dell'albero
dest = (struct Albero*) malloc(sizeof(struct Albero));
//Imposto il valore dei puntatori ai nodi figli
dest->d = NULL;
dest->s = NULL;
//Impostazione della frequenza
dest->Elemento.freq = sorg->Elemento.freq;
//Allocazione della memoria per la stringa contenete la parola
dest->Elemento.parola =
(char*)malloc(sizeof(sorg->Elemento.parola));
//Copia della stringa
strcpy(dest->Elemento.parola,sorg->Elemento.parola);
}
else
{
//Comparazione Frequenza
if ( dest->Elemento.freq < sorg->Elemento.freq)
{
dest->s = AggNodo_TreeF(sorg,dest->s);
}
else
{
dest->d = AggNodo_TreeF(sorg,dest->d);
}
}
return dest;
}

/*Funzione che crea l'abero delle frequenze partendo dall'abero ordinato per
alfabeto passato in input*/
void CreaAlberoF(struct Albero *sorg)
{
struct Albero *nodoprec;
if (sorg != NULL)
{
CreaAlberoF(sorg->s);
if (treeF == NULL)
{
treeF = AggNodo_TreeF(sorg, treeF);
}
else
{
AggNodo_TreeF(sorg, treeF);
}
CreaAlberoF(sorg->d);
}
}
 
A

AK

TC said:
Hi.
I write a program in c language that read a text file and extrapolate
the word. for all word the program calculate the number of the times
that word is present in the text.
The problem is the REALLOC that on my pc at times it produces error.
Someone can help me for this error?
Thank you


/*Inclusione librerie*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>

/*Definizione della strutura Elemento*/
typedef struct
{
char *parola;
unsigned int freq;
}Elem;

/*Definizione della lista delle parole trovate*/
struct Albero
{
Elem Elemento;
struct Albero *s;
struct Albero *d;
};

/*Definizione variabili*/
//Albero ordinato per alfabeto
struct Albero *treeA = NULL;
//Albero ordinato per frequenze
struct Albero *treeF = NULL;

unsigned int count = 0;

/*Definizione funzioni*/
//Funzione di scansione del file costruzione delle parole e chiamata
//della funzione di inseriento nell'albero ordinato per alfabeto
void Scansione(FILE *pf);
//Aggiungi nodo all'albero ordinato per alfabeto
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola);
//Stampa albero
void Print(struct Albero *nodo);
//Crea un nuovo albero ordinato per frequenza utilizzando come sorgente
l'albero
//ordinato per alfabeto
void CreaAlberoF(struct Albero *sorg);
//Aggiunge un nuovo nodo all'albero ordinato pre frequenze copiando i
valori dal
//nodo passato come sorgente
struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest);


main (void)
{
int fOK;
//Nome del file di testo
char *NF;
//Puntatore al file
FILE *pf;
/*MAIN*/
printf("\n Avvio del programma \n");

do
{
printf("\nInserire il nome del file di testo che si desidera
utilizzare (Esempio: Testo.txt) \n");

NF = (char*)malloc(sizeof (char));
NF[0]='\0';

do
{
scanf("%s",NF); //Lettura del nome del file
}
while (strlen(NF)<4);

pf=fopen(NF, "r"); //Apertura del file in modalità di lettura

//Controllo apertura del file
if (pf==NULL)
{
//Restituzione del messaggio di errore in caso di mancata
apertura
perror("ERRORE nell'apertura del file");
fOK = 0;
}
else
{
fOK = 1;
}
}while(fOK != 1);

printf("\n\n");

int iScelta = 0;

do
{
/*Menù*/
printf("\n 1- Scansione del file di testo \n");
printf("\n 2- Creazione del file delle parole ordinato per
frequenza \n");
printf("\n 3- Stampa a video del file delle parole ordinato per
frequenza \n");
printf("\n 4- Stampa a video del file delle parole ordinato per
ordine alfabetico \n");
printf("\n 5- Esci \n");

do
{
scanf("%d", &iScelta);
}while(iScelta!= 1 && iScelta!= 2 && iScelta!= 3 && iScelta!= 4
&& iScelta!= 5);

//Blocco di scelta
switch(iScelta)
{
case (1):
Scansione(pf);
printf("\n Scansione EFFETTUATA! \n");
break;
case (2):
CreaAlberoF(treeA);
printf("\n Lista delle parole ordinata per
frequenza creata! \n");
break;
case (3):
count=0;
Print(treeF);
break;
case(4):
count=0;
Print(treeA) ;
break;
default:
exit(0);
}
}while(iScelta!=5);
}

/*Funzione che effettua la scansione del file per individuare le parole
e richiama la funzione di aggiunta di un nuovo elemento all'albero
alfabeto*/
void Scansione (FILE *pf)
{
char *parola; //Parola
char c; //Variabile per la letura dei caratteri dal file di testo
char *carattere; //Variabile utilizzatata per la concatenazione
int lung; //Lunghezza della parola

//Istanziazione e inizializzazione della variabile carattere
carattere = (char*)malloc(2*sizeof(char));
carattere[0]='\0';

//Istanziazione e inizializzazione della variabile parola
//parola = (char*)malloc(1*sizeof(char));
// parola[0]='\0';

while(!feof(pf)) //Ripete fino alla fine del file
{

fread(&c,1*sizeof(char),1,pf); //Lettura del carattere
printf("\n carattere letto->%c",c);
//Controllo se il carattere è presente nell'alfabeto
if (isalpha(c))
{
printf("\n carattere valido");
//Calcolo della lunghezza della parola
lung=strlen(parola);
//Assgnamento del valore alla variabile carattere
carattere[0]=c;
carattere[1]='\0';
parola=(char*)realloc(parola,(lung+1)*sizeof(char));
//lowercase
*carattere = tolower(*carattere);
//Concatenzazione dei caratteri per formare la parola
parola = strcat(parola,carattere);
printf("\n valore attuale di parola->%s",parola);
}
else
{
//Inserimento della parola
if ((parola[0]!='\0'))
{
//printf("%s",parola);
//Richiamo della funzione che aggiunge le parole
nell'albero
//ordianto per alfabeto
if (treeA == NULL)
{
//Aggionamemto della radice
treeA = AggNodo_TreeA(treeA,parola);
}
else
{
AggNodo_TreeA(treeA,parola);
}
//Reinizializzazione della variabile parola
//parola=NULL;
parola=(char*)realloc(parola,sizeof(char));
parola[0]='\0';
}
}
}
//Chiusura file
fclose(pf);
}

//Funzione di aggiunta di un nodo all'albero
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola)
{
if (nodo == NULL)
{
//Creazione nuovo nodo dell'albero
nodo = (struct Albero*) malloc(sizeof(struct Albero));
//Imposto il valore dei puntatori ai nodi figli
nodo->d = NULL;
nodo->s = NULL;
//Impostazione della frequenza
nodo->Elemento.freq = 1;
//Allocazione della memoria per la stringa contenete la parola
if(!(nodo->Elemento.parola =
(char*)malloc(strlen(parola)*sizeof(char))))
{
printf("\n Errore di allocazione della memoria.\n");
}
//Copia della stringa
strcpy(nodo->Elemento.parola,parola);
//Se è il primo inserimento aggiorno il puntatore alla radice
dell'albero
printf("\n Parola inserita nel nodo: %s",nodo->Elemento.parola);
}
else
{
//Variabile che restituisce il valore della comparazione parola
int conf;
//Comparazione della parola
conf = strcmp(nodo->Elemento.parola,parola);
printf("\n S1: %s S2: %s Ris: %d",nodo->Elemento.parola,parola,conf);
//printf("%d",conf);

switch(conf)
{
case (1):
nodo->s = AggNodo_TreeA(nodo->s,parola);
break;
case (-1):
nodo->d = AggNodo_TreeA(nodo->d,parola);
break;
default:
//Se le parole sono uguali incremento il valore della
frequenza
nodo->Elemento.freq = nodo->Elemento.freq + 1 ;
}
}
return nodo;
}

//Funzione di stampa dell'albero passato in input
void Print(struct Albero *nodo)
{

if (nodo != NULL)
{

//Richiamo della funzione sul ramo sinistro
Print(nodo->s);

if (count == 10 )
{
printf("\n Premere un tasto per continuare...\n");
getchar();
count = 0;
}
else
{
count++;
}
//Stampa della parola
printf("\n PAROLA: %s ", nodo->Elemento.parola);
printf(" FREQUENZA: %d ", nodo->Elemento.freq);

//Richiamo della funzione sul ramo destro
Print(nodo->d);
}
}

struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest)
{
if (dest == NULL)
{
//Creazione nuovo nodo dell'albero
dest = (struct Albero*) malloc(sizeof(struct Albero));
//Imposto il valore dei puntatori ai nodi figli
dest->d = NULL;
dest->s = NULL;
//Impostazione della frequenza
dest->Elemento.freq = sorg->Elemento.freq;
//Allocazione della memoria per la stringa contenete la parola
dest->Elemento.parola =
(char*)malloc(sizeof(sorg->Elemento.parola));
//Copia della stringa
strcpy(dest->Elemento.parola,sorg->Elemento.parola);
}
else
{
//Comparazione Frequenza
if ( dest->Elemento.freq < sorg->Elemento.freq)
{
dest->s = AggNodo_TreeF(sorg,dest->s);
}
else
{
dest->d = AggNodo_TreeF(sorg,dest->d);
}
}
return dest;
}

/*Funzione che crea l'abero delle frequenze partendo dall'abero ordinato per
alfabeto passato in input*/
void CreaAlberoF(struct Albero *sorg)
{
struct Albero *nodoprec;
if (sorg != NULL)
{
CreaAlberoF(sorg->s);
if (treeF == NULL)
{
treeF = AggNodo_TreeF(sorg, treeF);
}
else
{
AggNodo_TreeF(sorg, treeF);
}
CreaAlberoF(sorg->d);
}
}

Please translate your comments in English would you?
 
F

Flash Gordon

TC said:
Hi.
I write a program in c language that read a text file and extrapolate
the word. for all word the program calculate the number of the times
that word is present in the text.
The problem is the REALLOC that on my pc at times it produces error.
Someone can help me for this error?
Thank you


/*Inclusione librerie*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

This is not a standard header. The correct header for malloc and friends
is stdlib.h, so I suggest getting rid of whatever documentation you've
got that suggests using malloc.h
#include <ctype.h>

/*Definizione della strutura Elemento*/
typedef struct
{
char *parola;
unsigned int freq;
}Elem;

/*Definizione della lista delle parole trovate*/
struct Albero
{
Elem Elemento;
struct Albero *s;
struct Albero *d;
};

/*Definizione variabili*/
//Albero ordinato per alfabeto

// style comments are not valid in C89, which is the only standard most
compilers implement fully. Also, they do not survive line wrapping so
even when using C99 (which does support them) they are inadvisable for
postings to Usenet.
struct Albero *treeA = NULL;
//Albero ordinato per frequenze
struct Albero *treeF = NULL;

unsigned int count = 0;

/*Definizione funzioni*/
//Funzione di scansione del file costruzione delle parole e chiamata
//della funzione di inseriento nell'albero ordinato per alfabeto
void Scansione(FILE *pf);
//Aggiungi nodo all'albero ordinato per alfabeto
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola);
//Stampa albero
void Print(struct Albero *nodo);
//Crea un nuovo albero ordinato per frequenza utilizzando come sorgente
l'albero
//ordinato per alfabeto
void CreaAlberoF(struct Albero *sorg);
//Aggiunge un nuovo nodo all'albero ordinato pre frequenze copiando i
valori dal

See what I mean about // style comments being a pain on Usenet?
//nodo passato come sorgente
struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest);


main (void)
{
int fOK;
//Nome del file di testo
char *NF;

Please don't use all upper case names for variables. By convention all
upper case names are only used for macros and possibly the constants
defined by an enum.
//Puntatore al file
FILE *pf;
/*MAIN*/
printf("\n Avvio del programma \n");

do
{
printf("\nInserire il nome del file di testo che si desidera
utilizzare (Esempio: Testo.txt) \n");

NF = (char*)malloc(sizeof (char));

Don't cast the return value of malloc. In fact, don't cast EVER unless
you know EXACTLY why the cast is required. The compiler complaining at
you is NOT a valid reason for casting, it means you need to find out WHY
the compiler is complaining.

Note, I'm not saying don't ever use a cast, sometimes they are required,
only that you should not use them UNLESS you know why it is required and
what effect it will have.

The generally preferred form for using malloc around here is:
NF = malloc(N * sizeof *NF);
where N is the number of items you want NF to point to. However, in your
case NF is a char pointer, so with N=1 (as in your case) this allocate
enough space for exactly ONE character. Since all strings are terminated
by a nul character, this means there is only enough space for an empty
string.

Also check the return value, malloc CAN fail.
NF[0]='\0';

do
{
scanf("%s",NF); //Lettura del nome del file

Don't EVER use %s in scanf, always specify the maximum number of
characters to be read. In any case, as stated above, the space pointed
to by NF is not large enough for ANY non-empty string, and scanf won't
change that.

In any case, you would be best using a fixed length array and fgets, but
remember to check the return value of fgets (as you should have done
with scanf) and also note what fgets does if the line is too long and
what it does if the line fits.
}
while (strlen(NF)<4);

That, IMHO, is a stupid check. I regularly use files named t or t.t when
I want to create a file for testing purposes.
pf=fopen(NF, "r"); //Apertura del file in modalità di lettura

//Controllo apertura del file
if (pf==NULL)
{
//Restituzione del messaggio di errore in caso di mancata
apertura
perror("ERRORE nell'apertura del file");
fOK = 0;
}
else
{
fOK = 1;
}
}while(fOK != 1);

That is a bad habit. In general any non-zero value is treated as true in C.
} while (!fOK);
printf("\n\n");

int iScelta = 0;

do
{
/*Menù*/
printf("\n 1- Scansione del file di testo \n");
printf("\n 2- Creazione del file delle parole ordinato per
frequenza \n");
printf("\n 3- Stampa a video del file delle parole ordinato per
frequenza \n");
printf("\n 4- Stampa a video del file delle parole ordinato per
ordine alfabetico \n");
printf("\n 5- Esci \n");

You might as well use puts, although there is nothing technically wrong
with printf here.
do
{
scanf("%d", &iScelta);

Check the return value of scanf. Also, read up on what will happen if
the user enters something other than a number.
}while(iScelta!= 1 && iScelta!= 2 && iScelta!= 3 && iScelta!= 4
&& iScelta!= 5);

//Blocco di scelta
switch(iScelta)
{
case (1):
Scansione(pf);
printf("\n Scansione EFFETTUATA! \n");
break;
case (2):
CreaAlberoF(treeA);
printf("\n Lista delle parole ordinata per frequenza
creata! \n");
break;
case (3):
count=0;
Print(treeF);
break;
case(4):
count=0;
Print(treeA) ;
break;
default:
exit(0);
}
}while(iScelta!=5);
}

/*Funzione che effettua la scansione del file per individuare le parole
e richiama la funzione di aggiunta di un nuovo elemento all'albero
alfabeto*/
void Scansione (FILE *pf)
{
char *parola; //Parola

What is the point of a comment that just restates the name of a variable?
char c; //Variabile per la letura dei caratteri dal file di testo
char *carattere; //Variabile utilizzatata per la concatenazione
int lung; //Lunghezza della parola

//Istanziazione e inizializzazione della variabile carattere
carattere = (char*)malloc(2*sizeof(char));

See previous comments about malloc usage. Also, sizeof(char) is 1 by
definition. This applies even if a char is 3248573249857393485 bits long.
carattere[0]='\0';

//Istanziazione e inizializzazione della variabile parola
//parola = (char*)malloc(1*sizeof(char));
// parola[0]='\0';

Why is the above commented out? It is the only initialisation for this
variable. Also see previous comments about malloc.
while(!feof(pf)) //Ripete fino alla fine del file
{

fread(&c,1*sizeof(char),1,pf); //Lettura del carattere

Using fread for a single character is just plain daft, as is not
checking the return value. You should use getc or fgetc and ALWAYS check
whether the input function succeeded. Remember that feof does not
predict the future, it only tell you AFTER a read has failed due to
reaching the end of a file.
printf("\n carattere letto->%c",c);
//Controllo se il carattere è presente nell'alfabeto
if (isalpha(c))
{
printf("\n carattere valido");
//Calcolo della lunghezza della parola
lung=strlen(parola);

Unless I've missed something, parola is uninitialised the first time you
get here, so this invokes undefined behaviour. On some systems under
some conditions this *will* crash your program. Unless, of course, you
uncomment the code that initialises it.
//Assgnamento del valore alla variabile carattere
carattere[0]=c;
carattere[1]='\0';
parola=(char*)realloc(parola,(lung+1)*sizeof(char));

This is very bad usage of realloc, see comments about malloc and also
look up on what realloc does if it fails. You need a temporary variable
and, once again, to check the return value.

I've got bored with all the errors, but that should be enough to keep
you busy.

<snip remainder of code>
 
I

Ingo Menger

TC said:
//Allocazione della memoria per la stringa contenete la parola
dest->Elemento.parola = (char*)malloc(sizeof(sorg->Elemento.parola));
//Copia della stringa
strcpy(dest->Elemento.parola,sorg->Elemento.parola);

How many memory is allocated here?
What will the value of the expression sizeof(sorg->Elemento.parola) be?
Che cosa quando la parola esta molto lungo?
 
I

Ingo Menger

AK said:
Please translate your comments in English would you?

Not needed. Not all people here are barbarians :)
FYI, "funzione" might be, ahh well, a function.
If you have no clue of roman languages, the code should tell you, that
"abero" must be a tree.
And so forth.
 
T

TC

I have make some corrections, but the program doesn't correctly work.
Help me please.

/*Inclusione librerie*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

/*Definizione della strutura Elemento*/
typedef struct
{
char *parola;
unsigned int freq;
}Elem;

/*Definizione della lista delle parole trovate*/
struct Albero
{
Elem Elemento;
struct Albero *s;
struct Albero *d;
};

/*Definizione variabili*/
//Albero ordinato per alfabeto
struct Albero *treeA = NULL;
//Albero ordinato per frequenze
struct Albero *treeF = NULL;

unsigned int count = 0;

/*Definizione funzioni*/
//Funzione di scansione del file costruzione delle parole e chiamata
//della funzione di inseriento nell'albero ordinato per alfabeto
void Scansione(FILE *pf);
//Aggiungi nodo all'albero ordinato per alfabeto
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola);
//Stampa albero
void Print(struct Albero *nodo);
//Crea un nuovo albero ordinato per frequenza utilizzando come sorgente
l'albero
//ordinato per alfabeto
void CreaAlberoF(struct Albero *sorg);
//Aggiunge un nuovo nodo all'albero ordinato pre frequenze copiando i
valori dal
//nodo passato come sorgente
struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest);


main (void)
{
char scelta;
int fOK;
//Nome del file di testo
char nf[50];
//Puntatore al file
FILE *pf;
/*MAIN*/
printf("\n Avvio del programma \n");

do
{
fOK = 0;
printf("\nInserire il nome del file di testo che si desidera
utilizzare (Esempio: Testo.txt) \n");

gets(nf); //Lettura del nome del file

pf=fopen(nf,"r"); //Apertura del file in modalità di lettura

//Controllo apertura del file
if (pf==NULL)
{
//Restituzione del messaggio di errore in caso di mancata apertura
perror("ERRORE nell'apertura del file");
fOK = 1;
}

}while(fOK != 0);

printf("\n\n");



do
{
scelta = 0;
/*Menù*/
printf("\n 1- Scansione del file di testo \n");
printf("\n 2- Creazione del file delle parole ordinato per frequenza \n");
printf("\n 3- Stampa a video del file delle parole ordinato per
frequenza \n");
printf("\n 4- Stampa a video del file delle parole ordinato per ordine
alfabetico \n");
printf("\n 5- Esci \n");

do
{
scelta = getchar();
}while(scelta!= '1' && scelta!= '2' && scelta!= '3' && scelta!= '4' &&
scelta!= '5');
count=0;
//Blocco di scelta
switch(scelta)
{
case ('1'):
Scansione(pf);
printf("\n Scansione EFFETTUATA! \n");
break;
case ('2'):
CreaAlberoF(treeA);
printf("\n Lista delle parole ordinata per frequenza creata! \n");
break;
case ('3'):
Print(treeF);
break;
case('4'):
Print(treeA) ;
break;
default:
exit(0);
}
}while(scelta!=5);
}

/*Funzione che effettua la scansione del file per individuare le parole
e richiama la funzione di aggiunta di un nuovo elemento all'albero
alfabeto*/
void Scansione (FILE *pf)
{
char *ptr;
char *parola;
char c; //Variabile per la letura dei caratteri dal file di testo
char *carattere; //Variabile utilizzatata per la concatenazione
int lung; //Lunghezza della parola

//Istanziazione e inizializzazione della variabile carattere
carattere = malloc(2*sizeof(char));
carattere[0]='\0';

//Istanziazione e inizializzazione della variabile parola
parola = malloc(1*sizeof(parola));
parola[0]='\0';

while(!feof(pf)) //Ripete fino alla fine del file
{
c = fgetc(pf);//Lettura del carattere
//printf("\n carattere letto->%c",c);
//Controllo se il carattere è presente nell'alfabeto
if (isalpha(c))
{
//printf("\n carattere valido");
//Calcolo della lunghezza della parola
lung=strlen(parola);

//Assgnamento del valore alla variabile carattere
carattere[0]=c;
carattere[1]='\0';
//printf("\nLunghezza parola: %d",lung);

if(!(parola= realloc(parola,(lung+1)*sizeof(char))))
{
printf("\n REALLOC : Errore di allocazione della
memoria.\n");
getch();
}
//lowercase
*carattere = tolower(*carattere);
//Concatenzazione dei caratteri per formare la parola
parola = strcat(parola,carattere);
//printf("\n valore attuale di parola->%s",parola);
}
else
{
//Inserimento della parola
if ((parola[0]!='\0'))
{
printf("\n PAROLA: -> %s",parola);
//Richiamo della funzione che aggiunge le parole nell'albero
//ordianto per alfabeto
if (treeA == NULL)
{
//Aggionamemto della radice
treeA = AggNodo_TreeA(treeA,parola);
}
else
{
AggNodo_TreeA(treeA,parola);
}
//Reinizializzazione della variabile parola
parola= realloc(parola,sizeof(char));
parola[0]='\0';
}
}
}
//Chiusura file
fclose(pf);
}

//Funzione di aggiunta di un nodo all'albero
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola)
{

if (nodo == NULL)
{
//Creazione nuovo nodo dell'albero
if(!(nodo = (struct Albero*) malloc(sizeof(struct Albero))))
{
printf("\n Errore di allocazione della memoria.\n");
}
//Imposto il valore dei puntatori ai nodi figli
nodo->d = NULL;
nodo->s = NULL;
//Impostazione della frequenza
nodo->Elemento.freq = 1;

//Allocazione della memoria per la stringa contenete la parola
*nodo->Elemento.parola = malloc(sizeof(parola));
if(nodo->Elemento.parola == NULL)
{
printf("\n Errore di allocazione della memoria.\n");
}
//Copia della stringa
strcpy(nodo->Elemento.parola,parola);
//Se è il primo inserimento aggiorno il puntatore alla radice dell'albero
//printf("\n Parola inserita nel nodo: %s",nodo->Elemento.parola);
//getch();
}
else
{
//Variabile che restituisce il valore della comparazione parola
int conf;
//Comparazione della parola
conf = strcmp(nodo->Elemento.parola,parola);
//printf("\n S1: %s S2: %s Ris: %d",nodo->Elemento.parola,parola,conf);

switch(conf)
{
case (1):
nodo->s = AggNodo_TreeA(nodo->s,parola);
break;
case (-1):
nodo->d = AggNodo_TreeA(nodo->d,parola);
break;
default:
//Se le parole sono uguali incremento il valore della frequenza
nodo->Elemento.freq = nodo->Elemento.freq + 1 ;
break;
}
}
return nodo;
}

//Funzione di stampa dell'albero passato in input
void Print(struct Albero *nodo)
{

if (nodo != NULL)
{

//Richiamo della funzione sul ramo sinistro
Print(nodo->s);

if (count == 10 )
{
printf("\n Premere un tasto per continuare...\n");
getchar();
count = 0;
}
else
{
count++;
}
//Stampa della parola
printf("\n PAROLA: %s ", nodo->Elemento.parola);
printf(" FREQUENZA: %d ", nodo->Elemento.freq);

//Richiamo della funzione sul ramo destro
Print(nodo->d);
}
}

struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest)
{
if (dest == NULL)
{
//Creazione nuovo nodo dell'albero
dest = (struct Albero*) malloc(sizeof(struct Albero));
//Imposto il valore dei puntatori ai nodi figli
dest->d = NULL;
dest->s = NULL;
//Impostazione della frequenza
dest->Elemento.freq = sorg->Elemento.freq;
//Allocazione della memoria per la stringa contenete la parola
dest->Elemento.parola = malloc(sizeof(sorg->Elemento.parola));
//Copia della stringa
strcpy(dest->Elemento.parola,sorg->Elemento.parola);
}
else
{
//Comparazione Frequenza
if ( dest->Elemento.freq < sorg->Elemento.freq)
{
dest->s = AggNodo_TreeF(sorg,dest->s);
}
else
{
dest->d = AggNodo_TreeF(sorg,dest->d);
}
}
return dest;
}

/*Funzione che crea l'abero delle frequenze partendo dall'abero ordinato
per
alfabeto passato in input*/
void CreaAlberoF(struct Albero *sorg)
{
struct Albero *nodoprec;
if (sorg != NULL)
{
CreaAlberoF(sorg->s);
if (treeF == NULL)
{
treeF = AggNodo_TreeF(sorg, treeF);
}
else
{
AggNodo_TreeF(sorg, treeF);
}
CreaAlberoF(sorg->d);
}
}
 
F

Flash Gordon

TC said:
I have make some corrections, but the program doesn't correctly work.
Help me please.

Help us. In future tell us what you mean by "not working".
/*Inclusione librerie*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

malloc.h is STILL not a standard header, so don't include it. stdlib.h
which you are now also including provides all you need in terms of
malloc and friends.
/*Definizione della strutura Elemento*/
typedef struct
{
char *parola;
unsigned int freq;
}Elem;

/*Definizione della lista delle parole trovate*/
struct Albero
{
Elem Elemento;
struct Albero *s;
struct Albero *d;
};

/*Definizione variabili*/
//Albero ordinato per alfabeto
struct Albero *treeA = NULL;
//Albero ordinato per frequenze
struct Albero *treeF = NULL;

unsigned int count = 0;

/*Definizione funzioni*/
//Funzione di scansione del file costruzione delle parole e chiamata
//della funzione di inseriento nell'albero ordinato per alfabeto
void Scansione(FILE *pf);
//Aggiungi nodo all'albero ordinato per alfabeto
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola);
//Stampa albero
void Print(struct Albero *nodo);
//Crea un nuovo albero ordinato per frequenza utilizzando come sorgente
l'albero

You are still using // style comments. Please don't for the reasons I
previously posted, including the fact that as you can see above they
BREAK because of line wrapping.
//ordinato per alfabeto
void CreaAlberoF(struct Albero *sorg);
//Aggiunge un nuovo nodo all'albero ordinato pre frequenze copiando i
valori dal
//nodo passato come sorgente
struct Albero * AggNodo_TreeF(struct Albero *sorg, struct Albero *dest);


main (void)
{
char scelta;
int fOK;
//Nome del file di testo
char nf[50];
//Puntatore al file
FILE *pf;
/*MAIN*/
printf("\n Avvio del programma \n");

do
{
fOK = 0;
printf("\nInserire il nome del file di testo che si desidera
utilizzare (Esempio: Testo.txt) \n");

gets(nf); //Lettura del nome del file

Don't use gets. If the line is too long this WILL overflow the buffer
and can lead to ANYTHING happening. Use fgets but check the return value
and also check for the \n at the end of the text read (if it is not
there the line was too long to fit in the buffer.
pf=fopen(nf,"r"); //Apertura del file in modalità di lettura

//Controllo apertura del file
if (pf==NULL)
{
//Restituzione del messaggio di errore in caso di mancata
apertura
perror("ERRORE nell'apertura del file");
fOK = 1;
}

}while(fOK != 0);

printf("\n\n");



do
{
scelta = 0;
/*Menù*/
printf("\n 1- Scansione del file di testo \n");
printf("\n 2- Creazione del file delle parole ordinato per
frequenza \n");
printf("\n 3- Stampa a video del file delle parole ordinato per
frequenza \n");
printf("\n 4- Stampa a video del file delle parole ordinato per
ordine alfabetico \n");
printf("\n 5- Esci \n");

do
{
scelta = getchar();
}while(scelta!= '1' && scelta!= '2' && scelta!= '3' && scelta!=
'4' && scelta!= '5');

Better. However, for the future please note that on many systems no
input is passed to your program until the user presses enter. Telling
the user to select an option and press enter is a way around this, then
you can read all the characters up to and including the enter.
count=0;
//Blocco di scelta
switch(scelta)
{
case ('1'):
Scansione(pf);
printf("\n Scansione EFFETTUATA! \n");
break;
case ('2'):
CreaAlberoF(treeA);
printf("\n Lista delle parole ordinata per frequenza
creata! \n");
break;
case ('3'):
Print(treeF);
break;
case('4'):
Print(treeA) ;
break;
default:
exit(0);
}
}while(scelta!=5);
}

/*Funzione che effettua la scansione del file per individuare le parole
e richiama la funzione di aggiunta di un nuovo elemento all'albero
alfabeto*/
void Scansione (FILE *pf)
{
char *ptr;
char *parola;
char c; //Variabile per la letura dei caratteri dal file di testo
char *carattere; //Variabile utilizzatata per la concatenazione
int lung; //Lunghezza della parola

//Istanziazione e inizializzazione della variabile carattere
carattere = malloc(2*sizeof(char));

Better, but multiplying by sizeof(char) is pointless as it is defined as
being 1. Also, what if malloc fails?
carattere[0]='\0';

//Istanziazione e inizializzazione della variabile parola
parola = malloc(1*sizeof(parola));
parola[0]='\0';

while(!feof(pf)) //Ripete fino alla fine del file

Check the comp.lang.c FAQ. feof tells you if you reached the end of a
file when you tried doing the read, i.e. this is too early to do this check.
{
c = fgetc(pf);//Lettura del carattere

You need to check for feof here instead. You also need to check for it
failing for other reasons.
//printf("\n carattere letto->%c",c);
//Controllo se il carattere è presente nell'alfabeto
if (isalpha(c))
{
//printf("\n carattere valido");
//Calcolo della lunghezza della parola
lung=strlen(parola);

//Assgnamento del valore alla variabile carattere
carattere[0]=c;
carattere[1]='\0';
//printf("\nLunghezza parola: %d",lung);

if(!(parola= realloc(parola,(lung+1)*sizeof(char))))
{

If the realloc failed, then the old buffer (which you have just lost
your only pointer to) is still allocated. So you need to use a temporary
pointer.
printf("\n REALLOC : Errore di allocazione della
memoria.\n");
getch();

getch is not a standard function. Also, if the realloc failed shouldn't
you abort this function (and possibly the program in this case) rather
than continuing on and using the pointer which now does not point
anywhere valid?
}
//lowercase
*carattere = tolower(*carattere);
//Concatenzazione dei caratteri per formare la parola
parola = strcat(parola,carattere);
//printf("\n valore attuale di parola->%s",parola);
}
else
{
//Inserimento della parola
if ((parola[0]!='\0'))
{
printf("\n PAROLA: -> %s",parola);
//Richiamo della funzione che aggiunge le parole
nell'albero
//ordianto per alfabeto
if (treeA == NULL)
{
//Aggionamemto della radice
treeA = AggNodo_TreeA(treeA,parola);
}
else
{
AggNodo_TreeA(treeA,parola);

Don't you need the pointer you have just thrown away? This is probably
the cause of the problem you had spotted.
}
//Reinizializzazione della variabile parola
parola= realloc(parola,sizeof(char));

See previous comment about realloc.
parola[0]='\0';
}
}
}
//Chiusura file
fclose(pf);
}

//Funzione di aggiunta di un nodo all'albero
struct Albero *AggNodo_TreeA(struct Albero *nodo, char *parola)
{

if (nodo == NULL)
{
//Creazione nuovo nodo dell'albero
if(!(nodo = (struct Albero*) malloc(sizeof(struct Albero))))
{
printf("\n Errore di allocazione della memoria.\n");
}
//Imposto il valore dei puntatori ai nodi figli
nodo->d = NULL;
nodo->s = NULL;
//Impostazione della frequenza
nodo->Elemento.freq = 1;

//Allocazione della memoria per la stringa contenete la parola
*nodo->Elemento.parola = malloc(sizeof(parola));


This is also WRONG. You need to allocate enough space for the string you
are about to copy in, NOT enough for a pointer to a string.
if(nodo->Elemento.parola == NULL)
{
printf("\n Errore di allocazione della memoria.\n");
}

Again, if the allocation failed you don't want to continue on and make
use of the null pointer as if it was a valid pointer.

<snip>

I've not checked the rest of your program.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,585
Members
45,081
Latest member
AnyaMerry

Latest Threads

Top