PDA

Visualizza versione completa : 1)RISOLUZIONE PROBLEMA ALGORITMO IN C


caralu
11-09-2004, 18.52.20
Salve a tutti!
Ho un grosso problema: Dovrei risolvere il seguente algoritmo ASSOLUTAMENTE in linguaggio C :
"Gli studiosi di testi letterari a volte fanno un esame statistico delle
lettere (A,B,..), articoli (Il, lo,...),preposizioni(di, del, al...) e
parole presenti in un certo testo. Scrivere un programma che faccia
questa analisi stampando per ciascun di questi elementi le percentuali
di occorrenza in ordine crescente. Come esempi si prendano testi a
carattere matematico, informatico, un aricolo di giornale sportivo, un
racconto di uno scrittore".
Ho provato ad implementarlo da un p di tempo ma non riesco a trovare l'errore(che, presumo, sia nella funzione "pmatch"): viene eseguito un ciclo infinito. Il codice il seguente:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h> //Funz ricerca stringa: strstr();
#include <conio.h>

#define tot_lettere 36 //Tutte le lettere dell'alfabeto + i numeri del sistema decimale
#define dim_max 100

struct lista{
char *parola;
int contatore;
struct lista *next;
};

typedef struct lista list;

void spazio (void);
void analisi(char *);
int pmatch(char *, char *);
void insucc(char *);
void incrementa_lettera(char );
list *crea_lista(list *, char *);
list *confronta_stringa(char *, list *);
void stampa(list *);

int insuccesso[dim_max];
char lettere[tot_lettere]; //array contenente tutte le lettere dell'alfabeto + num.del sist decimale
char max_parola[dim_max]; //Parola massima composta da 25 caratteri
char pat[dim_max];

main()
{
int s, i;
char *testo;

do
{
spazio();
printf("\t\tDIGITI:\n\n");
printf("\n1- Analizzare il testo esistente (che verr visualizzato)\n2- Inserire un nuovo testo\n0- ESCI dal programma");
spazio();
scanf("%d",& s);

switch (s){

case 1 : clrscr();
spazio();
printf("Il testo esistente e':");
spazio();
//80 caratteri per riga nella schermata dell'applicativo
printf("\nDurante i primi decenni della loro esistenza, le reti di computer sono state\nusate principalmente dai ricercatori universitari per inviare messaggi\nelettronici, e dai dipendenti di industrie per condividere stampanti.\nIn questi ambiti, la segretezza non aveva ragione di esistere.\nInvece adesso, con milioni di comuni cittadini che utilizzano le reti per\noperazioni bancarie, commerciali e fiscali questo problema e' apparso\nell orizzonte come potenzialmente collettivo.\nLa sicurezza in rete e' un argomento vasto e riguarda una moltitudine di\ncrimini.\nNella sua forma piu' semplice, si occupa di assicurare che nessuno possa leggere\no, peggio ancora, modificare i messaggi destinati ad altri. Si occupa di persone\nche cercano di accedere a servizi remoti che non sono autorizzati a usare.\nLa sicurezza si occupa anche di problemi come l intercettazione di messaggi\nautografi e la loro riproduzione, e di persone che cercano di negare di aver\nspedito tali messaggi.\n");
spazio();
testo = "\nDurante i primi decenni della loro esistenza, le reti di computer sono state\nusate principalmente dai ricercatori universitari per inviare messaggi\nelettronici, e dai dipendenti di industrie per condividere stampanti.\nIn questi ambiti, la segretezza non aveva ragione di esistere.\nInvece adesso, con milioni di comuni cittadini che utilizzano le reti per\noperazioni bancarie, commerciali e fiscali questo problema e' apparso\nell orizzonte come potenzialmente collettivo.\nLa sicurezza in rete e' un argomento vasto e riguarda una moltitudine di\ncrimini.\nNella sua forma piu' semplice, si occupa di assicurare che nessuno possa leggere\no, peggio ancora, modificare i messaggi destinati ad altri. Si occupa di persone\nche cercano di accedere a servizi remoti che non sono autorizzati a usare.\nLa sicurezza si occupa anche di problemi come l intercettazione di messaggi\nautografi e la loro riproduzione, e di persone che cercano di negare di aver\nspedito tali messaggi.\n ";
printf("\n\n\n\t\t...[INVIO] per continuare...\n");
getchar(); getchar();
clrscr();
analisi(testo);

for(i=0; i<tot_lettere; i++)
printf("\n%d lettera : %d ", i+1, lettere[i]);
break;

case 2 : //clrscr();
spazio();
printf("\tINSERISCA UN NUOVO TESTO, tutto su una riga ([INVIO] per terminare):");
gets(testo);
//clrscr();
spazio();
printf("\t\tHA INSERITO:");
spazio();
puts(testo);
spazio();
printf("\n\n\n\t\t...[INVIO] per continuare...\n");
getchar();
//clrscr();
analisi(testo);
break;

case 0 : exit(0);

default : //clrscr();
printf("\a\t\tSELEZIONE NON PRESENTE!\n\n\t\tDigiti [INVIO] e ripeta la scelta:");
getchar();
break;
}
}
while(s < 0 || s > 2);


fflush(stdin);
getchar();
}

