[C] Problema conteggio vocali
Salve a tutti!
Ecco la consegna del mio esercizio:
"Scrivere un programma C che legga una frase introdotta da tastiera. La frase è terminata
dall’introduzione del carattere di invio. La frase contiene sia caratteri maiuscoli che caratteri
minuscoli e complessivamente al più 100 caratteri. Il programma dovrà stampare su schermo le
seguenti informazioni:
• per ognuna delle lettere dell’alfabeto, il numero di volte che la lettera compare nella stringa
• il numero di consonanti presenti nella stringa
• il numero di vocali presenti nella stringa.
Il programma deve gestire l'input in modo sicuro."
Premetto che il programma funziona e anche se magari si potrebbero fare delle migliorie, lasciatemelo così com'è: devo inviarlo ai prof per farmelo correggere quindi lascio a loro il compito di consigliarmi del codice più efficiente.
Il punto è che nel conteggio delle vocali non vengono lette quelle accentate.
Per esempio se scrivo "città", il programma mi dice:
La frase è composta da 5 caratteri.
Hai inserito 1 vocale.
Hai inserito 3 consonanti.
Come è possibile?
(Come potete vedere nel codice sottostante nello switch per il conteggio delle vocali le ho inserite.
)


Ecco la consegna del mio esercizio:
"Scrivere un programma C che legga una frase introdotta da tastiera. La frase è terminata
dall’introduzione del carattere di invio. La frase contiene sia caratteri maiuscoli che caratteri
minuscoli e complessivamente al più 100 caratteri. Il programma dovrà stampare su schermo le
seguenti informazioni:
• per ognuna delle lettere dell’alfabeto, il numero di volte che la lettera compare nella stringa
• il numero di consonanti presenti nella stringa
• il numero di vocali presenti nella stringa.
Il programma deve gestire l'input in modo sicuro."
Premetto che il programma funziona e anche se magari si potrebbero fare delle migliorie, lasciatemelo così com'è: devo inviarlo ai prof per farmelo correggere quindi lascio a loro il compito di consigliarmi del codice più efficiente.


Il punto è che nel conteggio delle vocali non vengono lette quelle accentate.
Per esempio se scrivo "città", il programma mi dice:
La frase è composta da 5 caratteri.
Hai inserito 1 vocale.
Hai inserito 3 consonanti.
Come è possibile?


