Domanda Primo carattere viene cancellato

enk17

Utente Bronze
23 Ottobre 2021
69
17
8
37
Salve stavo scrivendo questo codice in cui preso in input una frase dice quante consonanti ci sono, non riesco a fixare questo bug ovvero la seconda frase che viene inserita il primo carattere viene sempre cancellato e non capisco perchè. (non posso usare le funzioni)

C++:
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <conio.h>

using namespace std;

int main()
{
    string frase,frase_s;
    int consonanti=0,p_frasi,lun,len;
    cout<<"quanti frasi vuoi analizzare? ";
    cin>>p_frasi;
    
    
while(p_frasi>0)
{
    p_frasi--;
    cout<<"inserisci la frase : ";
    cin.ignore();
    getline(cin,frase);
    frase_s=frase;
    
    lun=frase.size();
    len=lun;   
    for(int x=0; x<lun; x++)
    {
    for (int i = 0; i < lun; i++)
        {
            if (frase[i]==' ')
            {
                frase.erase(i,1);
                lun--;
                i--;
            }
        }   
    }
    for(int x=0;x<len; x++)
    {
        if(frase[x] != 'a' && frase[x]!= 'e' && frase[x]!= 'i' && frase[x] != 'o' && frase[x] != 'u' )
        {
        consonanti++;
        }
    }
cout<<"la frase "<<frase_s<<" e' lunga "<<lun<<" ed contiene "<<consonanti<<" consonanti "<<endl;
//stampa dei risultati
}

return 0;

}
 
È dovuto a cin.ignore() che serve proprio ad ignorare un carattere dall'input. Spostalo prima del loop while. Inoltre, la variabile consonanti deve essere resettata a zero dopo ogni iterazione del ciclo.
 
Il problema lo ha illustrato SpeedJack, ma c'è ne sono altri: stai cancellando gli spazi, accorciando la stringa, ma poi fai un ciclo in base alla lunghezza precedente, il che risulta in una lettura fuori dal buffer e il conseguente undefined behavior. Poi non resetti il contatore delle consonanti tra una stringa e l'altra e infine le vocali maiuscole e i simboli (punti, virgole, numeri ecc) verranno contati come consonanti. Ti scrivo la mia idea sul come risolvere tutti questi problemi:

C++:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    int n_frasi;
    string frase;
    cout << "Quante frasi vuoi analizzare? ";
    cin >> n_frasi;
    cin.ignore();

    while (n_frasi--)
    {
        cout << "Inserisci la frase: ";
        getline(cin, frase);
        int len = frase.size();
        int c, consonanti = 0, vocali = 0;

        for (int i = 0; i < len; i++)
        {
            c = frase[i];
            if ('a' <= c && c <= 'z')
                c -= 32;
            if ('A' <= c && c <= 'Z')
            {
                if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
                    vocali++;
                else
                    consonanti++;
            }
        }

        cout << "Frase: " << frase << endl
            << "N. Caratteri: " << len << endl
            << "N. Lettere: " << (consonanti + vocali) << endl
            << "N. Consonanti: " << consonanti << endl
            << "N. Vocali: " << vocali << endl;
    }

    return 0;
}
 
  • Geniale
Reazioni: enk17
Ultima modifica:
È dovuto a cin.ignore() che serve proprio ad ignorare un carattere dall'input. Spostalo prima del loop while. Inoltre, la variabile consonanti deve essere resettata a zero dopo ogni iterazione del ciclo.
Vero che stupido, grazie.
Messaggio unito automaticamente:

Il problema lo ha illustrato SpeedJack, ma c'è ne sono altri: stai cancellando gli spazi, accorciando la stringa, ma poi fai un ciclo in base alla lunghezza precedente, il che risulta in una lettura fuori dal buffer e il conseguente undefined behavior. Poi non resetti il contatore delle consonanti tra una stringa e l'altra e infine le vocali maiuscole e i simboli (punti, virgole, numeri ecc) verranno contati come consonanti. Ti scrivo la mia idea sul come risolvere tutti questi problemi:

C++:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    int n_frasi;
    string frase;
    cout << "Quante frasi vuoi analizzare? ";
    cin >> n_frasi;
    cin.ignore();

    while (n_frasi--)
    {
        cout << "Inserisci la frase: ";
        getline(cin, frase);
        int len = frase.size();
        int c, consonanti = 0, vocali = 0;

        for (int i = 0; i < len; i++)
        {
            c = frase[i];
            if ('a' <= c && c <= 'z')
                c -= 32;
            if ('A' <= c && c <= 'Z')
            {
                if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
                    vocali++;
                else
                    consonanti++;
            }
        }

        cout << "Frase: " << frase << endl
            << "N. Caratteri: " << len << endl
            << "N. Lettere: " << (consonanti + vocali) << endl
            << "N. Consonanti: " << consonanti << endl
            << "N. Vocali: " << vocali << endl;
    }

    return 0;
}
stai cancellando gli spazi, accorciando la stringa
è una cosa voluta.
i simboli (punti, virgole, numeri ecc) verranno contati come consonanti.
stavo pensando di creare un array di simboli e confrontarli però mi da errore
Messaggio unito automaticamente:

non ho capito a cosa serve questo contatore
 
non ho capito a cosa serve questo contatore

Serve a convertire le minuscole in maiuscole, in modo da trovare le vocali in entrambe le forme controllando le lettere solo come maiuscole. 32 perché in ASCII c'è una distanza di 32 tra le lettere maiuscole e quelle minuscole: la a minuscola è 97, mentre la A maiuscola è 65 ecc.
Il codice che ho postato ignora i simboli (non li conta nè come lettere nè come vocali o consonanti), questo grazie al controllo che verifica se il carattere si trova tra la A e la Z. Il punto ad esempio in ASCII è 46, lo spazio è 32 e questi non vengono considerati dall'if che va da A (65) a Z (90)
 
  • Mi piace
Reazioni: enk17