SEGUE NELLA PAGINA PRECEDENTE---------------------------------->

caralu
11-09-2004, 18.56.13
<----------------------------------IL CONTINUO:

void spazio(void)
{
printf("\n--------------------------------------------------------------------------\n");
}

//************************************************** ******************

void analisi (char *testo)
{

int cont = 0, i;
list *inizio, *p;

inizio = p = NULL;

do
{
//Se la lettera corrente uguale ad un qualsiasi carattere di punteggiatura si effettua la verifica
if(*testo != ',' && *testo != '.' && *testo != ' ' && *testo != '?' && *testo != '!' && *testo != '"' && *testo != '=' && *testo != '\\' && *testo != ':' && *testo != '<' && *testo != '>' && *testo != ';' && *testo != '' && *testo != '$' && *testo != '%' && *testo != '(' && *testo != ')' && *testo != '*' && *testo != '_' && *testo != '+' && *testo != '-' && *testo != '/' && *testo != '|' && *testo != '#' && *testo != '@' && *testo != '[' && *testo != ']' && *testo != '\0' && *testo != '\'')
{
incrementa_lettera(*testo); //Incrementa il contatore della lettera

max_parola[cont] = *testo;

cont++;
testo++;
}
else
{
if (cont == 0 || cont ==1) //Se una lettera il suo contatore gi stato incrementato
{
testo++;
cont = 0;
}
else
{
inizio = confronta_stringa(max_parola, inizio);
}

for(i=0; i<tot_lettere; i++) //Inizializziamo a vuoto tutte le componenti dell'array
max_parola[i] = '\0';
}

}
while(*testo != '\0');
}

//************************************************** ******************

list *confronta_stringa(char *v, list *inizio)
{
int flag = -1;

while(inizio && flag == -1) //non si raggiunta la fine del testo e non si trovata la stringa
{
flag = pmatch(v, inizio->parola);
if(flag != -1) //Se il pattern non stato trovato pmatch restituisce -1
{
inizio->contatore ++; //Incrementa il contatore della stringa esistente
return(inizio);
}
else
inizio = inizio->next;
}

if(flag == -1)
inizio = crea_lista(inizio, v);

return(inizio);
}

//************************************************** ******************

int pmatch(char *stringa, char *pat)
{
int i=0, j=0;

int lens = strlen(stringa);
int lenp = strlen(pat);

insucc(pat);

while(i<lens && j<lenp)
{
if(stringa[i] == pat[j])
{i++; j++;}
else
if(j==0)
i++;
else
j = insuccesso[j-1]+1;
}
return( (j==lenp) ? (i-lenp) : -1);
}

//************************************************** ******************

void insucc(char *pat)
{
int i, j;

int n = strlen(pat);

insuccesso[0] = -1;

for(j=1; j<n; j++)
{
i = insuccesso[j-1];
while((pat[j] != pat[i+1]) && (i>=0))
i = insuccesso[i];

if(pat[j] == pat[i+1])
insuccesso[j] = i+1;
else
insuccesso[j] = -1;
}
}

//************************************************** ******************

