[C] Esercizio sequenza numeri

floppyes
Ciao a tutti!

Non riesco proprio a capire come risolvere la parte finale di questo esercizio:
Si sviluppi un programma in linguaggio C che riceva in ingresso una sequenza di al più 100 numeri interi diversi da zero, terminata da uno zero, e mostri a video la sequenza dei numeri distinti (senza ripetizioni) ricevuti, ciascuno accompagnato dalla frequenza di apparizione nella sequenza
d’ingresso.
Ad esempio, se si riceve la sequenza: 12 10 -8 10 10 12 3 0
il programma dovrà mostrare a video:
12: 28.6%
10: 42.8%
-8: 14.3%
3: 14.3%


La prima parte del programma sono riuscito a scriverla:
#include <stdio.h>
#define DIM1 5

int main ()
{
    int vet[DIM1], i,j;
    
    printf("Inserisci %d numeri:\n", DIM1);
    for (i=0;i<DIM1;i++)
    {
        printf("\t ==> Numero %d: ", (i+1));
        scanf("%d", &vet[i]);
        if (vet[i]==0)
        {
            break;
        }
    }
    printf("\nNumeri inseriti:\n");
    for (i=0;i<DIM1;i++)
    {
        printf("\t%d ", vet[i]);
    }
    return 0;
}


Quello che non riesco a fare è la parte finale dell'esercizio: mostrare i singoli numeri inseriti con la loro percentuale. Riuscite a darmi qualche dritta? :-D

Grazie in anticipo
Ciaoo!

Risposte
Atem1
vettore.contatore/n è una divisione fra interi che restituisce un numero intero.
Ad esempio 5/10 ti restituisce 0 perchè nella divisione fra interi 5/10=0 con il resto di 5.
Qualsiasi valore che dividi per N darà sempre 0 visto che N è maggiore di qualsiasi "contatore".
Quindi prima devi fare un operazione di cast.

perc=(double) vettore.contatore/ n;
oppure
perc=vettore.contatore/ (double) n;
Cioè almeno uno dei due operandi deve essere di tipo float (o double).

floppyes
Ciao!
Grazie, ho aggiornato il codice così:
printf("\n\nPercentuali:\n\t");
for (i=0;i<dim;i++)
{
perc[i]=(double) (vettore[i].contatore/n)*100;
printf("%f ", perc[i]);
}

Però se provo ad immettere la stringa di esempio dell'esercizio:
12 10 -8 10 10 12 3 0

dovrebbe uscire
28.6% 42.8% 14.3% 14.3%

Invece da me esce:
0.000000 0.000000 409600.000000 409600.000000 409600.000000 
:cry:

Grazie ancora
Ciaoo :)

Atem1
Se scrivi così:
perc=(double) (vettore.contatore/n)*100;
è comunque una divisione fra interi.
Prima hai fatto la divisione fra interi e poi l'hai trasformato in double.
In altre parole è come se non avessi fatto assolutamente nulla.

Devi scrivere:

perc=(double) vettore.contatore/ n;
oppure
perc=vettore.contatore/ (double) n;

E poi se ci sono degli errori prova a postare il codice intero.

vict85
Puoi anche usare questo metodo
(a+0.)/b

oppure
a/(b+0.)

floppyes
Ciao!

Questo è il codice completo:
#include <stdio.h>
#define DIM1 10

