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