list *crea_lista(list *inizio, char *pattern)
{
list *p, *aux;

p = (list *)malloc(sizeof(list));

if(!p)
{printf("\nMEMORIA ESAURITA!!");
getchar();
exit(0);
}


strcpy(p->parola, pattern);
p->contatore = 1;
p->next = NULL;
if(!inizio)
return(p);
else
{
aux = inizio;
while(aux->next)
aux = aux->next;
aux->next = p;

return(inizio);
}
}

//************************************************** ******************

void stampa (list *inizio)
{
spazio();
printf("\t\tCOMPOSIZIONE TESTO:");
spazio();

while(inizio)
{
printf("\n%s compare nel testo %d volte.", inizio->parola, inizio->contatore);
inizio = inizio->next;
}
spazio();
}

//************************************************** ******************
void incrementa_lettera(char lettera)
{
switch (lettera){
case 'a' :
case 'A' : lettere[0]++; break;
case 'b' :
case 'B' : lettere[1]++; break;
case 'c' :
case 'C' : lettere[2]++; break;
case 'd' :
case 'D' : lettere[3]++; break;
case 'e' :
case 'E' : lettere[4]++; break;
case 'f' :
case 'F' : lettere[5]++; break;
case 'g' :
case 'G' : lettere[6]++; break;
case 'h' :
case 'H' : lettere[7]++; break;
case 'i' :
case 'I' : lettere[8]++; break;
case 'j' :
case 'J' : lettere[9]++; break;
case 'k' :
case 'K' : lettere[10]++; break;
case 'l' :
case 'L' : lettere[11]++; break;
case 'm' :
case 'M' : lettere[12]++; break;
case 'n' :
case 'N' : lettere[13]++; break;
case 'o' :
case 'O' : lettere[14]++; break;
case 'p' :
case 'P' : lettere[15]++; break;
case 'q' :
case 'Q' : lettere[16]++; break;
case 'r' :
case 'R' : lettere[17]++; break;
case 's' :
case 'S' : lettere[18]++; break;
case 't' :
case 'T' : lettere[19]++; break;
case 'u' :
case 'U' : lettere[20]++; break;
case 'v' :
case 'V' : lettere[21]++; break;
case 'w' :
case 'W' : lettere[22]++; break;
case 'x' :
case 'X' : lettere[23]++; break;
case 'y' :
case 'Y' : lettere[24]++; break;
case 'z' :
case 'Z' : lettere[25]++; break;
case '1' : lettere[26]++; break;
case '2' : lettere[27]++; break;
case '3' : lettere[28]++; break;
case '4' : lettere[29]++; break;
case '5' : lettere[30]++; break;
case '6' : lettere[31]++; break;
case '7' : lettere[32]++; break;
case '8' : lettere[33]++; break;
case '9' : lettere[34]++; break;
case '0' : lettere[35]++; break;

default : break;
}
}

P8257 WebMaster
11-09-2004, 21.48.36
Praticamente devi fare un programma che cerchi una o pi occorrenze in un dato testo .. ho capito bene?...

I tipi dati sono stati decisi da te .. o qualcuno ti ha obbligato ad usare le strutture?...

Questo algoritmo va fortemente ottimizzato...

Bye :cool:

Sergio Neddi
11-09-2004, 21.56.38
Ho unito le discussioni: spezzare il tutto in 2 thread genererebbe confusione.

Ah, dimenticavo, caralu: benvenuto!

P8257 WebMaster
11-09-2004, 22.03.53
caralu ha scritto:

SEGUE NELLA PAGINA PRECEDENTE---------------------------------->

:D .. :devil: :D..

Bye :cool:

LoryOne
13-09-2004, 12.05.35
Io lo riscriverei proprio.
L'esempio non che sia il massimo della vita :D per gi un po meglio, almeno dal mio punto di vista.


#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>

#define un 0
#define uno 1
#define una 2

static const char *punt=" !;,.:'?-\n";
short int chr[255],prop[una+1];
char *s=NULL;