int main()
{
    typedef struct nome_struttura
    {
    int numero;
    int contatore;
    } nuovo_tipo;
    nuovo_tipo vettore[DIM1];
    
    // Inizializzo la variabile n ed i e num
    int n=1, i, num, flag;
    double perc[DIM1];
    
    // L'utente inserisce il primo numero, lo salvo in vettore[0] ed aumento il contatore
    printf("Inserisci 10 numeri diversi da zero\n");
    printf("Inserisci il primo numero: ");
    scanf("%d", &vettore[0].numero);
    vettore[0].contatore=1;
    
    // Inizializzo la variabile dim=1
    int dim=1;
    
    // Chiedo all'utente di inserire numeri diversi da 0
    while (num!=0 && n!=DIM1)
    {
        printf("Inserisci numero %d: ", (n+1));
        scanf("%d", &num);
        flag=0;
        n++;
        for (i=0;i<dim;i++)
        {
            if (vettore[i].numero == num) 
            {
                vettore[i].contatore++;
                flag=1;
                break;
            }
        }
        if (flag == 0)
        {
            vettore[dim].numero = num;
            vettore[dim].contatore++;
            dim++;
        }
    }
    
    printf("\nSingoli numeri inseriti:\n\t");
    for (i=0;i<dim;i++)
    {
        printf("%4d", vettore[i].numero);
    }
    printf("\n\nPercentuali:\n\t");
    for (i=0;i<dim;i++)
    {
        perc[i]=(double) (vettore[i].contatore/n)*100;
        printf("%f  ", perc[i]);
    }
    return 0;
}


Ho provato a ricontrollarlo e mi sembra tutto giusto, ho cambiato anche la parte finale con il double, però la percentuale mi esce ancora sbagliata.

Grazie mille
Ciaoo :)

Atem1
L'errore è vettore[dim].contatore++; mentre devi mettere vettore[dim].contatore=1.

"floppyes":

if (flag == 0)
{
vettore[dim].numero = num;
vettore[dim].contatore++;
dim++;
}



Nel primo codice che avevi postato c'era scritto due volte:
vettore[dim].contatore=1;
mentre ora hai scritto due volte:
vettore[dim].contatore++;

Se flag==0 allora vuol dire che il numero è diverso da quelli inseriti in precedenza e quindi contatore=1.
Invece sopra (nella parte NON quotata), se X è uguale ad almeno un numero che già era stato inserito allora aumenta il suo contatore.
Quindi sopra è ++, invece sotto (nella parte che ti ho quotato) è =1
E comunque così ti salva anche lo 0 nel vettore, se vuoi che non venga contato, alla fine decrementa n, e fai finire il ciclo a dim-2 cioè i

floppyes
Ciao!

Grazie per la risposta, avevo dimenticato di rimettere l'1 al posto giusto. Ho corretto però adesso le percentuali rimangono tutte quante a 0 :(

Per evitare di aggiungere lo zero ho inserito un altro if subito dopo lo scanf, mettendo l'istruzione break e decrementando n in caso il numero sia uguale a 0. Ecco il codice:
#include <stdio.h>
#define DIM1 10

int main()
{
    typedef struct nome_struttura
    {
    int numero;
    int contatore;
    } nuovo_tipo;
    nuovo_tipo vettore[DIM1];
    
    // Inizializzo la variabile n ed i e num
    int n=1, i, num, flag;
    double perc[DIM1];
    
    // L'utente inserisce il primo numero, lo salvo in vettore[0] ed aumento il contatore
    printf("Inserisci 10 numeri diversi da zero\n");
    printf("Inserisci il primo numero: ");
    scanf("%d", &vettore[0].numero);
    vettore[0].contatore=1;
    
    // Inizializzo la variabile dim=1
    int dim=1;
    
    // Chiedo all'utente di inserire numeri diversi da 0
    while (num!=0 && n!=DIM1)
    {
        printf("Inserisci numero %d: ", (n+1));
        scanf("%d", &num);
        flag=0;
        n++;
        if (num==0)
        {
            n--;
            break;
        }
        for (i=0;i<dim;i++)
        {
            if (vettore[i].numero == num) 
            {
                vettore[i].contatore++;
                flag=1;
                break;
            }
        }
        if (flag == 0)
        {
            vettore[dim].numero = num;
            vettore[dim].contatore=1;
            dim++;
        }
    }
    
    printf("\nSingoli numeri inseriti:\n\t");
    for (i=0;i<dim;i++)
    {
        printf("%4d", vettore[i].numero);
    }
    printf("\n\nPercentuali:\n\t");
    for (i=0;i<dim;i++)
    {
        perc[i]=(double) (vettore[i].contatore/n)*100;
        printf("%f  ", perc[i]);
    }
    return 0;
}


Manca solo questa percentuale poi è perfetto :D

Grazie mille
Ciaoo!

