Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

[C] Conferme esercizio su vettori

Linguaggi e sistemi

Moderatori: Foto UtentePaolino, Foto Utentefairyvilje

0
voti

[31] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentesimo85 » 27 ago 2013, 23:59

Dunque, un ultimo consiglio che mi sento di darti è di ridurre il corpo del main più che puoi. Questo implica ad usare le funzioni, in modo da richiamarle quando serve e non scrivere più volte lo stesso codice.

Inoltre, ora capisco cosa voleva dire il grande Foto UtenteDirtyDeeds in 14. :D

Per il momento il codice è questo con il controllo dei numeri negativi o uguali a 0 in input:

Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>

#define IN_SIZE 10
#define OUT_SIZE (2 * (IN_SIZE))
           
void fill_array(int array[], const int SIZE)
{   
   int index = 0;

   while(index < SIZE)
   {
      scanf("%d", &array[index]);
      
      index++;
   }

   index = 0;
   
   while(index < SIZE)
   {
      if(array[index] <= 0)
      do
      {
         printf("(!) The value of element %.2d is negative or equal to 0 (%.2d).\nPlease, insert its value again: ", index, array[index]);
         scanf("%d", &array[index]);

      }while(array[index] <= 0);
      
      index++;
   }
}

void cmp_and_fill(int IN1[], int IN2[], int OUT[], const int SIZE)
{
   int indexIn = 0, indexOut = 0;

   while(indexIn < SIZE)
   {
      if(IN1[indexIn] < IN2[indexIn])
      {
         OUT[indexOut] = IN1[indexIn];
         OUT[indexOut + 1] = IN2[indexIn];
                       
         indexOut += 2;
      }
      else if(IN1[indexIn] > IN2[indexIn])
      {
         OUT[indexOut] = IN2[indexIn];
         OUT[indexOut + 1] = IN1[indexIn];
                       
         indexOut += 2;
      }
      else if(IN1[indexIn] == IN2[indexIn])
      {
         OUT[indexOut] = IN1[indexIn];
                           
         indexOut += 1;
      }
                   
      indexIn++;
   }
}

void print_array(int array[], const int N)
{
   int index = 0;

   while(index < N)
   {
      printf("[%.2d] = %.2d\n", index, array[index]);
      
      index++;
   }
}

int main (void)
{
   int IN1[IN_SIZE] = {0}, IN2[IN_SIZE] = {0}, OUT[OUT_SIZE] = {0};
             
   printf("Fill the 1st array:\n");
   fill_array(IN1, IN_SIZE);

   printf("Fill the 2nd array:\n");
   fill_array(IN2, IN_SIZE);
               
   cmp_and_fill(IN1, IN2, OUT, IN_SIZE);
                           
   printf("OUT array\n");
   print_array(OUT, OUT_SIZE);

   exit(0);
}


Ora sono stanco e vado a nanna. Procedi ad implementare la funzione per riordinare l'array OUT e successivamente eliminare i doppioni. Ovviamente le ricontrolleremo. :D

O_/
Avatar utente
Foto Utentesimo85
30,9k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9927
Iscritto il: 30 ago 2010, 4:59

2
voti

[32] Re: [C] Conferme esercizio su vettori

Messaggioda Foto UtenteDirtyDeeds » 28 ago 2013, 9:33

Per Foto Utentesimo85: per ciò che riguarda il discorso dell'inserire un numero alla volta, il discorso è più o meno lo stesso del controllo degli errori. O uno assume che l'utente:

1) Immetta un numero alla volta
2) Immetta solo numeri interi positivi
3) Immetta i numeri nell'ordine corretto

e non fa nessun controllo degli errori, oppure uno decide di implementare un controllo, ma allora se vuol fare le cose fatte bene deve controllare 1), 2) e 3). Come dicevo, ai fini dell'esercizio un programma senza controllo degli errori va bene, più in generale no.

Per ciò che riguarda il punto 1), bisogna ricordarsi che l'input da tastiera (come quello da file) è tipicamente bufferizzato, sia per l'input che per l'output, e questo, quando un vuole implementare un controllo degli errori completo, dà qualche grattacapo. In questo vecchio messaggio avevo proposto una soluzione, che però contiene anch'essa due errori (riuscite a vederli? ;-) ) ed è quindi da NON usare. Comunque se avete pazienza, appena riesco vi scrivo una possibile soluzione corretta.

simo85 ha scritto:Ti avevo chiesto gentilmente di evitare i nomi come i, j, s, etc.. :?


