[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
vict85
Non capisco la presenza di DIM1. Anche perché dovrebbe essere verosimilmente uguale a 100. Il secondo for non andrebbe messo, se non per ragioni di debug.

Per la seconda parte, come lo faresti a mano? Prova ad elencare i passaggi che faresti.

floppyes
Ciao!

Il DIM1 è provvisorio, l'ho messo io per verificare con meno numeri se il programma funziona :)

Per la seconda parte io farei così, andrei a verificare tutti quanti i numeri inseriti. Parto dal primo numero e lo confronto col secondo, se è diverso allora memorizzo il numero e aumento il contatore di uno, poi passo al secondo numero, se è identico al primo allora incremento il contatore portandolo a 2, se è diverso allora lo aggiungo ai miei numeri ed incremento di uno il contatore e così per tutti quanti i numeri, poi mi calcolo la percentuale.

Grazie
Ciaoo!

vict85
Quando tu descrivi un algoritmo spesso ci si dimentica di esprimere la memoria, ma il computer elabora blocca di memoria.
Quello che tu possiedi è un blocco di \(\displaystyle s \) interi non nulli seguiti da uno zero in pozione \(\displaystyle s \) e \(\displaystyle 100 - s - 1 \) interi casuali.
n : [ n_0 , n_1 , n_2 , ... , n_s = 0 , ... , n_100 ]

Un modo in cui puoi fare il tuo lavoro consiste nel costruire un nuovo blocco di memoria:
m : [ [m_0 , f_0 ] , [m_1 , f_1 ] , ... ]

in cui \(\displaystyle m_i \neq m_j \), \(\displaystyle m_i \neq 0 \) e \(\displaystyle \sum_{i=0}^{?} f_i = s \). Il determinare la seconda dimensione lo lascio a te. Nota inoltre che è possibile che parte dell'array non venga inizializzata.
Nota comunque che è possibile unire direttamente i due passaggi e scrivere il secondo array mentre carichi i valori senza passare da primo array.
Il procedimento quindi inizierà ponendo, se \(\displaystyle n_0 \neq 0 \), \(\displaystyle m_0 = n_0 \) e \(\displaystyle f_0 = 1 \). Il passaggio successivo si occuperà di \(\displaystyle n_1 \), nel caso in cui \(\displaystyle n_1 \neq 0 \) controllerà se \(\displaystyle n_1 = n_0 = m_0 \) e incrementerà \(\displaystyle f_0 \) oppure porrà \(\displaystyle m_1 = n_1 \) e \(\displaystyle f_1 = 1 \) a seconda del risultato del confronto. E così via.

Prova a scrivere il codice corrispondente.

floppyes
Ciao!

Grazie per la risposta. Ho provato a modificare il codice così:
#include <stdio.h>
#define DIM1 5

int main ()
{
    int vet[DIM1],i,n=0,j,vet2[DIM1];
    
    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]);
    }
    
    // Ricerco i singoli numeri inseriti
    printf("\n\nSingoli numeri inseriti:\n");
    for (i=0;i<DIM1;i++)
    {
        if (vet[i]==0)
        {
            break;
        }
        else if (vet[i]!=vet[i+1] && vet[i]!=vet2[n])
        {
            vet2[n]=vet[i];
        }
    }
    for (i=0;i<DIM1;i++) 
    {
        printf("%d", vet2[n]);
    }      
    return 0;
}


(ho aggiunto il pezzo finale da riga 24).

Però mi stampa solo l'ultimo numero diverso dagli altri.

Grazie
Ciaoo

vict85
Devi confrontarlo con tutti gli elementi precedentemente estratti e non solo con quello precedente. In ogni caso io avevo scritto un array multidimensionale.

floppyes
Ciao!

Quello che non riesco a capire è come fare per confrontarlo con tutti gli elementi precedenti, devo impostare un ciclo for che parte dall'ultimo elemento e retrocede fino al primo?

Grazie
Ciaoo

