Istogrammi e vettori

di il
11 risposte

Istogrammi e vettori

Ciao ragazzi, ho ancora bisogno di voi.
Non riuscendo a trovare una discussione che fa al caso mio, ne avvio un'altra, su un argomento piuttosto battuto.
Sto cercando di portare a termine un esercizio che mi chiede di stampare un istogramma che rappresenti la lunghezza delle parole che riceve in input e sto cercando di capire come riprodurne uno a barre orizzontali, ma non mi è molto chiaro (e nel codice questo è chiarissimo), come riuscire a stampare gli elementi che sono stati memorizzati nei vettori.
Questo è il tentativo che mi sembra il migliore di tutti quelli fatti fino adesso.

#include <stdio.h>
#define IN  1           //siamo all'interno di una parola
#define OUT 0           //siamo all'esterno di una parola

int main()
{
    int c, i, n, j, k, state;
    int nletter [20];
    int nword [1000];

    for (i = 0; i <= 20; ++i)
        nletter[i] = 0;
                                //l'intenzione sarebbe quella di riuscire a far memorizzare il numero delle lettere
                                //delle parole immesse in un vettore "nletter"

    for (n = 0; n <= 1000; ++n)
        nword[n] = 0;
                                //quando il carattere immesso identifica l'inizio di un'altra parola, la lunghezza memorizzata
                                //dovrebbe venire memorizzata da un altro vettore "nword" che successivamente verrà stampato
                                //sotto forma di asterischi, i quali andranno a individuare le colonne dell'istogramma

                                //Si può fare tutto con un vettore solo?


    state = OUT;
    while ((c = getchar()) != EOF)
       {
        if (c == '\n' || c == '\t' || c == ' ')     //se il carattere immesso è "a capo", "tabulazione", "spazio", siamo di fronte
                                                            //ad una nuova parola, lo state è OUT
            state = OUT;
            else if (state == OUT)
                ++nword[n];
            {
                state = IN;
                ++nletter[i];
            }

       }

    for (k = 0; k <= nword[n]; ++k)
    {
    for (j = 0; j <= nletter [i]; ++j)
    putchar ('*');
    putchar ('\n');
    }
}
nei commenti inseriti nel codice ho messo le mie intenzioni, nel codice ho provato a mettere tutto quello che ho imparato finora.
Credo di far confusione con i vettori, anche se avevo sperato di averne colto il senso.
Il compilatore che sto usando al momento è Code::Blocks 17.12 e non ne ricavo nulla, nè un errore, nè un output.
Siate clementi nei commenti, ripeto che sono un amatore, che si diletta con il C solo per passione, con tutti i miei limiti.
Grazie ancora per la vostra disponibilità.