Atem1
L'errore è qui:
perc[i]=(double) (vettore[i].contatore/n)*100;


Ti ho già risposto che mettere (double) in quella posizione equivale a non metterlo.
La divisione NON deve essere fra 2 interi, ma almeno uno dei 2 operandi deve essere double (o float).
Lo devi mettere prima di uno dei 2 operandi, non prima dell'operazione.

vict85
Alternativamente puoi anche definire contatore come un double: un double è preciso per numeri così bassi

floppyes
Ciao

Grazie mille per l'aiuto! Finalmente sono riuscito a far andare tutto il programma :D :D
Se dovesse interessare a qualcuno ecco il codice completo:
#include <stdio.h>
#define DIM1 10

int main()
{
    // Vado a definire la struttura che mi servirà per contare i numeri e quante volte sono stati inseriti
    typedef struct nome_struttura
    {
    int numero;
    int contatore;
    } nuovo_tipo;
    nuovo_tipo vettore[DIM1];
    
    /* Inizializzo le variabili che utilizzerò: n per contare fino a DIM1 in modo da inserire tutti i         numeri, num per salvare il numero che viene inserito ogni volta dall'utente, flag per determinare se il numero è uguale a uno già presente oppure se è diverso, dim per contare quante volte un numero è stato inserito.*/
    int n=1, dim=1, i, num, flag;
    double perc[DIM1];
    
    // L'utente inserisce il primo numero, lo salvo in vettore[0] e imposta il contatore ad 1.
    printf("Inserisci 10 numeri diversi da zero\n");
    printf("Inserisci il primo numero: ");
    scanf("%d", &vettore[0].numero);
    vettore[0].contatore=1;
    
    // Chiedo all'utente di inserire numeri diversi da 0 fino ad arrivare a DIM1
    while (num!=0 && n!=DIM1)
    {
        printf("Inserisci numero %d: ", (n+1));
        scanf("%d", &num);
        flag=0;
        n++;
        // Se il numero è uguale a 0 allora esco dal ciclo e vado a calcolare le percentuali
        if (num==0)
        {
            n--;
            break;
        }
        // Verifico se un numero inserito è già presente nel vettore
        for (i=0;i<dim;i++)
        {
            if (vettore[i].numero == num) 
            {
                vettore[i].contatore++;
                flag=1;
                break;
            }
        }
        // Se il numero non è presente nel vettore allora lo aggiungo
        if (flag == 0)
        {
            vettore[dim].numero = num;
            vettore[dim].contatore=1;
            dim++;
        }
    }
    
    // Stampo i singoli numeri e le loro percentuali
    printf("\nSingoli numeri:\t\tPercentuale inserimento:\n");
    for (i=0;i<dim;i++)
    {
        printf("%7d \t\t\t\t", vettore[i].numero);
        // Formula per calcolare la percentuale, devo usare il double per fare in modo da salvare anche i numeri con la virgola.
        perc[i]=(vettore[i].contatore/ (double) n)*100;
        printf("%14.1f   \n", perc[i]);
    }
    return 0;
}


Io pensavo che bastasse definire il vettore
double perc[DIM1] invece il double andava messo anche nella divisione!

Due sole domande
1) Se io provo a cambiare la dimensione di [code]DIM1
passando da 10 a 100, appena inserisco il primo numero il programma termina. Come mai questa cosa? Mi succede anche se imposto la dimensione a 20 al posto di 10.
2) Nel printf è possibile stampare il segno della percentuale %? Il codice da utilizzare non era \"%"\?


"vict85":
Alternativamente puoi anche definire contatore come un double: un double è preciso per numeri così bassi

Ciao!
Ho provato e funziona anche con il tuo metodo :) Grazie :)


Grazie ancora per l'ottimo aiuto!
Ciaoo :)

Atem1
Per visualizzare % devi scriverlo due volte quindi %%.
Invece per la prima domanda cosa intendi?

Se scrivo
#define DIM1 100


a me funziona...
E comunque il typedef sarebbe meglio metterlo prima del MAIN.

floppyes
Ciao!
Ok ho spostato il typedef prima del main :)
Se io metto
define DIM1 100

