Newsgroup: it.comp.lang.c
Titolo: Problemino di funzione che restituisce un vettore al main

Salve,
 
ecco il testo dell'esercizietto:
"Data una main che contiene un vettore di interi definito come
int v1[10]={2,4,11,6,17,1,24,4,45,3} , creare una funzione che crea un 
Vettore v2, che contiene solo gli elementi di v1 maggiori di 5, e lo 
restituisce al main."
 
io ho risolto come segue:
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int* elabora(int v1[],int v2[]);
int main() {
 
     int v1[10]={2,4,11,6,17,1,24,4,45,3};
     int v2[10];
     int i=0;
     int *p;
     p=elabora(v1,v2);
     for (i=0;i<10;i++)
     printf("%d ",p[i]);
     system("PAUSE");
     return 0;
}
 
int* elabora(int v1[],int v2[]) {
      int *w;
      w=v2;
      int i,k=0;
      for (i=0;i<10;i++)
          if(v1[i]>5) {
                       v2[k]=v1[i];
                       k++;
                      }
      return w;
}
 
 
 
ma non son ben certo, in effetti forse elabora non doveva avere come 
parametri v2, ma creare v2 stesso (meglio con allocazione dinamica o 
statica?) . In ogni caso se creo v2 con elabora, nella main devo sempre 
dichiarare un vettore v2 giusto?
Qual'ï¿œ il modo piï¿œ corretto per risolvere l'esercizio?
Grazie

 [...]
 
Il problema gira attorno al fatto che il vettore v2 avrà un numero di elementi
minore (o uguale) a v1.
Non basta quindi che ritorni il vettore, ma devi ritornare anche il numero
di elementi!
 
Se usare memoria dinamica o meno dipende ovviamente dal caso, ma il discorso
del numero degli elementi rimane sempre lo stesso.
 
Ciao!

 del numero degli elementi rimane sempre lo stesso.
 
si, ci avevo pensato, ma stavo pi� che altro pensando se era corretto 
passare v2 a elabora o se era meglio che elabora creasse v2.
 
Circa la tua osservazione, risolverei cosi':
 
int* elabora(int v1[],int v2[],int *n);
int main() {
 
     int v1[10]={2,4,11,6,17,1,24,4,45,3};
     int v2[10];
     int i=0;
     int n=0;
     int *p;
     p=elabora(v1,v2,&n);
     for (i=0;i<n;i++)
     printf("%d ",p[i]);
     system("PAUSE");
     return 0;
}
 
int* elabora(int v1[],int v2[],int *n) {
      int *w;
      w=v2;
      int i;
      for (i=0;i<10;i++)
          if(v1[i]>5) {
                       v2[*n]=v1[i];
                       *n=*n+1;
                      }
      return w;
}
 
 
che ne dici?
Grazie ciao

 Grazie ciao
 
 
o meglio qualcosa del genere?
 
#include <stdio.h>
#include <stdlib.h>
 
int* elabora(int v1[], int *dim);
int main() {
 
     int v1[10]={2,4,11,6,17,1,24,4,45,3};
     int i=0;
     int dim=0;
     int *p;
     p=elabora(v1,&dim);
     for (i=0;i<dim;i++)
          printf("%d ",p[i]);
     system("PAUSE");
     return 0;
}
 
int* elabora(int v1[], int *dim) {
      int *v2;
      int i,N=0;
      for (i=0;i<10;i++)
           if(v1[i]>5)
                     N++;
      v2=(int *) malloc (N*sizeof(int));
      for (i=0;i<10;i++)
            if(v1[i]>5) {
                         v2[*dim]=v1[i];
                         (*dim)++;
                        }
      return v2;
}

 [...]
 
 
Ciao  Manlio

 restituisci il numero di elementi processati, invece di w.
 
io ho cercato di soddisfare le richieste dell'esercizio (magari non 
capendole) che chiedono che la funzione _crei_ v2 e che lo _restituisca_ 
al main.
 
Poi mi son trovato nel problema di non poter restituire la dimensione di 
v2, in quanto costretto dal testo a restituire v2 stesso (return 
"impegnato"), e quindi per far avere alla main la dimensione di v2 ho 
utilizzato il passaggio per indirizzo (&n).
Ripeto probabilemente non ho capito le richieste dell'esercizio, o son 
stato troppo integralista nell'interpretazione.
 