11 Risposte

  • Re: Istogrammi e vettori

    Se sei solo un amatore, e vuoi solo giocare con la programmazione, lascia perdere il C, il C++, Java e C#.

    Sono tutti linguaggi 'rognosi' per un motivo o per l'altro

    Passa a Python: puoi fare quello che fai in C, ma con moooolte meno rogne.

    Anche lui (Python) ha le sue belle rognette, ma solo quando uno se ne rende conto e le trova limitative, ha senso passare ad un linguaggio piu' complesso.

    Nota 1: il codice che stai guardando, nella sua semplicita', e' abbastanza sofisticato perche' fa uso di un AUTOMA A STATI FINITI per leggere la stringa di input, non esattamente una cosa banale da capire (anche se non e' cosi' complicato).

    Nota 2: il codice e' pure sbagliato: nessuno inizializza e modifica 'n', e dove viene fatto NON HA NIENTE A CHE FARE con il suo utilizzo successivo.
  • Re: Istogrammi e vettori

    Grazie per la risposta, anche se speravo di poter affrontare il C attraverso il Kernighan & Ritchie e poter imparare qualcosa seguendo passo passo gli esercizi proposti.
    Per quanto riguarda n mi sembrava di aver capito che la sua inizializzazione potesse essere lasciata al for
    
    for (n = 0; n <= 1000; ++n)
    [\code]
    
    come risolvreste il problema?
  • Re: Istogrammi e vettori

    Scusa potresti fare qualche esempio? Non ho ben capito cosa dovrebbe fare il programma!
  • Re: Istogrammi e vettori

    Il programma dovrebbe stampare un istogramma a barre orizzontali (siano esse asterischi o qualsiasi altro carattere), le quali dovrebbero essere lunghe tanto quanto le parole immesse da tastiera.
    Se io immetto la frase:

    "Caro Babbo Natale vorrei veder funzionare il programma"

    L'output dovrebbe essere

    ****
    *****
    ******
    ******
    *****
    **********
    **
    *********
  • Re: Istogrammi e vettori

    Non basterebbe semplicemente
    int main()
    {
        int c;
        while((c = getchar()) != '\n')
        {
            if(c == '\t' || c == ' ')
            {
                printf("\n");
            }
            else
            {
                printf("*");
            }
        }
    }
    o mi sfugge qualcosa?
  • Re: Istogrammi e vettori

    Probabilmente hai ragione e il colpo di genio si vede nella semplicità della soluzione... mi sono intestardito sull'uso di vettori, perché nel K&R l'esercizio viene proposto dopo la loro introduzione e volevo sperimentarne l'utilizzo.
    Proverò ad aggiungere al codice la possibilità di inserire parole separate anche da '\n', ma per il momento la tua soluzione è decisamente elegante. Grazie Nippolo, il tuo è stato davvero un prezioso contributo.
  • Re: Istogrammi e vettori

    Di niente!
  • Re: Istogrammi e vettori

    Con un unico vettore potresti fare una cosa del genere:
    #include <stdio.h>
    #include <ctype.h>
    
    int main() {
        char frase[1024], *p=frase;
    
        fgets( frase, 1024, stdin );
        
        while( *p ) {
            putchar( !isspace(*p++) ? '*' : '\n' );
        }
    
        return 0;
    }
  • Re: Istogrammi e vettori

    Urca! Questo è molto di piùdi quello che sono in grado di capire a questo punto del mio studio. Grazie mille per l'aiuto, adesso comincio a pensare che l'esercizio proposto dagli autori non fosse altro che un trabocchetto.
    Faccio tesoro di questi suggerimenti e me li portò dietro proseguendo nel mio studio.
    Grazie a tutti e al prossimo topic!
  • Re: Istogrammi e vettori

    La complicazione è più apparente che reale, si tratta giusto di cercare sul tuo libro un po' di cose. in particolare:

    1) come funziona fgets() (che è in stdio.h)
    2) cos'è un puntatore
    3) come funzionano gli operatori di incremento e decremento (++ e --)
    3) cosa significa "incrementare un puntatore"
    4) come funzionano putchar() (che è in stdio.h) e isspace() (che è in ctype.h)
    5) come funziona l'operatore ternario ?:
    #include <stdio.h>
    #include <ctype.h>
    
    int main() {
        char frase[1024]; // un vettore di 1024 char, usati come buffer
        char *p = frase;  // un puntatore a char, inizializzato per puntare a frase
    
        fgets( frase, 1024, stdin ); // libreria standard: preleva una stringa da
                                     // uno stream (in questo caso stdin) e la
                                     // immette nel vettore frase; il limite della
                                     // stringa ottenibile e' di 1023 caratteri
       
        while( *p ) { // fintanto che il puntatore non punta a '\0', cioe' fintanto
                      // che non si arriva alla fine della stringa immessa nel
                      // vettore da fgets()...
            
            putchar( !isspace(*p++) ? '*' : '\n' );
            
            // in quest'ultima riga trovi, condensate:
            // 1) una chiamata alla funzione di libreria isspace(), che serve a
            //    verificare se un determinato carattere e' o non e' uno spazio;
            // 2) l'uso dell'operatore ternario ?: (cerca sul tuo libro, che c'e'
            //    di sicuro ed non e' cosi' complicato come sembra)
            // il senso complessivo e' "se' p non punta, nel vettore frase, a un
            // carattere spaziatore, chiama putchar() con '*', altrimenti chiama
            // putchar() con '\n'"
            
            // nota che il puntatore p viene incrementato di una posizione con '++',
            // il che fa si' che dopo la verifica del suo contenuto punti al
            // carattere successivo, pronto per la prossima ripetizione del ciclo
        }
    
        return 0;
    }
    Volendo toglierti dai piedi un po' di cose, se per te sono nuove, puoi scrivere la stessa cosa senza usare i puntatori, così:
    #include <stdio.h>
    #include <ctype.h>
    
    int main() {
        char frase[1024];
        int i;
    
        fgets( frase, 1024, stdin );
    
        for( i=0; frase[i]; i++ ) {
            putchar( !isspace(frase[i]) ? '*' : '\n' );
        }
    
        return 0;
    }
    Diventa ancor più lineare se eliminiamo l'operatore ternario, sostituendolo con un comune if:
    #include <stdio.h>
    #include <ctype.h>
    
    int main() {
        char frase[1024];
        int i;
    
        fgets( frase, 1024, stdin );
    
        for( i=0; frase[i]; i++ ) {
            if( !isspace(frase[i]) )
                putchar( '*' );
            else putchar( '\n' );
        }
    
        return 0;
    }
    Le tre versioni, sostanzialmente, fanno la stessa cosa.

    P.S. Anch'io sono un hobbista, per cui sei in buona compagnia.
  • Re: Istogrammi e vettori

    Grande! Così mi sento meno solo e meno vittima della frustrazione! Ma non voglio mollare la presa, mi affascina troppo questo mondo e da troppo tempo e ora che riesco a dedicarmici un po' mi piace l'idea di spaccarmi un po' la testa!
Devi accedere o registrarti per scrivere nel forum
11 risposte