vict85
Andare in avanti o indietro è la stessa cosa. Comunque si: devi usare un ciclo for.

floppyes
Ciao!

Riusciresti a scrivermi solo l'inizio perchè non riesco mica a capire come impostare il ciclo. Pensavo di impostare un ciclo for che controlla a partire da 0 l'elemento successivo, e uno che controlla a partire dall'ultimo elemento ma non mi funziona :(

Grazie ancora
Ciaoo!

floppyes
Ciao!
Ho provato a scrivere questo codice ma non funziona ancora! Mi stampa sempre l'ultimo carattere! :?
     // Ricerco i singoli numeri inseriti
    printf("\n\nSingoli numeri inseriti:\n");
    while (vet2[n]==vet[i])
    {
        vet2[n]=vet[i];
    }
                
    for (i=0;i<DIM1;i++)
    {
        if (vet[i]!=vet2[n])
        {
            vet3[n]=vet2[n];
        }
    }

Ciao!

Atem1
"floppyes":
Ciao!
Riusciresti a scrivermi solo l'inizio perchè non riesco mica a capire come impostare il ciclo. Pensavo di impostare un ciclo for che controlla a partire da 0 l'elemento successivo, e uno che controlla a partire dall'ultimo elemento ma non mi funziona :(
Grazie ancora
Ciaoo!

Io userei una struct del tipo

typedef struct nome_struttura
{
int numero;
int conteggio;
} nuovo_tipo;

E dopo dichiarerei un array di questo nuovo_tipo...
nuovo_tipo vettore[100]; //visto che hai scritto di dover inserire al più 100 elementi

Quindi:
1.Inizializzi una variabile contatore "n=1" che incrementi ad ogni numero inserito dall'utente
2.Chiedi all'utente di inserire il primo numero
3.Leggi il numero e lo inserisci in vettore[0].numero, inizializzando vettore[0].contatore ad 1
4.Inizializzi un'altra variabile contatore "dim=1" che conta il numero di elementi diversi fra loro
5.Chiedi all'utente di inserire numeri diversi da 0
6.Leggi il numero X
7.Incrementi la variabile contatore "n" dei numeri inseriti.
8.Fai partire un ciclo che va da 0 a dim-1 e controlli che ogni "vettore.numero" sia diverso dal numero X, in tal caso aggiungi X al vettore e inizializzi vettore[dim].conteggio ad 1, ed incrementi la variabile dim, altrimenti se X è uguale ad un elemento i-esimo di vettore.numero, incrementi vettore.conteggio ed esci da questo ciclo senza bisogno di arrivare a dim-1.
9.Quando l'utente avrà finito di inserire i suoi numeri, tu avendo la variabile "n" che ha contato tutti gli elementi inseriti dall'utente, il calcolo della percentuale per ogni elemento i-esimo del diventa molto facile visto che ad esso è stata associato il suo numero di occorrenze.

floppyes
Ciao!

Grazie per la risposta. Provo a scrivere il programma e vedo se funziona!

Ti faccio sapere
Grazie
Ciao :)

floppyes
Ciao!

Ho provato a scrivere il codice fino al punto 8.. però non penso sia corretto :(

#include <stdio.h>
#define DIM1 10

int main()
{
    typedef struct nome_struttura
    {
    int numero;
    int conteggio;
    int contatore;
    } nuovo_tipo;
    nuovo_tipo vettore[DIM1];
    
    // Inizializzo la variabile n ed i e num
    int n=1, i, num;
    
    // L'utente inserisce il primo numero, lo salvo in vettore[0] ed aumento il contatore
    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-1))
    {
        printf("Inserisci un altro numero");
        scanf("%d", &num);
       
        for (i=0;i<dim-1;i++)
        {
            if (vettore[i].numero != num) 
            {
                vettore[i].numero = num;
                vettore[dim].conteggio=1;
                dim++;
            }
            else
            {
                vettore[i].conteggio++;
                break;
            }
        }
    }
    
    printf("\nNumeri singoli inseriti:\n\t");
    for (i=0;i<vettore[i].conteggio;i++)
    {
        printf("%d", vettore[i].numero);
    }
}