Su questo non sono molto d'accordo: per gli indici di un ciclo breve, i,j,k vanno bene, perché in quel caso index non è più significativo di i, perché la funzione di i risulta evidente dal codice.
It's a sin to write sin instead of \sin (Anonimo).
...'cos you know that cos ain't \cos, right?
You won't get a sexy tan if you write tan in lieu of \tan.
Take a log for a fireplace, but don't take log for \logarithm.
Avatar utente
Foto UtenteDirtyDeeds
55,9k 7 11 13
G.Master EY
G.Master EY
 
Messaggi: 7012
Iscritto il: 13 apr 2010, 16:13
Località: Somewhere in nowhere

0
voti

[33] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentetecfil » 28 ago 2013, 10:08

Ciao!

Guardando il codice di Foto Utentesimo85 penso che tutto l'esercizio dia per scontato i tre punti riportati da Foto UtenteDirtyDeeds
1) Immetta un numero alla volta
2) Immetta solo numeri interi positivi
3) Immetta i numeri nell'ordine corretto

Essendo a 100 righe solo con il controllo dei numeri inseriti, dovendo scrivere tutto il codice a mano su foglio di carta in meno di 60 minuti :mrgreen: credo proprio che questi tre punti siano da considerarsi già verificati.

Comunque grazie per la spiegazione, adesso provo a terminare il codice con la parte mancante e vi faccio sapere :ok:

Ho guardato il codice del messaggio [21] dell'altro topic ma :mrgreen: non trovo dove sono i due errori :mrgreen:

Grazie
Ciaoo!
Il colmo per un elettricista? Essere isolato :D
Avatar utente
Foto Utentetecfil
327 1 5 6
Stabilizzato
Stabilizzato
 
Messaggi: 440
Iscritto il: 2 lug 2013, 21:41

1
voti

[34] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentecronos80 » 28 ago 2013, 11:19

Premesso che non ho un compilatore C e quindi il codice non lo posso testare, io eviterei di inserire i valori nell'array OUT prima di averli ordinati, altrimenti che vantaggio c'è nell'avere tutti numeri interi positivi ordinati nei vettori di origine?
Io farei così in linea di massima:
Codice: Seleziona tutto
int last=1;
int i2=0;

/* Codice per prendere l'input
...
...
*/

/*Metto il primo valore in OUT*/
if(IN1[0]<=IN2[0]){
   OUT[0]=IN1[0];
}else{
   OUT[0]=IN2[0];
}

