Esercizio sulle stringhe in C
Salve a tutti, ho il seguente programma da svolgere.
Si scriva un programma che acquisisca utilizzando la funzione gets una stringa composta da un massimo di 5 parole separati da spazi, per un totale di massimo 60 caratteri. Il programma deve:
a) Stabilire quante sono effettivamente le parole contenute nella stringa
b) Calcolare la media delle lunghezze delle parole
c) produrre una statistica sulla lunghezza delle parole
Io ho risolto solo il punto a) purtroppo... Diciamo che il programma potrebbe essere fatto in "maniera furba" calcolando prima la lunghezza delle singole parole e poi farne la media, ma stampandoli con la printf nell'ordine richiesto..
Avete qualche consiglio da darmi?
P.s string.h l'ho inclusa provvisoriamente, ma so che per come è scritto il programma per ora è inutile!
Si scriva un programma che acquisisca utilizzando la funzione gets una stringa composta da un massimo di 5 parole separati da spazi, per un totale di massimo 60 caratteri. Il programma deve:
a) Stabilire quante sono effettivamente le parole contenute nella stringa
b) Calcolare la media delle lunghezze delle parole
c) produrre una statistica sulla lunghezza delle parole
Io ho risolto solo il punto a) purtroppo... Diciamo che il programma potrebbe essere fatto in "maniera furba" calcolando prima la lunghezza delle singole parole e poi farne la media, ma stampandoli con la printf nell'ordine richiesto..
Avete qualche consiglio da darmi?

P.s string.h l'ho inclusa provvisoriamente, ma so che per come è scritto il programma per ora è inutile!

#include <stdio.h> #include <stdlib.h> #include <string.h> #define LUNG_STRING 61 int main() { char stringa[LUNG_STRING]; int i; int quante_parole=0; printf("Inserisci una stringa di caratteri separati da spazi\n"); gets(stringa); i=1; while(stringa[i]!='\0') { if ((stringa[i]==' ')&&(stringa[i-1]!=' ')) quante_parole++; i++; } if (stringa[i-1]!=' ') quante_parole++; if(quante_parole>5) printf("Sono state inserite troppe parole\n"); else printf("Le parole presenti nella fase sono %d",quante_parole); return EXIT_SUCCESS; }
Risposte
Per prima cosa, gets NON ANDREBBE MAI USATA!!! e nessun professore dovrebbe per questo motivo insegnarla.
Per quanto riguarda la tua domanda invece, che genere di consigli stai cercando?
Per quanto riguarda la tua domanda invece, che genere di consigli stai cercando?
Come calcolare la media della lunghezza delle parole e poi dire ad esempio.. tre parole sono lunghe 6 caratteri, una parola è lunga 5 caratteri e cosi via

Il numero di caratteri per ogni parola lo calcoli contando i caratteri fino allo spazio successivo. Memorizzi questi valori in un array che utilizzerai sia per calcolare le statistiche, sia per stampare poi i singoli valori successivamente.
Quindi, se ho capito bene, devo crearmi una funzione leggi_stringa per trovare questi valori per calcolare le statistiche etc?
Più o meno, l'idea è quella di scorrere la stringa letta, sostituire tutti gli spazi con '\0' memorizzando gli indirizzi all'inizio di ogni parola e la loro lunghezza. A questo punto le ultime due fasi dovrebbero essere immediate.
Per leggere le stringhe ho una funzione "standard" che sarebbe questa:
Ma in questo caso non so davvero come adattarlo...
int leggi_stringa( char str[],int*p_lung_stringa) { int indice,carat; indice=0; while((carat = getchar())!='\n') if(indice<LUNG_STRINGA) { stringa[indice] = (char) carat; indice++; } stringa[indice] ='\0'; *p_lung_stringa = indice; return(carat); }
Ma in questo caso non so davvero come adattarlo...
Chi è mai questo professore che fa utilizzare la gets???
Altra cosa, se fossi in te, prevederei anche un meccanismo (prima di tutto quanto il resto del codice) che conta che le stringhe effettivamente immesse siano al massimo 5.
Altra cosa, se fossi in te, prevederei anche un meccanismo (prima di tutto quanto il resto del codice) che conta che le stringhe effettivamente immesse siano al massimo 5.
Il mio prof non ha accennato alla funzione gets e non sta neanche sul suo libro credo, infatti non ne conoscevo il funzionamento; queste sono esercitazioni fatte da tutti i docenti e magari l'ha inserita qualcun altro.. comunque ho calcolato la lunghezza della media delle parole, ma rimane il problema sul punto c)... Ho anche inserito il controllo sul numero di parole, dovresti trovarlo facilmente coi commenti 