Grazie ciao


Entrambe le tue soluzioni vanno bene.
 
Tieni presente che in un caso reale le cose cambiano a seconda dei vincoli; se
vuoi fare qualche esercizio puoi pensare ai casi in cui:
- il vettore iniziale è scandalosamente grosso
- la distribuzione dei valori non sia uniforme (molti valori piccoli oppure
molti valori grossi)
- i vettori (e questo ti consiglio di farlo) siano ordinati.
 
Ciao!

 
 
L'unico problema che vedo è che v2 non lo crei nella funzione elabora ma 
in main.
 
 
Ciao   Manlio


 
Come ti ha suggerito Manlio, qui "w" ï¿œ completamente superfluo, infatti
non fai che copiare il puntatore v2 e lo restituisci. Sarebbe stato lo
stesso scrivere "return v2", senza il passaggio a w. Il punto perï¿œ ï¿œ
un altro. Come i tuoi stessi dubbi confermano, se ti ï¿œ chiesto di "creare"
l'array nella funzione elabora() ï¿œ certo che ci si riferisca all'alloca-
zione dinamica di memoria. In questo caso ci sono dei punti importanti
da considerare, questo vale per l'allocazione dinamica in generale, non
tanto per l'esercizio in questione che tanto dovrï¿œ allocare solo 10 interi:
 