main(void){
long l=0,i=0,j=0;
char car;

s="\nDurante i primi decenni della loro esistenza, "
"le reti di computer sono state usate principalmente "
"dai ricercatori universitari per inviare messaggi elettronici, "
"e dai dipendenti di industrie per condividere stampanti.\nIn "
"questi ambiti, la segretezza non aveva ragione di esistere. "
"Invece adesso, con milioni di comuni cittadini che utilizzano "
"le reti per operazioni bancarie, commerciali e fisca li questo "
"problema e' apparso nell orizzonte come potenzialmente colletti"
"vo. La sicurezza in rete e' un argomento vasto e riguarda una "
"moltitudine di crimini.\nNella sua forma piu' semplice, si "
"occupa di assicurare che nessuno possa leggere o, peggio ancora, "
"modificare i messaggi destinati ad altri.\nSi occupa di persone "
"che cercano di accedere a servizi remoti che non sono autorizzati "
"a usare.\nLa sicurezza si occupa anche di problemi come l' "
"intercettazione di messaggi\nautografi e la loro riproduzione, "
"e di persone che cercano di negare di aver spedito tali messaggi.\n";

printf("TESTO DA ANALIZZARE:\n%s",s);
memset(chr,0,sizeof(chr));
i=strlen(s)-1;
j=strlen(punt);
while(*s){
// Conteggio le occorrenze dei singoli caratteri
chr[*s]++;
switch(*s){
// Controllo un,uno,una
case 'u':
// Se all'inizio o alla fine del testo
if(l==0){
// un
if(*(s+1)=='n'&&memchr(punt,*(s+2),strlen(punt))||
(*(s+1)=='n'&&l+1==i))prop[un]++;
// uno
if(*(s+2)=='o'&&memchr(punt,*(s+3),j)||
(*(s+2)=='o'&&l+3==i))prop[uno]++;
// una
if(*(s+2)=='a'&&memchr(punt,*(s+3),j)||
(*(s+2)=='a'&&l+3==i))prop[una]++;
}else{ // Se all'interno del testo
if(memchr(punt,*(s-1),j)){
if(*(s+1)=='n'&&memchr(punt,*(s+2),j)||
(*(s+1)=='n'&&l+1==i))prop[un]++;
if(*(s+2)=='o'&&memchr(punt,*(s+3),j)||
(*(s+2)=='o'&&l+3==i))prop[uno]++;
if(*(s+2)=='a'&&memchr(punt,tolower(*(s+3)),j)||
(*(s+2)=='a'&&l+3==i))prop[una]++;
}
}break;
}l++;s++;
}
printf("\nPREMI UN TASTO...\n");getch();
printf("Quale carattere vuoi controllare ?");
scanf("%c",&car);
printf("\nIl carattere '%c' e' presente %i volte nel testo.\n",car,chr[car]);
printf("il termine 'un' e' presente %i volte nel testo.\n",prop[un]);
printf("il termine 'una' e' presente %i volte nel testo.\n",prop[una]);
printf("il termine 'uno' e' presente %i volte nel testo.",prop[uno]);
getch();
}

caralu
13-09-2004, 23.47.25
Grazie SERGIO, cos molto pi leggibile.
Per quanto riguarda WEBMASTER: si, l'algoritmo deve effettuare una ricerca di parole, articoli, lettere e preposizioni in un testo.
L'algoritmo che ho scritto io molto grezzo.
Trovo abbastanza buona l'impostazione effettuata da Lory ONe: appena ho un p di tempo modifico il tuo codice e lo pubblico qua cos lo vediamo assieme... A molto presto e grazie a tutti per l'aiuto

LoryOne
16-09-2004, 15.12.26
... appena ho un p di tempo modifico il tuo codice e lo pubblico qua cos lo vediamo assieme... A molto presto e grazie a tutti per l'aiuto


Ok. :)

caralu
04-10-2004, 18.23.22
Ho modificato il codice:
siccome devo stampare le parole in ordine di occorrenza crescente
(prima quelle che compaiono di meno, poi via via quelle pi frequenti), ho introdotto l'algoritmo di ordinamento radix-sort che permette di ordinare la lista in ordine crescente, in modo da stampare la lista delle parole con l'ordine giusto.
Nonostante questo ho un problema di compilazione e non riesco a trovare l'errore. L'algoritmo sembra corretto e non riesco a capire cosa abbia sbagliato. Se qualcuno pu darmi una mano lo ringrazio davvero tantissimo.




#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

//Queste due costanti servono per l'ordinamento radix sort:
#define RADICE_SIZE 10 //numero di cifre del sist. decimale
#define MAX_CIFRE 3 //numero di cifre da 0 a 999