#include <stdio.h> #include <stdlib.h> #include <string.h> #define LUNG_STRING 61 int main() { int i,d,r; char stringa[LUNG_STRING]; int quante_parole=0; int n_blank=0; /* numero di spazi */ float media_parole; printf("Inserisci una stringa di caratteri separati da spazi\n\n"); gets(stringa); i=1; while(stringa[i]!='\0') { if ((stringa[i]==' ')&&(stringa[i-1]!=' ') /* conto le parole */ quante_parole++; i++; } if (stringa[i-1]!=' ') quante_parole++; if((quante_parole>5)) /* verifico che non sono state inserite più di 5 parole */ printf("\nSono state inserite troppe parole\n"); else printf("Le parole presenti nella fase sono %d\n",quante_parole); d=1; while(stringa[d]!='\0') { if(stringa[d]==' ' &&(stringa[i-1]!=' ')) /* conto gli spazi */ n_blank++; d++; } strlen(stringa); /* prima calcolo la lunghezza della stringa e poi sottraggo il numero di spazi; se divido per il numero di parole trovo la lunghezza media */ r = strlen(stringa); media_parole = ((float)r - (float)n_blank)/(float)quante_parole; printf("La lunghezza media delle parole e': %f\n",media_parole); return EXIT_SUCCESS; }
Il grosso problema di gets, come descritto anche nel link che ho postato in precedenza, è che non esegue alcuna verifica sul limite della stringa. La funzione che andrebbe sempre usata al suo posto è fgets. Quindi la riga in cui leggi la stringa dovrebbe essere modificata per usare questa funzione:
Sarebbe opportuno aggiungere anche il codice per verificare che l'intera riga sia stata letta.. Ma per ora assumiamo che nessuno inserisca righe più lunghe.
Gli spazi potrebbero essere di diverso tipo, ma lo standard contiene una funzione chiamata isspace nella libreria ctype.h da usare per riconoscerli. Consiglio l'uso di tale funzione in modo da considerare nello stesso modo anche '\n' o '\t' o altro. Sembrerebbe in effetti necessario per riconoscere l'ultima parola nel seguente frammento di codice:
Questa semplice modifica permette infatti l'eliminazione del codice seguente, aggiunto evidentemente per risolvere il problema:
Osserva che fgets legge e inserisce nella stringa anche '\n' per cui l'ultimo carattere è sempre una specie di spazio..
I due cicli, quello di conteggio delle parole e quello di conteggio degli spazi potrebbero poi essere fusi nello stesso ciclo.. Anche la funzione strlen contiene un ulteriore ciclo dello stesso tipo che potrebbe essere fuso. Credo sia comunque meglio un approccio diverso, basato su di un array in cui inserire la lunghezza di ogni parola come già consigliato.
fgets(stringa, LUNG_STRING, stdin);
Sarebbe opportuno aggiungere anche il codice per verificare che l'intera riga sia stata letta.. Ma per ora assumiamo che nessuno inserisca righe più lunghe.
Gli spazi potrebbero essere di diverso tipo, ma lo standard contiene una funzione chiamata isspace nella libreria ctype.h da usare per riconoscerli. Consiglio l'uso di tale funzione in modo da considerare nello stesso modo anche '\n' o '\t' o altro. Sembrerebbe in effetti necessario per riconoscere l'ultima parola nel seguente frammento di codice:
i=1; while(stringa[i]!='\0') { if ((stringa[i]==' ')&&(stringa[i-1]!=' ') /* conto le parole */ quante_parole++; i++; }
Questa semplice modifica permette infatti l'eliminazione del codice seguente, aggiunto evidentemente per risolvere il problema:
if (stringa[i-1]!=' ') quante_parole++;
Osserva che fgets legge e inserisce nella stringa anche '\n' per cui l'ultimo carattere è sempre una specie di spazio..
I due cicli, quello di conteggio delle parole e quello di conteggio degli spazi potrebbero poi essere fusi nello stesso ciclo.. Anche la funzione strlen contiene un ulteriore ciclo dello stesso tipo che potrebbe essere fuso. Credo sia comunque meglio un approccio diverso, basato su di un array in cui inserire la lunghezza di ogni parola come già consigliato.
Sisi, diciamo che questo metodo un po strano rende la media della lunghezza delle parole, indipendente dal conteggio della lunghezza delle parole..
Grazie per tutti i consigli, soprattutto quello riguardo la funzione gets
Il problema è che non riesco a scandire le parole carattere per carattere sino a quando non incontro e dire quanti caratteri ho contato...
Grazie per tutti i consigli, soprattutto quello riguardo la funzione gets

Il problema è che non riesco a scandire le parole carattere per carattere sino a quando non incontro e dire quanti caratteri ho contato...
Iterando lungo la stringa puoi immaginare di trovarti in uno di due "stati": successione di spazi o parola. Si passa da uno stato all'altro quando viene incontrato un carattere diverso dall'insieme di caratteri ammessi in quello spazio e si esce dal ciclo quando si incontra il terminatore della stringa. Quando si è nello spato corrispondente alle parole si può allora incrementare il numero di caratteri della parola corrispondente. Il codice dovrebbe apparire più o meno come il seguente (non l'ho provato e sono possibili anche grosse modifiche), ma dovrebbe darti qualche idea..
i = 0; // carattere corrente p = -1; // parola corrente while (1) { /* ciclo infinito.. */ while ( isspace(stringa[i]) ) i++; /* ignora spazi.. */ if (stringa[i] == '\0') break; /* esci dal ciclo quando la stringa è terminata.. */ p++; /* inizia una nuova parola.. */ if (p > 4) { /* gestire errore troppe parole.. */ } do { numero_caratteri[p]++; i++; } while ( !isspace(stringa[i]) && stringa[i] != '\0' ); } len = i; /* la lunghezza della stringa è uguale all'indice di '\0'.. */
"Obidream":
Sisi, diciamo che questo metodo un po strano rende la media della lunghezza delle parole, indipendente dal conteggio della lunghezza delle parole..
Grazie per tutti i consigli, soprattutto quello riguardo la funzione gets
Il problema è che non riesco a scandire le parole carattere per carattere sino a quando non incontro e dire quanti caratteri ho contato...
sicuramente ci sono soluzioni piu eleganti, ma la prima che mi viene in mente, semplice e rude è questa:
ti crei un array di interi di 5 elementi che andrà a contenere la lunghezza di ogni singola parola, ed un contatore intero che tiene traccia delle parole effettivamente lette. Ovviamente il tutto inizializzato a 0.
Partendo dall'ovvio presupposto che una stringa è un array di caratteri, con un indice ti scandisci lo stringone acquisito da tastiera. Se il carattere corrente è diverso dal blank (quindi lo spazio bianco) significa che stai scandendo ancora una parola, ed incrementi il contatore. Arrivato al blank (ovvero la parola è terminata), se sei alla prima parola (fondamentale questa considerazione) ti salvi il valore dell'indice corrente nella prima cella dell'array. Ora altro giro altra musica, la prima parola l'hai letta, quindi vai avanti con la tua iterazione fino al successivo spazio bianco. Arrivato a questo punto, nell'array non ti salvi piu il valore dell'indice corrente, ma il valore dell'indice corrente MENO la lunghezza della stringa calcolata in precedenza, e che ti sei salvato dentro all'array.
Quindi dovrai mantenerti anche un indice, una variabile o quello che ti pare, che ti dice quante parole hai trovato fino a quel momento.
Una volta che ti sei ricavato questo array, ed hai questo indice che ti indica le parole effettivamente lette (occhio alla dimensione di quest'ultimo indice), puoi dare tutto in pasto alla funzione che ti andrà a calcolare tutte le statistiche di questo mondo.
Eccomi di nuovo! Ho fatto una specie di funzione ma non riesco ancora a far funzionare il programma...
void c(char str[]) { int ctChar=0; // conterà i caratteri di ogni parola int i=0; //contatore per scorrere la stringa int wordStat[60]; //array che "conteggia" le statistiche wordStat[60]=0; while(str!='\0') { if(str[i]==' ') // se ha raggiunto una nuova parola { wordStat[ctChar]++; ctChar=0; } else ctChar++; i++; } for(i=0; i<60; i++) //scorre l´array delle statistiche if(wordStat[i]>0) printf("%d parola è/sono di %d caratteri\n", wordStat[i], i); }
Ho risolto, grazie a tutti per l'aiuto

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define LUNG_STRING 60 #define TRUE 1 #define FALSE 0 #define N_PAROLE 5 int main() { int indice,vett[LUNG_STRING+1],cont_str,tot_carat; int sono_in_parola,quante_parole,cont_carat,lenght_stringa; char stringa[LUNG_STRING+1]; printf("inserisci una stringa di max %d caratteri e contenente max %d parole:\n", LUNG_STRING, N_PAROLE); gets(stringa); lenght_stringa=strlen(stringa); if(lenght_stringa>LUNG_STRING) printf("Sono stati inseriti troppi caratteri\n"); else { for(indice=0; indice <= LUNG_STRING; indice++) vett[indice] = 0; /* */ sono_in_parola=FALSE; /* si inializza a FALSE perché non ho ancora scandito la stringa */ cont_carat=0; quante_parole=0; /* Tutte le variabili sono inizializzate a zero */ cont_str=0; tot_carat=0; while(cont_str<=lenght_stringa) { if(!sono_in_parola) { if(isalpha(stringa[cont_str])) { sono_in_parola=TRUE; cont_carat++; } } else /* sono in parola */ { if(isalpha(stringa[cont_str])) cont_carat++; else { quante_parole++; sono_in_parola=FALSE; vett[cont_carat]++; tot_carat = tot_carat+cont_carat; cont_carat=0; } } cont_str++; } if(quante_parole<(N_PAROLE+1)) { printf("La stringa contiene %d parole\n", quante_parole); printf("La lunghezza media delle parole e' %.2f\n",(float)tot_carat / (float)quante_parole); printf("La stringa contiene:\n"); for(indice = 1; indice <= LUNG_STRING; indice++) if(vett[indice] > 0) printf (" %2d parole da %d caratteri\n",vett[indice], indice); } else printf("Sono state inserite piu' di %d parole\n",N_PAROLE); } return EXIT_SUCCESS; }