- (come ha detto fmassei) Cosa accadrebbe se l'array v1 fosse di
   dimensioni giganti? Sarebbe una mossa astuta allocare un array
   v2 dinamico con le stesse dimensioni sapendo giï¿œ in partenza che
   potremmo (con un po' di fortuna) risparmiare un sacco di memoria?
 
- Quanto ï¿œ conveniente calcolare il numero di elementi che v2 dovrï¿œ
   contenere *prima* di allocare la memoria corrispondente? (Considera
   che calcolare a priori il numero di elementi e poi fare la cernita
   di elementi che popoleranno v2 ï¿œ ridondante, perchï¿œ in pratica per
   due volte passiamo in rassegna tutti gli elementi di v1.
 
Questo significa che in casi come questo (immaginando array di grosse
dimensioni) avremmo il dilemma se sacrificare la memoria allocata
(immagina di allocare un milione di elementi e poi invece quelli maggiori
di 5 sono soltanto 30) oppure fare un test su tutti gli elementi di v1
per vedere quanta memoria allocare per v2 e poi rifare tutto il test per
"popolare" v2 con gli elementi che ci interessano. (Certo uno direbbe,
potremmo ri-dimensionare v2 dopo, ma il punto ï¿œ che l'allocazione potrebbe
fallire al momento che ci serve).
 
Detto questo, ï¿œ bene che ti faccia tutti questo problemi in generale,
ma in questo caso particolare puoi star sicuro che sia il sacrificio
di memoria che di cpu sono assolutamente irrilevanti.
 
Aggiungere comunque un po' di elasticitï¿œ al programma non guasta, per
esempio, la tua funzione elabora() fa leva sul numero 10 come max numero
di elementi e sul numero 5 come soglia per fare la cernita. Questa non ï¿œ
una buona pratica perchï¿œ immagina di aver scritto un sacco di funzioni
che usano direttamente i valori 10 e 5, poi se l'esercizio cambia e devi
modificare questi numeri devi modificare tutte le funzioni? Meglio usare
delle costanti "#define", oppure "const int", oppure chiedere questi
numeri in input durante l'esecuzione.
 
#include <stdio.h>
#include <stdlib.h>
 
#define MAX 10
#define THRESHOLD 5
 
int* elabora(const int v1[], const int n);
 
int main(void)
{
     int v1[MAX] = {2, 4, 11, 6, 17, 1, 24, 4, 45, 3};
     int nElementi = 0;
     int i, *v2;
 
     for(i = 0; i < MAX; i++)
         if(v1[i] > THRESHOLD) nElementi++; /* conta gli elementi */
 
     v2 = elabora(v1, nElementi); /* tenta allocazione memoria per v2 */
     if(!v2) {
         fprintf(stderr, "in main(): la funzione elabora() "
                         "ha restituito NULL\n");
         return EXIT_FAILURE;
     }
 
     for(i = 0; i < nElementi; i++)
         printf("%d ", v2[i]);
 
     putchar('\n');
     free(v2); /* libera memoria allocata per v2 */
     system("PAUSE");
     return EXIT_SUCCESS;
}
 
int* elabora(const int v1[], const int n)
/*
  * NB: qui 'n' ï¿œ il numero di elementi per cui bisogna allocare memoria
  *     non ï¿œ la dimensione di v1. Sarebbe tuttavia consigliato passare
  *     come parametri entrambe le cose, in casi piï¿œ generali. Ora qui
  *     ce la caviamo con la costante MAX.
  */
{
     int i, k, *p;
 
     p = malloc(n * sizeof(int));
 
     if(!p) {
         fprintf(stderr, "in elabora(): allocazione array dinamico "
                         "non riuscita\n");
         return p;
     }
 
     for(i = 0, k = 0; i < MAX; i++) {
         if(v1[i] > THRESHOLD) {
             p[k] = v1[i];
             k++;
         }
     }
     return p;
}
 
 
-- 
Vincenzo Mercuri

       for (i=0;i<10;i++)
[..]
 
Il cast a (int *) non � necessario, anzi puo' essere controproducente se
per esempio dimentichi di includere l'header "<stdlib.h>, non ti segnala
l'errore. Quello che � necessario � vedere de l'allocazione � andata a
buon fine. Non dimenticare mai di controllare se v2 � NULL. Dover allocare
pochissima memoria non � garantisce il successo di malloc().
 
-- 
Vincenzo Mercuri


Scusa, lo riscrivo in italiano: :)
 
Il cast a (int *) non � necessario, anzi puo' essere controproducente.
Se per esempio dimentichi di includere l'header "<stdlib.h>", non ti 
segnala
l'errore. Quello che � necessario � vedere se l'allocazione � andata a


io ho risolto come segue:
 
io ho risolto come segue:
 
#include  <stdio.h>
#include  <stdlib.h>
#include  "libreria.h"
 
// NB: P==printf R==return F==for  G==goto
// i32 qui � int  u32 � unsigned
// array di i32, terminati col numero INT_MAX
//               in pratica suppone che i valori utili siano 
//               in    [INT_MIN, INT_MAX-1]
 
i32*  ArrInt(i32* a)
{i32      *v, m;
 u32    i, j, n;
 
 if(a==0)  R  0;
 F(i=0, n=0; a[i]!=INT_MAX ; ++i)
    {if(i>= UINT_MAX/sizeof(i32) ) R  0;
     if(a[i]> 5) ++n;
    }
 ++n;
 
 v=malloc(n*sizeof *v);
 if(v==0)  R  0;
 // P("Elementi=%d\n", n);
 
 F(i=0, j=0, m=0; m!=INT_MAX; ++i)
   {if(i>=UINT_MAX/sizeof(i32)) 
            {ge: free(v); R  0;}
    m=a[i];
    // significa che INT_MAX viene scritto
    if(m>5){if(j>=n) G  ge;
            v[j]=m; ++j;
           }
   }
 R  v;
}
 
void StampaArr(i32*  v)
{u32  i;
 if(v==0){P("{}"); R;}
 P("{ ");
 F(i=0; v[i]!=INT_MAX ; ++i)
    P("%d ", v[i]);
 P("}"); 
}
 
int main(void)
{i32   v1[]={2,4,11,6,17,1,24,4,45,3, INT_MAX}, *v2=0;
 
 P("INi=");StampaArr(v1);P("\n");
 P("Ris=");StampaArr(v2);P("\n");
 
 v2=ArrInt(v1);
 if(v2){P("Ris=");StampaArr(v2);P("\n");
        free(v2);
       }
 R 0;
}
 
----------------
INi={ 2 4 11 6 17 1 24 4 45 3 }
Ris={}
Ris={ 11 6 17 24 45 }
 

 }
 
UCAS.
basta un for e un uso oculato della realloc()
 
Ciao Jack
-- 
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?