[C] Problema conteggio vocali

pippopluto95
Salve a tutti! :-D :-D

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. :D :D

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? :? :shock:
(Come potete vedere nel codice sottostante nello switch per il conteggio delle vocali le ho inserite. :cry: )

#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
Summerwind78
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

pippopluto95
Sei un genio! =D> =D> :-D
Ora mi conta anche le vocali accentate! :smt023

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

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.

Summerwind78
Si lo so. L'ho visto facendo il debug. Vuoi provare a risolverlo tu o ti serve una mano?

pippopluto95
Se riesci, una mano sarebbe gradita! :D :D
Conta che ho iniziato quest'anno l'università e faccio programmazione da solo un mese e mezzo! :?
Grazie mille in anticipo! :smt023

Summerwind78
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à :) )

vict85
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ì:
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.

Summerwind78
@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.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.