for(i1=1;i1<DIM1;i1++){
   while(i2<DIM1){
      /*Qui ci mettiamo un po' di comparisons*/
      if(IN1[i1]<IN2[i2]){
         if(IN1[i1]>OUT[last]){            
            OUT[last]=IN1[i1];
            last++;
         } /*se non e' > puo' essere solo uguale*/
         break;/*esco dal ciclo su IN2 senza aumentare */
      }else{
         if(IN1[i1]>IN2[i2]){
            if(IN2[i2]>OUT[last]){
               OUT[last]=IN2[i2];
               last++;
            } /*se non e' > puo' essere solo uguale*/
            i2++;
         }else { /*IN1[i1]=IN2[i2]*/
            i2++;
            break;/*esco dal ciclo su IN2 */         
         }
   }
}
/* Ho controllato tutto IN1, ma potrei aver tralasciato qualche elemento di IN2*/
while(i2<DIM1){
   last++;
   OUT[last]=IN2[i2];
   i2++;
}
/* Aggiungiamo gli 0 mancanti. NON NECESSARIO SE OUT E' INIZIALIZZATO CON TUTTI 0 */
while(last<DIM2){   
   OUT[last]=0;
   last++;
}


ATTENZIONE: codice non testato, è solo per dare un'idea di come farei.
O_/
Non cercare di piegare il cucchiaio. È impossibile. Cerca invece di fare l'unica cosa saggia: giungere alla verità. Il cucchiaio non esiste. Allora ti accorgerai che non è il cucchiaio a piegarsi, ma sei tu stesso!
Avatar utente
Foto Utentecronos80
1.546 1 6 12
Expert EY
Expert EY
 
Messaggi: 636
Iscritto il: 17 gen 2012, 10:43

0
voti

[35] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentetecfil » 28 ago 2013, 15:01

Ciao!

Grazie Foto Utentecronos80, ho provato il tuo codice e funziona, però mi stampa in output un vettore con solo alcuni elementi del primo vettore IN1.

Ho provato anche a riscrivere il codice in questa maniera:
Codice: Seleziona tutto
#include <stdio.h>
#define DIM1 10
#define DIM2 20

int main ()
{
    int IN1[DIM1], IN2[DIM1], OUT[DIM2]={0}, i, j, num, s=0;
   
    printf("Riempi il primo vettore:\n");
    for (i=0;i<DIM1;i++)
    {
        scanf("%d", &num);
        IN1[i]=num;
    }
    printf("Riempi il secondo vettore:\n");
    for (i=0;i<DIM1;i++)
    {
        scanf("%d", &num);
        IN2[2]=num;
    }
   
    for (i=0;i<DIM1;i++)
    {
        for (j=0;j<DIM1;j++)
        {
            if (IN1[i]!=IN2[i])
            {
                OUT[s]=IN1[i];
                s++;
            }
        }
    }
    for (i=0;i<DIM1;i++)
    {
        OUT[s]=IN2[i];
    }
   
    printf("\n");
    for (i=0;i<DIM2;i++)
    {
        printf("%4d", OUT[i]);
    }
   
   
    return 0;
}


L'utente riempie i due vettori, poi faccio partire un ciclo che si dovrebbe comportare in questo modo: confronto l'elemento i del primo vettore con tutti gli elementi j del secondo vettore, se l'elemento i è diverso dall'elemento j allora lo aggiungo al vettore in uscita, altrimenti passo al successivo.

Fatto questo avrò nel vettore in uscita solamente i numeri del primo vettore che non sono ripetuti nel secondo, allora aggiungo con un altro ciclo for tutti i numeri del secondo vettore a quello in uscita. Manca solo la parte di codice per ordinare il vettore, però il codice non mi funziona perché se inserisco:
Codice: Seleziona tutto
IN1: 2 5 9 14 15 20 25 27 30 32
IN2: 3 5 10 11 12 22 23 25 26 27

ottengo in uscita
Codice: Seleziona tutto
2   2   2   2   2   2   2   2   2   2   5   5   5   5   5   5   5   5   5   5


Ho provato a seguire questo ragionamento perché se gli array in input sono già ordinati, dovrebbe essere sufficiente scorrere i due array in contemporanea e inserire nell'array di output l'elemento più piccolo tra quelli correnti dei due array (incrementando quindi il corrispondente indice), quando i due elementi sono uguali allora non faccio niente e passo al successivo.

Per questo ho utilizzato OUT[s], così posso incrementare la i e mantenere nella stessa posizione la s quando mi ritrovo due numeri uguali

Grazie
Ciaoo!
Il colmo per un elettricista? Essere isolato :D
Avatar utente
Foto Utentetecfil
327 1 5 6
Stabilizzato
Stabilizzato
 
Messaggi: 440
Iscritto il: 2 lug 2013, 21:41

0
voti

[36] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentecronos80 » 28 ago 2013, 16:33

tecfil ha scritto:Grazie cronos80, ho provato il tuo codice e funziona, però mi stampa in output un vettore con solo alcuni elementi del primo vettore IN1.

Potresti riportare il risultato ottenuto ed i due input?
O_/
Non cercare di piegare il cucchiaio. È impossibile. Cerca invece di fare l'unica cosa saggia: giungere alla verità. Il cucchiaio non esiste. Allora ti accorgerai che non è il cucchiaio a piegarsi, ma sei tu stesso!
Avatar utente
Foto Utentecronos80
1.546 1 6 12
Expert EY
Expert EY
 
Messaggi: 636
Iscritto il: 17 gen 2012, 10:43

0
voti

[37] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentetecfil » 28 ago 2013, 19:09

Ciao!

Dopo ore ed ore passate su questo esercizio questo codice dovrebbe finalmente funzionare!
Codice: Seleziona tutto
#include <stdio.h>
#define DIM1 10
#define DIM2 20
int unisci(int v1[10], int v2[10], int out[20]);
int main ()
{
    int IN1[DIM1], IN2[DIM1], IN3 [DIM2], IN4[DIM2], OUT[DIM2], k=0,zeri=0, i1;
    int i,j, temp;
    int last=1;
    int i2=0;

   
    printf("Riempi il primo vettore con %d numeri maggiori di zero in ordine crescente:\n", DIM1);
    for (i=0;i<DIM1;i++)
    {
        scanf("%d", &IN1[i]);
        if (IN1[i]<0)
        i--;
       
    }
    printf("Riempi il secondo vettore con %d numeri maggiori di zero in ordine crescente:\n", DIM1);
    for (i=0;i<DIM1;i++)
    {
        scanf("%d", &IN2[i]);
        if (IN2[i]<0)
        i--;
    }

    unisci (IN1, IN2, OUT);
   
    printf("\nEcco il vettore dopo averlo ordinato:\n");
    for (i=0;i<DIM2;i++)
    {
        printf("%4d", OUT[i]);
    }
   
    return 0;
}

int unisci(int v1[10], int v2[10], int out[20])
{
    int i = 0, j = 0, k = 0;
    while (i < 10 && j < 10) {
        if (v1[i] < v2[j]) {
            out[k++] = v1[i++];
        } else if (v1[i] == v2[j]) {
            out[k++] = v1[i++]; ++j;
        } else {
            out[k++] = v2[j++];
        }
    }
    while (i < 10) { out[k++] = v1[i++]; }
    while (j < 10) { out[k++] = v2[j++]; }
    return k;
}


Col primo ciclo while vado ad ordinare gli elementi, partendo dal presupposto che i due vettori sono già in ordine crescente. Creo quindi le varie condizioni, se il primo elemento è minore del secondo, se è uguale o maggiore.

Nel caso in cui sia uguale allora stampo una volta il numero e incremento però il valore della j in modo da passare a quello successivo senza ristampare il numero.

Fatto questo aggiungo gli ultimi due cicli while in modo da andare a completare con gli elementi mancanti del primo e del secondo vettore.

Secondo voi può andare? Nel codice manca il controllo se il numero è negativo, per adesso ho messo una toppa con
Codice: Seleziona tutto
        if (IN1[i]<0)
        i--;

però comunque dal testo dell'esercizio sembra che anche questo passaggio sia da prendere per vero!

Ciaoo :-)
Il colmo per un elettricista? Essere isolato :D
Avatar utente
Foto Utentetecfil
327 1 5 6
Stabilizzato
Stabilizzato
 