//Mantiene le frequenze delle lettere
int freqLettere['z' - 'a' + 1]; //Array di dimensione 26 (numero di lettere dell'alfabeto)

//Mantiene le frequenze dei numeri
int freqNumeri[10]; //Dimensione 10 per prendere in considerazione i numeri del sistema decimale

//Mantiene il numero totale di caratteri trovati nel testo (lettere e numeri)
int totaleCaratteri = 0;

//Mantiene il numero totale di parole trovate nel testo
int totaleParole = 0;



//Definizione dell'elemento di una lista
typedef struct list *lista;
typedef struct list{
char *parola;
int frequenza[MAX_CIFRE];
list *next;
}list;

//Variabile che mantiene le lista di parole
lista parole = NULL;

//Inizializza a zero i vettori delle frequenze (lettere e numeri)
void inizializza(){
int i;
for(i = 0; i < 10; i++)
freqNumeri[i] = 0;
for(i = 0; i < ('z' - 'a' + 1); i++)
freqLettere[i] = 0;
}

//Aggiorna le frequenze di lettere e numeri
void aggiornaFrequenze(char *parola)
{
int i;
char c;
int len = strlen(parola); //Memorizza la dimensione di char della parola corrente

for(i = 0; i < len; i++)
{
c = parola[i]; //Memorizza in c la parola corrente
//isalpha restituisce un valore diverso da zero se e una lettera (maiuscola o minuscola)
if(isalpha(c))
{
//la funzione tolower rende tutte le lettere minuscole
c = tolower(c);

//incrementiamo la posizione corrispondente di freqLettere
freqLettere[c - 'a']++;
}

//isdigit controlla se il carattere corrente un numero (in tal caso restituisce un valore diverso da 0)
if(isdigit(c))
{
//incrementiamo la posizione corrispondente di freqLettere
freqNumeri[c - '0']++;
}
}
//Incremento il numero di parole totali
totaleParole++;
//Incremento il numero di caratteri totali
totaleCaratteri = totaleCaratteri + len;
}

//Restituisce la prossima parola che si trova in testo a partire
//dalla posizione posizioneCorrente. Una parola definita come
//una sequenza di lettere e/o numeri senza altri caratteri.
//Restituisce NULL se non c' una prossima parola

char *prossimaParola(char *testo)
{
static int posizioneCorrente = 0;
int i;
int len = strlen(testo); //len rappresenta il numero dei caratteri presenti nel testo

//mi sposto avanti finche non trovo una lettera o un numero
while(! isalnum(testo[posizioneCorrente]))
{ //isalnum restituisce un valore diverso da zero se ci che analizziamo un carattere alfanumerico
posizioneCorrente++;
//se sono alla fine senza aver trovato lettere o numeri ritorno null
if(posizioneCorrente >= len)
return NULL;
}
//incremento i finch trovo numeri e lettere; alla fine del cilco
//i punta alla fine della parola corrente
i = posizioneCorrente; //in i si registra l'indice dell'array in cui inizia la prima frase del testo
while(isalnum(testo[i]) && (i < len))
i++; //i adesso assume il valore dell'indice dell'array che rappresenta la fine della parola
int lunghezza = i - posizioneCorrente; //lunghezza la lunghezza di caratteri della parola considerata
char *parola = (char *)malloc((lunghezza + 1));
for(i = 0; i <= lunghezza; i++)
parola[i] = testo[posizioneCorrente + i]; //su parola viene memorizzata la parola corrente
//Inserisco il carattere di fine stringa alla fine della parola
parola[lunghezza] = '\0';
posizioneCorrente = posizioneCorrente + i; //riprende dalla fine della parola
return parola;
}

void stampaNumeri(){
printf("\n\n");
int i;
for(i = 0; i < 10; i++)
printf("\nfrequenza di %d: %d", i, freqNumeri[i]);
}

void stampaLettere(){
printf("\n\n");
int i;
for(i = 0; i < ('z' - 'a' + 1); i++)
printf("\nfrequenza di %c: %d", 'a' + i, freqLettere[i]);
}

void stampaParole(){
printf("\n\n");
lista temp = parole;
while(temp){
printf("\nfrequenza di %s: %d", temp->parola, temp->frequenza[0]);
temp = temp -> next;
}
}

