Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problemino di funzione che restituisce un vettore al main

30 views
Skip to first unread message

lucas

unread,
Apr 29, 2013, 6:52:01 PM4/29/13
to
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

fma...@gmail.com

unread,
Apr 30, 2013, 2:21:19 AM4/30/13
to
On Tuesday, April 30, 2013 12:52:01 AM UTC+2, lucas wrote:
> 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];
> [...]

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!

lucas

unread,
Apr 30, 2013, 3:21:12 AM4/30/13
to
Il 30/04/2013 8.21, fma...@gmail.com ha scritto:
> 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.

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

lucas

unread,
Apr 30, 2013, 4:49:18 AM4/30/13
to
Il 30/04/2013 9.21, lucas ha scritto:

> che ne dici?
> 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;
}

Manlio Perillo

unread,
Apr 30, 2013, 7:28:10 AM4/30/13
to
Il Tue, 30 Apr 2013 09:21:12 +0200, lucas ha scritto:

> Il 30/04/2013 8.21, fma...@gmail.com ha scritto:
>> 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.
>
> 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.
>

In generale, io preferisco che sia chi chiama a passare l'array delle
dimensioni giuste.

> 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;

Questo non ha senso. Perchè non modifichi direttamente v2? Inoltre
restituisci il numero di elementi processati, invece di w.

Infine, specifica il fatto che v1 non viene modificato.

> [...]


Ciao Manlio

lucas

unread,
Apr 30, 2013, 8:56:08 AM4/30/13
to
Il 30/04/2013 13.28, Manlio Perillo ha scritto:
> Inoltre
> 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

fma...@gmail.com

unread,
Apr 30, 2013, 9:24:04 AM4/30/13
to
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!

Manlio Perillo

unread,
Apr 30, 2013, 9:47:49 AM4/30/13
to
Il Tue, 30 Apr 2013 14:56:08 +0200, lucas ha scritto:

> Il 30/04/2013 13.28, Manlio Perillo ha scritto:
>> Inoltre
>> 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.
>

Di certo, la tua funzione *non crea* v2; assumendo che per creare si
intenda allocare. w è un alias di v2, che viene creato in 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"),

Ok allora, non avevo riletto quel testo.

> 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.
>

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


Ciao Manlio

Vincenzo Mercuri

unread,
Apr 30, 2013, 2:36:10 PM4/30/13
to
On 30/04/2013 00:52, lucas wrote:
> 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>

L'header <string.h> non ᅵ necessario per questo esercizio.

>
> 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);

Ogni volta che assegni qualcosa a un puntatore devi verificare che quel
valore abbia senso, cioᅵ che almeno non sia NULL altrimenti qualunque
operazione fai ha un comportamento indefinito (undefined behaviour - UB).

> 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;
> }
>

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

Vincenzo Mercuri

unread,
Apr 30, 2013, 2:41:38 PM4/30/13
to
On 30/04/2013 10:49, lucas wrote:
[..]
>
> 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++)
[..]

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

Vincenzo Mercuri

unread,
Apr 30, 2013, 2:55:00 PM4/30/13
to
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

Rosario1903

unread,
May 16, 2013, 12:40:00 PM5/16/13
to
On Tue, 30 Apr 2013 00:52:01 +0200, lucas wrote:
>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:

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 }

Jack

unread,
May 17, 2013, 4:28:27 AM5/17/13
to
Rosario1903 <Ros...@invalid.invalid> wrote:

> On Tue, 30 Apr 2013 00:52:01 +0200, lucas wrote:
> >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:
>
> io ho risolto come segue:

Il codice sotto e' da buttare.

> // NB: P==printf R==return F==for G==goto

ma perche' sta cosa?
Non guadagni niente e rende il codice molto meno leggibile


> // 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]

non mi pare che nell'esercizio ci sia scritto che l'array e' terminato
con il numero INT_MAX.
Visto che sai gia' che il vettore e' lungo 10, usala questa
informazione.

>
> i32* ArrInt(i32* a)
> {i32 *v, m;
> u32 i, j, n;

mi raccomando la prossima volta usa dei nomi di variabili ancora meno
significativi.

>
> 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;
> }

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?
0 new messages