Inserisco il primo numero e poi il programma termina da solo :S



Non capisco come mai!

Grazie
Ciaoo :)

Atem1
Ehm se il codice è quello che hai inserito sopra a me non da quel problema scrivendo 100 invece di 10.
Non è che magari hai modificato qualcos'altro? Forse è meglio se riposti il codice finale con
#define DIM1 100

floppyes
Codice sempre lo stesso.. eccolo :)
#include <stdio.h>
#define DIM1 10

// Vado a definire la struttura che mi servirà per contare i numeri e quante volte sono stati inseriti
    typedef struct nome_struttura
    {
        int numero;
        int contatore;
    } nuovo_tipo;
    nuovo_tipo vettore[DIM1];
    
int main()
{
    /* Inizializzo le variabili che utilizzerò: n per contare fino a DIM1 in modo da inserire tutti i         numeri, num per salvare il numero che viene inserito ogni volta dall'utente, flag per determinare se il numero è uguale a uno già presente oppure se è diverso, dim per contare quante volte un numero è stato inserito.*/
    int n=1, dim=1, i, num, flag;
    double perc[DIM1];
    
    // L'utente inserisce il primo numero, lo salvo in vettore[0] e imposta il contatore ad 1.
    printf("Inserisci %d numeri diversi da zero\n", DIM1);
    printf("Inserisci il 1° numero: ");
    scanf("%d", &vettore[0].numero);
    vettore[0].contatore=1;
    
    // Chiedo all'utente di inserire numeri diversi da 0 fino ad arrivare a DIM1
    while (num!=0 && n!=DIM1)
    {
        printf("Inserisci il %d° numero: ", (n+1));
        scanf("%d", &num);
        flag=0;
        n++;
        // Se il numero è uguale a 0 allora esco dal ciclo e vado a calcolare le percentuali
        if (num==0)
        {
            n--;
            break;
        }
        // Verifico se un numero inserito è già presente nel vettore
        for (i=0;i<dim;i++)
        {
            if (vettore[i].numero == num) 
            {
                vettore[i].contatore++;
                flag=1;
                break;
            }
        }
        // Se il numero non è presente nel vettore allora lo aggiungo
        if (flag == 0)
        {
            vettore[dim].numero = num;
            vettore[dim].contatore=1;
            dim++;
        }
    }
    
    // Stampo i singoli numeri e le loro percentuali
    printf("\nSingoli numeri:\t\tPercentuale inserimento:\n");
    for (i=0;i<dim;i++)
    {
        printf("%7d \t\t\t\t", vettore[i].numero);
        // Formula per calcolare la percentuale, devo usare il double per fare in modo da salvare anche i numeri con la virgola.
        perc[i]=(vettore[i].contatore/ (double) n)*100;
        printf("%14.1f %%   \n", perc[i]);
    }
    return 0;
}

Con DIM1 a 10 funziona alla perfezione, con altri valori maggiori di 10 va in tilt!
Grazie
Ciaoo :)

floppyes
Sto riguardando il codice ma è tutto come prima, però ora mi si ferma al primo numero anche nel caso di
DIM1 10


Misteri del C? :D

Ciaoo!

Atem1
Magari invece di usare la #define prova ad usare
const int DIM1=100;
Comunque un modo che hai per scoprirlo è fare il DEBUG... segui passo per passo, e vedendo che valori assumono le variabili capisci qual'è il problema...

vict85
"floppyes":
Sto riguardando il codice ma è tutto come prima, però ora mi si ferma al primo numero anche nel caso di
DIM1 10

Misteri del C? :D
Ciaoo!


Semplicemente non hai inizializzato num ad un valore diverso da zero prima della condizione nel white.

Atem1
Wow è vero, io mi ero fissato sul fatto che num fosse stato inizializzato dopo il primo inserimento (cioè prima del while) quando in realtà il primo numero era stato giustamente inserito direttamente su vettore[0].numero e non su num.

floppyes
Cavolo è vero!! Ho modificato
num=1
e così è tornato a funzionare tutto!

Grazie mille per l'aiuto! :D
Ciaoo!

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