//Inserisce la parola nella lista parole, se non gia presente,
//altrimenti incrementa la sua frequenza
void inserisciParola(char *parola){
lista temp = parole;
//Scorriamo la lista per vedere se la parola ia stata inserita
while(temp){
//Se la parola gi c' ci limitiamo a incrementare
//la frequenza
if(strcmp(temp -> parola, parola) == 0) //se strcmp restituisce 0 le stringhe sono uguali
{ temp->frequenza[2] = temp->frequenza[2]%RADICE_SIZE;
temp->frequenza[1]=(temp->frequenza[1] % (RADICE_SIZE*RADICE_SIZE))/RADICE_SIZE;
temp->frequenza[0]=(temp->frequenza[0] % (RADICE_SIZE*RADICE_SIZE*RADICE_SIZE))/(RADICE_SIZE*RADICE_SIZE);
return;
}
temp = temp -> next;
}
//Se la parola non stata trovata, creiamo un nuovo elemento
//che sar inserito in testa alla lista.
temp = (lista )malloc(sizeof(lista));
temp -> parola = parola;
temp -> frequenza[0] = 1;
temp -> next = parole;
//Facciamo puntare la lista 'parole' all'elemento di testa
//appena isnerito
parole = temp;
}



/*questa funzione crea dei "recipienti" per rappresentare il valore delle chiavi (sono 10 recipienti, da 0 a 9). Visto che un numero intero costituito da pi cifre ordinate dalla meno significativa, in ultima posizione, alla pi significativa, in prima posizione (000, 001, 002,..., 010,...,100,..., 999) e
ogni cifra K si trova nell'intervallo 0 <= k <= 9 ,in questo tipo di ordinamento la chiave di ordinamento viene scomposta in cifre utilizzando una radice RADICE_SIZE*/


lista radice_sort(lista ptr)
{
lista davanti[RADICE_SIZE], dietro[RADICE_SIZE];
int i, j, cifra;

for(i=MAX_CIFRE-1;i>=0;i--)
{
for(j=0;j<RADICE_SIZE;j++)
davanti[j] = dietro[j] = NULL; //i recipienti sono //implementati come code di dati: davanti[i] punta al primo //record nel recipiente i, mentre dietro[i] punta all'ultimo //record nel recipiente i.

while(ptr)
{
cifra = ptr->frequenza[i];
if(!davanti[cifra])
davanti[cifra] = ptr;
else
dietro[cifra]->next = ptr;
dietro[cifra] = ptr;
ptr = ptr->next;
}
ptr = NULL;
for(j=RADICE_SIZE-1;j>=0;j--)
{
if(davanti[j])
{
dietro[j]->next = ptr;
ptr = davanti[j];
}
}
}
return ptr;
}

int main(){
char * p;
char *testo = "ciao\tt\n1r&7 (re)re t zz";
while((p = prossimaParola(testo))){
aggiornaFrequenze(p);
inserisciParola(p);
}
stampaNumeri();
stampaLettere();
parole = radice_sort(parole);
stampaParole();

printf("\n\nTotale parole: %d", totaleParole);
printf("\n\nTotale caratteri: %d", totaleCaratteri);

fflush(stdin);
getchar();
}

LoryOne
05-10-2004, 08.48.08
Il problema sembra risiedere in ProssimaParola, subito dopo questa istruzione:
char *parola = (char *)malloc((lunghezza + 1));

caralu
05-10-2004, 19.21.09
Il problema dev'essere all'interno della funzione "inserisciParola", ma non riesco ad individuarlo, gli assegnamenti mi sembrano corretti, eppure....
Mi serve che lo analizzi un esterno. Spero che qualcuno riesca a trovare un po di tempo e pazienza per farlo.
Grazie a chi lo facesse:confused: :)

LoryOne
05-10-2004, 21.13.08
Si, pu anche essere e forse esplode pure quando esegui il sort ma andiamo con ordine:

Compilato cos com' non da problemi ma quando lo lancio esplode.
E' tipico quando si lavora con i puntatori e quindi necessario fare molta attenzione.

La priam funzione che viene richiamata "ProssimaParola", quindi analizziamo prima questa.
Funziona tutto fino a:
char *parola = (char *)malloc((lunghezza + 1));
poi quel for...fa esplodere tutto.