Messaggi: 440
Iscritto il: 2 lug 2013, 21:41

0
voti

[38] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentesimo85 » 28 ago 2013, 19:35

Beh il codice per il controllo del numero negativo o uguale a zero te l'ho postato ieri sera.. È stato un gesto inutile?
Avatar utente
Foto Utentesimo85
30,9k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9927
Iscritto il: 30 ago 2010, 4:59

0
voti

[39] Re: [C] Conferme esercizio su vettori

Messaggioda Foto Utentetecfil » 28 ago 2013, 21:40

Ciao!

No no assolutamente! Dovevo ancora implementarlo :mrgreen:
Ecco fatto ora dovrebbe essere tutto completo:
Codice: Seleziona tutto
#include <stdio.h>
#define DIM1 10
#define DIM2 20
int unisci(int v1[10], int v2[10], int out[20]);
int main ()
{
    int IN1[DIM1], IN2[DIM1], IN3 [DIM2], IN4[DIM2], OUT[DIM2], k=0,zeri=0, i1;
    int i,j, temp;
    int last=1;
    int i2=0;
       int indexIn = 0, indexOut = 0;

    printf("Riempi il primo vettore con %d numeri maggiori di zero in ordine crescente:\n", DIM1);
    while(indexIn < DIM1)
    {
        scanf("%d", &IN1[indexIn]);
        if(IN1[indexIn] > 0)
        indexIn++;
    }
               
    indexIn = 0;

    printf("Riempi il secondo vettore con %d numeri maggiori di zero in ordine crescente:\n", DIM1);
    while(indexIn < DIM1)
   {
        scanf("%d", &IN2[indexIn]);           
        if(IN2[indexIn] > 0)
        indexIn++;
    }
               
    indexIn = indexOut = 0;

    unisci (IN1, IN2, OUT);
   
    printf("\nEcco il vettore dopo averlo ordinato:\n");
    for (i=0;i<DIM2;i++)
    {
        printf("%4d", OUT[i]);
    }
   
    return 0;
}

int unisci(int v1[10], int v2[10], int out[20])
{
    int i = 0, j = 0, k = 0;
    while (i < 10 && j < 10) {
        if (v1[i] < v2[j]) {
            out[k++] = v1[i++];
        } else if (v1[i] == v2[j]) {
            out[k++] = v1[i++]; ++j;
        } else {
            out[k++] = v2[j++];
        }
    }
    while (i < 10) { out[k++] = v1[i++]; }
    while (j < 10) { out[k++] = v2[j++]; }
    return k;
}


Ho aggiunto il codice di Foto Utentesimo85 per verificare che i numeri siano maggiori di zero, e devo dire che adesso funziona tutto!

Grazie mille ancora per l'aiuto! :ok:
Ciaoo O_/
Il colmo per un elettricista? Essere isolato :D
Avatar utente
Foto Utentetecfil
327 1 5 6
Stabilizzato
Stabilizzato
 
Messaggi: 440
Iscritto il: 2 lug 2013, 21:41

4
voti

[40] Re: [C] Conferme esercizio su vettori