Perchè mi stampa sempre una serie di numeri diversi rispetto a quelli da me inseriti

Grazie mille
Ciaoo

Atem1
"floppyes":
Ciao!
Perchè mi stampa sempre una serie di numeri diversi rispetto a quelli da me inseriti


Perchè la parte dentro l'IF è sbagliata.
if (vettore[i].numero != num)
{
  vettore[i].numero = num;
  vettore[dim].conteggio=1;
dim++;
}


Intendevo dire che, dopo aver controllato che num sia diverso da TUTTI gli elementi del vettore, in vettore[dim].numero metti num. Questa è una cosa che devi fare fuori dal ciclo che parte da 0 e va a dim-1.

Riformulo il punto 8:
Fai partire un ciclo che va da 0 a dim-1 e se "vettore.numero" è uguale al numero X allora incrementi vettore.conteggio ed esci dal ciclo senza bisogno di arrivare a dim-1, altrimenti prosegui il ciclo. Se alla fine del ciclo X è risultato diverso da tutti gli elementi del vettore allora aggiungi X al vettore (cioè lo metti in vettore[dim].numero) e inizializzi vettore[dim].conteggio ad 1, quindi dopo che hai fatto questo incrementi la variabile dim.

E comunque nell'ultimo ciclo, devi usare "dim" e non vettore.conteggio....
vettore.conteggio conta solamente il numero delle volte che vettore.numero è stato inserito dall'utente e ti serve per il calcoli delle percentuali (hai anche dimenticato di incrementare n ad ogni nuovo numero inserito dall'utente)...

floppyes
Ciao!
Grazie per la risposta. Ho provato a riscrivere il codice così:
#include <stdio.h>
#define DIM1 10
int main()
{
typedef struct nome_struttura
{
int numero;
int conteggio;
int contatore;
} nuovo_tipo;
nuovo_tipo vettore[DIM1];
// Inizializzo la variabile n ed i e num
int n=1, i, num;
// 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);
n++;
for (i=0;i<dim-1;i++)
{
if (vettore[i].numero == num)
{
vettore[i].conteggio++;
break;
}
}
vettore[dim].numero = num;
vettore[dim].conteggio=1;
dim++;
}
printf("\nNumeri singoli inseriti:\n\t");
for (i=0;i<vettore[i].conteggio;i++)
{
printf("%d", vettore[i].numero);
}
}