Io mi chiedo:
Se conosci la lunghezza a priori, perch allochi memoria dinamica ?
Non sarebbe pi semplice definire
char parola[lunghezza] ?

LoryOne
05-10-2004, 21.17.15
...intanto ti propongo un'altra visione della cosa, per prima cerchiamo di risolvere il problema col tuo listato :)

pholcus
06-10-2004, 11.35.40
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

//Queste due costanti servono per l'ordinamento radix sort:
#define RADICE_SIZE 10 //numero di cifre del sist. decimale
#define MAX_CIFRE 3 //numero di cifre da 0 a 999


//Mantiene le frequenze delle lettere
int freqLettere['z' - 'a' + 1]; //Array di dimensione 26 (numero di lettere dell'alfabeto)

//Mantiene le frequenze dei numeri
int freqNumeri[10]; //Dimensione 10 per prendere in considerazione i numeri del sistema decimale

//Mantiene il numero totale di caratteri trovati nel testo (lettere e numeri)
int totaleCaratteri = 0;

//Mantiene il numero totale di parole trovate nel testo
int totaleParole = 0;



//Definizione dell'elemento di una lista
//typedef struct list *lista;
typedef struct list{
char *parola;
int frequenza[MAX_CIFRE];
struct list *next;
} list;

//Variabile che mantiene le lista di parole
struct list *parole = NULL;

//Inizializza a zero i vettori delle frequenze (lettere e numeri)
void inizializza(){
int i;
for(i = 0; i < 10; i++)
freqNumeri[i] = 0;
for(i = 0; i < ('z' - 'a' + 1); i++)
freqLettere[i] = 0;
}

//Aggiorna le frequenze di lettere e numeri
void aggiornaFrequenze(char *parola)
{
int i;
char c;
int len = strlen(parola); //Memorizza la dimensione di char della parola corrente

for(i = 0; i < len; i++)
{
c = parola[i]; //Memorizza in c la parola corrente
//isalpha restituisce un valore diverso da zero se e una lettera (maiuscola o minuscola)
if(isalpha(c))
{
//la funzione tolower rende tutte le lettere minuscole
c = tolower(c);

//incrementiamo la posizione corrispondente di freqLettere
freqLettere[c - 'a']++;
}

//isdigit controlla se il carattere corrente un numero (in tal caso restituisce un valore diverso da 0)
if(isdigit(c))
{
//incrementiamo la posizione corrispondente di freqLettere
freqNumeri[c - '0']++;
}
}
//Incremento il numero di parole totali
totaleParole++;
//Incremento il numero di caratteri totali
totaleCaratteri = totaleCaratteri + len;
}

//Restituisce la prossima parola che si trova in testo a partire
//dalla posizione posizioneCorrente. Una parola definita come
//una sequenza di lettere e/o numeri senza altri caratteri.
//Restituisce NULL se non c' una prossima parola

char *prossimaParola(char *testo)
{
static int posizioneCorrente = 0;
int i;
int len = strlen(testo); //len rappresenta il numero dei caratteri presenti nel testo

//mi sposto avanti finche non trovo una lettera o un numero
while(! isalnum(testo[posizioneCorrente]))
{ //isalnum restituisce un valore diverso da zero se ci che analizziamo un carattere alfanumerico
posizioneCorrente++;
//se sono alla fine senza aver trovato lettere o numeri ritorno null
if(posizioneCorrente >= len)
return NULL;
}
//incremento i finch trovo numeri e lettere; alla fine del cilco
//i punta alla fine della parola corrente
i = posizioneCorrente; //in i si registra l'indice dell'array in cui inizia la prima frase del testo
while(isalnum(testo[i]) && (i < len))
i++; //i adesso assume il valore dell'indice dell'array che rappresenta la fine della parola
int lunghezza = i - posizioneCorrente; //lunghezza la lunghezza di caratteri della parola considerata
char *parola = (char *)malloc((lunghezza + 1));
for(i = 0; i <= lunghezza; i++)
parola[i] = testo[posizioneCorrente + i]; //su parola viene memorizzata la parola corrente
//Inserisco il carattere di fine stringa alla fine della parola
parola[lunghezza] = '\0';
posizioneCorrente = posizioneCorrente + i; //riprende dalla fine della parola
return parola;
}