(Come potete vedere nel codice sottostante nello switch per il conteggio delle vocali le ho inserite.

#include <stdio.h> #include <stdlib.h> #include <string.h> #define LETTERE 26 #define MAX 100 int main() { int lunghezza_della_frase = 0; int conta_vocali = 0; int conta_consonanti = 0; char frase[MAX + 1]; int i; int posizione; int conta_lettere[LETTERE]; printf("Scrivere una frase [ Massimo 100 caratteri ]:\n\n"); scanf("%[^\n]", &frase); // In questo modo evito di contare il ritorno a capo lunghezza_della_frase = strlen(frase);//Calcolo la lunghezza della frase printf("\nLa frase e' composta da %d caratteri.", lunghezza_della_frase); if ( lunghezza_della_frase > 100 ){ //controllo input printf("\n\nErrore! Inserire al piu' 100 caratteri!\n\n"); system("pause"); exit(0); } for (i = 0; i < LETTERE; i++) conta_lettere[i] = 0 ; //conteggio di quante volte una lettera compare nella frase for (i = 0; i < lunghezza_della_frase; i++){ if ( frase[i] >= 'A' && frase[i] <= 'Z'){ posizione = frase[i] - 'A'; conta_lettere[posizione]++; } else { if(frase[i] >= 'a' && frase[i] <= 'z'){ posizione = frase[i] - 'a'; conta_lettere[posizione]++; } } } printf("\n\n"); for (i = 0; i < LETTERE; i++){ if(conta_lettere[i] != 0){ printf ("La lettera %c compare %d volte \n",'A'+i, conta_lettere[i]);} } for(i = 0; i < lunghezza_della_frase; i++){ switch(frase[i]) //conteggio delle vocali { case 'a': case 'e': case 'i': case 'o': case 'u': case 'A': case 'E': case 'I': case 'O': case 'U': case 'à': case 'è': case 'é': case 'ì': case 'ò': case 'ù': conta_vocali++; break; } } printf("\nHai inserito %d vocali.\n", conta_vocali); for(i = 0; i < lunghezza_della_frase; i++){ switch(frase[i]) //conteggio delle consonanti { case 'q': case 'w': case 'r': case 't': case 'y': case 'p': case 's': case 'd': case 'f': case 'g': case 'h': case 'j': case 'k': case 'l': case 'z': case 'x': case 'c': case 'v': case 'b': case 'n': case 'm': case 'Q': case 'W': case 'R': case 'T': case 'Y': case 'P': case 'S': case 'D': case 'F': case 'G': case 'H': case 'J': case 'K': case 'L': case 'Z': case 'X': case 'C': case 'V': case 'B': case 'N': case 'M': conta_consonanti++; break; } } printf("\nHai inserito %d consonanti.\n", conta_consonanti); printf("\n\n\n"); system("pause"); return 0; }
Risposte
Ciao
dipende dal fatto che la lettera "à" appartiene alla parte "estesa" della tabella ASCII.
La parte estesa, ovvero i codici ASCII superiori al 127, sono sono univoci in tutti le lingue.
Ti suggerirei di dichiarare "frase" come unsigned char, e nello switch invece di mettere "à" usa il valore decimale 133
Di conseguenza anche le altre lettere accentate.
Ho provato con il debugger di CodeBlocks e funziona
Fammi sapere
Ciao
dipende dal fatto che la lettera "à" appartiene alla parte "estesa" della tabella ASCII.
La parte estesa, ovvero i codici ASCII superiori al 127, sono sono univoci in tutti le lingue.
Ti suggerirei di dichiarare "frase" come unsigned char, e nello switch invece di mettere "à" usa il valore decimale 133
Di conseguenza anche le altre lettere accentate.
Ho provato con il debugger di CodeBlocks e funziona
Fammi sapere
Ciao
Sei un genio!
Ora mi conta anche le vocali accentate!
Però ora sorge un altro problema ahahah (sono un guastafeste lo so
)
Quando stampo a video quali lettere sono state inserite non mi conta ad esempio la a accentata(esempio di prima).
Mi spiego:
io scrivo "città" e il programma mi dice:
La lettera C compare 1 volta.
La lettera I compare 1 volta.
La lettera T compare 2 volte.
Hai inserito 2 vocali.
Hai inserito 3 consonanti.



Ora mi conta anche le vocali accentate!

Però ora sorge un altro problema ahahah (sono un guastafeste lo so

Quando stampo a video quali lettere sono state inserite non mi conta ad esempio la a accentata(esempio di prima).
Mi spiego:
io scrivo "città" e il programma mi dice:
La lettera C compare 1 volta.
La lettera I compare 1 volta.
La lettera T compare 2 volte.
Hai inserito 2 vocali.
Hai inserito 3 consonanti.
Si lo so. L'ho visto facendo il debug. Vuoi provare a risolverlo tu o ti serve una mano?
Se riesci, una mano sarebbe gradita!
Conta che ho iniziato quest'anno l'università e faccio programmazione da solo un mese e mezzo!
Grazie mille in anticipo!


Conta che ho iniziato quest'anno l'università e faccio programmazione da solo un mese e mezzo!

Grazie mille in anticipo!

Ok volentieri ti do una mano. Oggi sono un pochino preso ma domani posso dedicarmici volentieri. E' un problema se stravolgo un po' il programma? (non è detto, parlo in caso di necessità
)

Al di là della questione delle vocali, il tuo codice non “gestisce l'input in modo sicuro”. Questo perché scanf non è una funzione molto sicura, e non ha senso usarla per leggere stringhe.
La funzione sicura da usare è fgets (da non confondere con gets, che non fa più parte dello standard).
Siccome al massimo puoi avere 100 caratteri allora dovresti scrivere le cose così:
La ragione del 102 è che devi inserire 100 caratteri, l'invio e il \0.
La soluzione di usare direttamente il valore non è in generale consigliata e andrebbe evitata.
La funzione sicura da usare è fgets (da non confondere con gets, che non fa più parte dello standard).
Siccome al massimo puoi avere 100 caratteri allora dovresti scrivere le cose così:
frase[102]; if(fgets(frase,sizeof(frase),stdin) == NULL) { \* codice errore *\ }
La ragione del 102 è che devi inserire 100 caratteri, l'invio e il \0.
La soluzione di usare direttamente il valore non è in generale consigliata e andrebbe evitata.
@vict85: di solito la evito anche io, era per indirizzare a pesare al fatto che il carattere "à" in questo caso viene dal compilatore con un valore diverso da quello corretto.
In questo caso la lettera "à" viene interpretata correttamente come 133 della tabella ASCII ma poi viene visto come "..." all'interno del programma
Dipende dal charset che viene utilizzato dal compilatore per la parte estesa della tabella.
Io fino ad ora non ho trovato un modo univoco per ovviare al problema se non verificando quali codici mi vengono restituiti quando vengono premuti caratteri accentati e poi reagire di conseguenza.
In questo caso la lettera "à" viene interpretata correttamente come 133 della tabella ASCII ma poi viene visto come "..." all'interno del programma
Dipende dal charset che viene utilizzato dal compilatore per la parte estesa della tabella.
Io fino ad ora non ho trovato un modo univoco per ovviare al problema se non verificando quali codici mi vengono restituiti quando vengono premuti caratteri accentati e poi reagire di conseguenza.