Però adesso mi stampa solo i primi due numeri inseriti :(
Nel punto 8 non ho capito una sola cosa:
Se alla fine del ciclo X è risultato diverso da tutti gli elementi del vettore allora aggiungi X al vettore

Io eseguo il ciclo for che contiene l'if, però quando vado ad eseguire questo pezzo di codice:
vettore[dim].numero = num;
vettore[dim].conteggio=1;
dim++;

essendo dopo il ciclo for e dopo l'if, non dovrebbe aggiungere anche tutti i numeri che non rispettano la condizione dell'if?
Grazie
Ciaoo!

Atem1
"floppyes":
Ciao!
Però adesso mi stampa solo i primi due numeri inseriti :(


La risposta è qui:
"Atem":

E comunque nell'ultimo ciclo, devi usare "dim" e non vettore.conteggio....
vettore.conteggio conta solamente il numero delle volte che vettore.numero è stato inserito dall'utente e ti serve per il calcoli delle percentuali


"floppyes":

essendo dopo il ciclo for e dopo l'if, non dovrebbe aggiungere anche tutti i numeri che non rispettano la condizione dell'if?


Infatti la condizione non è "se esci dal ciclo" ma se X è risultato diverso da TUTTI gli elementi del vettore.
Cioè...
If X diverso da tutti gli elementi del vettore allora
{
vettore[dim].numero = num;
vettore[dim].conteggio=1;
dim++;
}

E' chiaro che se non metti la condizione vengono aggiunti tutti gli elementi e quindi dim==n.
Come fai a stabilire se X è risultato diverso da tutti gli elementi del vettore?

Ci sono vari modi...
Per esempio potresti usare una variabile inizializzata a 0 (cioè la poni uguale a 0 subito dopo aver chiesto all'utente di inserire il numero X) e la setti ad 1 nel caso X sia uguale ad un elemento del vettore (per intenderci prima del break metti flag=1.

Se una volta uscito dal ciclo è flag==0 vuol dire che X è risultato diverso da tutti gli elementi del vettore...
Un altro modo consiste nello sfruttare il fatto che se X è risultato diverso da tutti gli elementi del vettore allora automaticamente i==dim perchè visto che hai usato il break, anche se X fosse uguale all'ultimo elemento del vettore, sarebbe i==dim-1 e poi ci sarebbe il break che evita che l'istruzione i++ all'interno del ciclo FOR venga eseguita.

floppyes
Ciao!

Perfetto adesso ho capito i passaggi che esegue il programma, ho riscritto il codice modificandolo come mi hai detto ma ancora non vengono stampati i numeri corretti :(
#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;
    
    // 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-1;i++)
        {
            if (vettore[i].numero == num) 
            {
                vettore[i].contatore=1;
                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<DIM1;i++)
    {
        printf("%d", vettore[i].numero);
    }
return 0;
}


In teoria adesso dovrebbe essere giusto, ho impostato anche la variabile flag che se uguale a zero allora aggiunge il numero al vettore.

Non riesco a capire qual'è il punto sbagliato. Una volta che vengono stampati i singoli numeri mi manca solo da calcolare la percentuale.

Grazie mille
Ciao :)

Atem1
1.Il ciclo for deve andare da 0 a dim-1 non a dim-2
Quindi o metti i
2.La dimensione del vettore (la usi quando alla fine vuoi visualizzare i numeri) è dim, non DIM1

3. Se scrivi
printf("%d", vettore[i].numero);

tutti i numeri vengono attaccati quindi risulta difficile capire cosa viene visualizzato di preciso.

4.
if (vettore[i].numero == num)
{
   vettore[i].contatore=1;
   flag=1;
   break;
}


Se num è uguale ad un elemento del vettore devi incrementare il suo contatore e non settarlo ad 1.

floppyes
Ciao!

Perfetto ora funziona alla grande! Vengono stampati solamente i singoli numeri inseriti senza contare i doppioni :smt023

Adesso mi manca da calcolare la percentuale dei singoli numeri. Una sola cosa non ho capito: il vettore
vettore[i].contatore

mi dirà quante volte è stato inserito ogni singolo numero?

Ad esempio se io inserisco il numero 3 due volte, allora il vettore terrà salvato in memoria che il numero 3 è stato inserito due volte?

Grazie mille per l'ottimo aiuto :)
Ciaoo!

Atem1
Sì esatto quindi per ogni elemento i-esimo del vettore dividi il relativo contatore per n e lo moltiplichi per 100 per avere la percentuale.
Comunque i typedef si mettono prima del MAIN in modo da poter usare i nuovi_tipi anche all'interno di procedure e funzioni. Inoltre in quella struct "conteggio" è inutile visto che hai usato contatore.

floppyes
Ciao!

Grazie per l'aiuto, ho spostato il typedef prima del main ed eliminato il conteggio.

Ultima domanda :D
Per fare la percentuale ho aggiunto questo codice prima della fine del programma:
    printf("\n\nPercentuali:\n\t");
    for (i=0;i<dim;i++)
    {
        perc[i]=((vettore[i].contatore/n)*100);
        printf("%f  ", perc[i]);
    }


Solo che mi stampa le percentuali sbagliate :( ho dichiarato il vettore come
    double perc[DIM1]={0};


Grazie mille :)
Ciaoo!

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