Messaggioda Foto UtenteDirtyDeeds » 31 ago 2013, 16:07

Avevo promesso di scrivere qualcosa sul controllo degli errori quando si fa l'input da tastiera. Inizio il discorso, lo spezzerò in più messaggi perché lungo. Buttiamo giù qualche "specifica". Supponiamo di voler richiedere a un utente di immettere un certo numero di valori interi da memorizzare in un buffer:

1) Il buffer, di nome buf, ha dimensione BUF_SZ (che qui supporremo uguale a 5 per non diventare vecchi a inserire numeri :mrgreen: ).
2) Il programma deve scrivere su schermo quale elemento deve essere immesso. Un esempio di sessione potrebbe essere il seguente:

Codice: Seleziona tutto
buf[0] = 1
buf[1] = 2
buf[2] = 3
buf[3] = 4
buf[3] = 5


dove il messaggio "buf[i]" è emesso dal programma e i numeri sono immessi dall'utente.
3) Il programma deve accettare al più un numero per riga, di modo che una risposta del tipo

Codice: Seleziona tutto
buf[0] = 5 6


deve generare una richiesta di un nuovo input per lo stesso elemento:

Codice: Seleziona tutto
buf[0] = 5 6
buf[0] =


4) Il programma deve gestire gli input errati, come
Codice: Seleziona tutto
buf[0] = Ciao


richiedendo di nuovo l'immissione del numero

Codice: Seleziona tutto
buf[0] = Ciao
buf[0] =


5) Infine, tanto per complicare ancora un po' le cose, supponiamo che i numeri interi all'ingresso debbano essere compresi nell'intervallo [VAL_MIN,VAL_MAX] (p.es. VAL_MIN = -100 e VAL_MAX = 100).

Un primo programma, grezzo e senza controlli, potrebbe essere questo:

Codice: Seleziona tutto
// getbuf.c
#include <stdio.h>
#define BUF_SZ 5

int main()
{
    int buf[BUF_SZ] = {0};

    for (size_t i = 0; i < BUF_SZ; ++i) {
        printf("buf[%zd] = ", i);
        scanf("%d", buf+i);
    }

    return 0;
}


Commenti:
1) Nella printf lo specificatore %zd dice che la variabile da stampare è di tipo size_t (v. qui). Non si può usare %d.
2) Un primo problema del codice sopra è che, siccome l'I/O è bufferizzato, non c'è nessuna garanzia che il PC stampi "buf[i] = " prima che venga richiesto l'input: potrebbe venire richiesto l'input senza che ci sia un messaggio. E' raro ma può capitare. Per esempio, supponendo di aver chiamato il programma getbuf, provate a eseguire il comando

Codice: Seleziona tutto
getbuf > out.txt


L'output del programma viene rediretto su out.txt: sebbene uno non veda nessun messaggio a schermo, il programma attende una risposta dall'utente. Bene: mentre il programma attende, provate ad aprire out.txt con un editor di testo: molto probabilmente vedrete un file vuoto, senza neanche il messaggio "buf[0] = ". Tale messaggio è rimasto nel buffer di uscita del sistema operativo: stdout è tipicamente bufferizzato per linee, e volendo essere sicuri che venga stampato un messaggio prima della richiesta di input bisogna o i) terminare la printf con un carattere '\n' (ma non è l'output che volevamo) oppure ii) aggiungere un'istruzione che dica al computer di svuotare il buffer. Scegliendo la seconda strada arriviamo a

Codice: Seleziona tutto
// getbuf.c
#include <stdio.h>
#define BUF_SZ 5

int main()
{
    int buf[BUF_SZ] = {0};

    for (size_t i = 0; i < BUF_SZ; ++i) {
        printf("buf[%zd] = ", i);
        fflush(stdout);
        scanf("%d", buf+i);
    }

    return 0;
}


Proviamo ora ad eseguire il programma e in risposta alla prima richiesta proviamo a rispondere "Ciao!". Cosa succede? Non quello che vorremmo ;-)

La risposta alla prossima puntata (to be continued...).
It's a sin to write sin instead of \sin (Anonimo).
...'cos you know that cos ain't \cos, right?
You won't get a sexy tan if you write tan in lieu of \tan.
Take a log for a fireplace, but don't take log for \logarithm.
Avatar utente
Foto UtenteDirtyDeeds
55,9k 7 11 13
G.Master EY
G.Master EY
 
Messaggi: 7012
Iscritto il: 13 apr 2010, 16:13
Località: Somewhere in nowhere

PrecedenteProssimo

Torna a PC e informatica

Chi c’è in linea

Visitano il forum: Nessuno e 31 ospiti