void stampaNumeri(){
printf("\n\n");
int i;
for(i = 0; i < 10; i++)
printf("\nfrequenza di %d: %d", i, freqNumeri[i]);
}

void stampaLettere(){
printf("\n\n");
int i;
for(i = 0; i < ('z' - 'a' + 1); i++)
printf("\nfrequenza di %c: %d", 'a' + i, freqLettere[i]);
}

void stampaParole(){
printf("\n\n");
struct list *temp = parole;
while(temp){
printf("\nfrequenza di %s: %d", temp->parola, temp->frequenza[0]);
temp = temp -> next;
}
}

//Inserisce la parola nella lista parole, se non gia presente,
//altrimenti incrementa la sua frequenza
void inserisciParola(char *parola){
struct list *temp = parole;
//Scorriamo la lista per vedere se la parola ia stata inserita
while(temp){
//Se la parola gi c' ci limitiamo a incrementare
//la frequenza
if(strcmp(temp -> parola, parola) == 0) //se strcmp restituisce 0 le stringhe sono uguali
{ temp->frequenza[2] = temp->frequenza[2]%RADICE_SIZE;
temp->frequenza[1]=(temp->frequenza[1] % (RADICE_SIZE*RADICE_SIZE))/RADICE_SIZE;
temp->frequenza[0]=(temp->frequenza[0] % (RADICE_SIZE*RADICE_SIZE*RADICE_SIZE))/(RADICE_SIZE*RADICE_SIZE);
return;
}
temp = temp -> next;
}
//Se la parola non stata trovata, creiamo un nuovo elemento
//che sar inserito in testa alla lista.
temp = (struct list *)malloc(sizeof(struct list));
temp -> parola = parola;
temp -> frequenza[0] = 1;
temp -> next = parole;
//Facciamo puntare la lista 'parole' all'elemento di testa
//appena isnerito
parole = temp;
}



/*questa funzione crea dei "recipienti" per rappresentare il valore delle chiavi (sono 10 recipienti, da 0 a 9). Visto che un numero intero costituito da pi cifre ordinate dalla meno significativa, in ultima posizione, alla pi significativa, in prima posizione (000, 001, 002,..., 010,...,100,..., 999) e
ogni cifra K si trova nell'intervallo 0 <= k <= 9 ,in questo tipo di ordinamento la chiave di ordinamento viene scomposta in cifre utilizzando una radice RADICE_SIZE*/


struct list * radice_sort(struct list *ptr)
{
struct list *davanti[RADICE_SIZE], *dietro[RADICE_SIZE];
int i, j, cifra;

for(i=MAX_CIFRE-1;i>=0;i--)
{
for(j=0;j<RADICE_SIZE;j++)
davanti[j] = dietro[j] = NULL; //i recipienti sono //implementati come code di dati: davanti[i] punta al primo //record nel recipiente i, mentre dietro[i] punta all'ultimo //record nel recipiente i.

while(ptr)
{
cifra = ptr->frequenza[i];
if(!davanti[cifra])
davanti[cifra] = ptr;
else
dietro[cifra]->next = ptr;
dietro[cifra] = ptr;
ptr = ptr->next;
}
ptr = NULL;
for(j=RADICE_SIZE-1;j>=0;j--)
{
if(davanti[j])
{
dietro[j]->next = ptr;
ptr = davanti[j];
}
}
}
return ptr;
}

int main(){
char * p;
char *testo = "ciao\tt\n1r&7 (re)re t zz";
while((p = prossimaParola(testo))){
aggiornaFrequenze(p);
inserisciParola(p);
}
stampaNumeri();
stampaLettere();
parole = radice_sort(parole);
stampaParole();

printf("\n\nTotale parole: %d", totaleParole);
printf("\n\nTotale caratteri: %d", totaleCaratteri);

fflush(stdin);
getchar();
}



Ora e' a posto nn crasha piu'..

Hai usato male i puntatori e le liste, in particolare:

typedef struct list *lista;
typedef struct list{
char *parola;
int frequenza[MAX_CIFRE];
lista *next;
} list;

nn e' corretto..


Ciao ;)