Vai al contenuto
matt_dev

Programmazione [Linguaggio C] - Problema con vettori dinamici di puntatori a struct

Recommended Posts

Buonsalve.

 

Mi ritrovo oggi con un problema che va oltre le mie competenze attuali (colpa del mio non seguire appieno le lezioni? è un'altra storia..).

Dovrei scrivere un programma in cui ho due elementi principali:

  1. Un vettore di struct Item allocato dinamicamente (chiamato v);
  2. Un vettore di puntatori a struct Item, i quali puntano proprio al vettore sopra citato (chiamato vP).

Nella pratica, la mia struct è:

typedef struct {   int matricola;   char nome[30], cognome[30];} Item;

v avrà lunghezza t ad esempio, e i suoi elementi dipenderanno da un file.

vP invece, punterà a v, e sarà ordinato per numero di matricola.

 

Ora: la lettura di v e la gestione del file sono banali. Il mio problema ricade su vP, poiché v dovrà mantenere il medesimo ordinamento di lettura, mentre vP dovrà essere ordinato per matricole.

Le mie domande dunque sono le seguenti:

  1. Come dichiaro il mio vettore di puntatori a Item?
  2. Come faccio a far sì che vP punti a v e venga ordinato, senza che v cambi il suo ordinamento?

Spero di esser stato abbastanza chiaro, in caso contrario sono pronto a dare delucidazioni sulla domanda.

Grazie a chiunque mi possa aiutare :ymmio:

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

provo ad aiutarti, anche se non sono bravo  :eqw:

 

v avrà lunghezza t ad esempio, e i suoi elementi dipenderanno da un file.

cioè, nome, cognome e matricola li prendi da un file o cosa?

 

v deve rimanere così come è stato caricato mentre vp deve essere ordinato per numero di matricola? ho capito bene?

 

vp deve essere un vettore parallelo a v ed ogni elemento di vp deve puntare ad un elemento di v esatto?

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Scrivo dall'uni e mi baso su quello che hai scritto, sarò per forza di cose sintetico e con più errori del solito.

Ora, il problema che hai è sull'utilizzo dei puntatori, un classico in C e C++.

Provo a darti qualche indizio prima del codice già bello e funzionante.

Quello che vuoi fare è scambiare i puntatori (così da non toccare gli elementi di v) tra le posizioni dell'array vP. Possono esserci due problemi qui:

1) L'assegnamento errato tra gli elementi di v e i suoi puntatori in vP;

2) Lo scambio, che deve riguardare *solo* i puntatori, non gli elementi originali.

In base a come fai le cose dovresti ottenere addirittura degli errori a tempo di compilazione.

Quindi cosa succede con tuo codice? Non si scambiano i puntatori? O si scambiano anche i valori originali?

In base all'errore possiamo provare ad aiutarti a capire dove sbagli nello specifico o semplicemente darti qualche dritta. ;)

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

provo ad aiutarti, anche se non sono bravo  :eqw:

 

v avrà lunghezza t ad esempio, e i suoi elementi dipenderanno da un file.

cioè, nome, cognome e matricola li prendi da un file o cosa?

 

v deve rimanere così come è stato caricato mentre vp deve essere ordinato per numero di matricola? ho capito bene?

 

vp deve essere un vettore parallelo a v ed ogni elemento di vp deve puntare ad un elemento di v esatto?

 

  • Sì li prendo da file, e quello come ho scritto, è banale e irrilevante: sappi che v ad ogni posizione ha matricola, nome e cognome;
  • Hai capito bene :zizi: v infatti lo leggo e non devo ordinarlo;
  • Esattamente :ok:

 

Scrivo dall'uni e mi baso su quello che hai scritto, sarò per forza di cose sintetico e con più errori del solito.

Ora, il problema che hai è sull'utilizzo dei puntatori, un classico in C e C++.

Provo a darti qualche indizio prima del codice già bello e funzionante.

Quello che vuoi fare è scambiare i puntatori (così da non toccare gli elementi di v) tra le posizioni dell'array vP. Possono esserci due problemi qui:

1) L'assegnamento errato tra gli elementi di v e i suoi puntatori in vP;

2) Lo scambio, che deve riguardare *solo* i puntatori, non gli elementi originali.

In base a come fai le cose dovresti ottenere addirittura degli errori a tempo di compilazione.

Quindi cosa succede con tuo codice? Non si scambiano i puntatori? O si scambiano anche i valori originali?

In base all'errore possiamo provare ad aiutarti a capire dove sbagli nello specifico o semplicemente darti qualche dritta. ;)

 

Dal mio codice, si scambiano anche i valori originali..

 

Ora credo di aver semi-risolto, ditemi se è corretto: prendendo il puntatore vP e assegnandogli gli indirizzi di v, ho creato una funzione che ordini il vettore vP scambiando gli indirizzi in memoria alle varie posizioni. Così facendo v rimane intatto e vP è ordinato.

 

Può reggere come algoritmo o ce ne sono di migliori?

 

Grazie ancora :^^:

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Dal mio codice, si scambiano anche i valori originali..

 

Ora credo di aver semi-risolto, ditemi se è corretto: prendendo il puntatore vP e assegnandogli gli indirizzi di v, ho creato una funzione che ordini il vettore vP scambiando gli indirizzi in memoria alle varie posizioni. Così facendo v rimane intatto e vP è ordinato.

 

Può reggere come algoritmo o ce ne sono di migliori?

 

Grazie ancora %5E%5E.png

 

Direi che ci siamo allora. ;) L'esercizio richiede proprio di fare questo, difficile che ci siano molti modi diversi di farlo. Se ora stai gestendo bene puntatori e indirizzi allora tutto dovrebbe funzionare tranquillamente. Magari l'unica cosa diversa dal solito era fare qualcosa come:

Item *temp = &v[i];
Se l'hai implementato una qualche funzione di swap in questo modo. Altrimenti l'importante è che funzioni correttamente. ;)

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

 

Direi che ci siamo allora. ;) L'esercizio richiede proprio di fare questo, difficile che ci siano molti modi diversi di farlo. Se ora stai gestendo bene puntatori e indirizzi allora tutto dovrebbe funzionare tranquillamente. Magari l'unica cosa diversa dal solito era fare qualcosa come:

Item *temp = &v[i];
Se l'hai implementato una qualche funzione di swap in questo modo. Altrimenti l'importante è che funzioni correttamente. ;)

 

 

Sì è una cosa molto simile, avendo dato a ciascun vP l'indirizzo corrispettivo di v, faccio lo swap scambiando gli indirizzi dei puntatori ai vari indici, e sembra funzionare!

L'unica cosa che mi sembrava strana era che dovevo iterare ciascun indice e assegnare il corrispettivo indirizzo.. per capirci:

int i, n = 3;Item *v, **vP;v = malloc(n*sizeof(Item));vP = malloc(n*sizeof(Item*));for (i=0; i<n; i++) {   vP[i] = &(v[i]);}

E non semplicemente una cosa del tipo vP = &v;

Sarà che non ho ancora capito bene come funziona, ma il codice che ho scritto funziona alla grande per fortuna :zizi:

 

Se posso ti chiederei un'altra cosa velocissima.. la riallocazione di un puntatore con realloc esiste o non si può fare?

Perché nel codice non riuscivo a riallocare il vettore di puntatori (come secondo esercizio), allora ho fatto un semplice;

free(vP);vP = malloc((n+i)*sizeof(Item*));

Dove i è l'incremento dell'indice di allocazione. Questo anche funziona alla grande, ma vorrei capire se si può fare anche con realloc.

 

Grazie per la pazienza Scan!

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Sì, devi per forza ciclare su tutti gli elementi perché tu vuoi proprio un puntatore per elemento in questo caso. Con l'istruzione

vP = &v

Avresti qualcosa del genere

v  [Item_1|Item_2|...|Item_n]      ^      |vP [  |  ]

In pratica solo un puntatore all'altro array. Invece ti serve, come hai fatto, una situazione del tipo:

v  [Item_1|Item_2|...|Item_n]      ^      ^          ^      |      |          |  vP [  |   |  |   |...|  |   ]

In cui puoi scambiare i vari puntatori in vP.
 
La reallocazione con realloc si può fare ovviamente e gestisce tutto internamente nel caso ci sia da fare con la memoria. Devi però controllare il valore di ritorno: realloc se fallisce ritorna NULL (da controllare) o altrimenti un puntatore alla nuova area di memoria allocata di grandezza size.

Se tutto è andato a buon fine potrai quindi assegnare al vecchio puntatore la nuova area di memoria. Se dai un'occhiata all'esempio che fanno sul sito che ho linkato magari hai le idee più chiare. ;) Altrimenti:

vP = malloc(n * sizeof(Item *));

/* ... */

Item *vP_new = NULL;

vP_new = realloc(vP, (n+i) * sizeof(Item *));

if (vP_new != NULL) {
    vP = vP_new;
} else {
    fprintf(stderr, "Error with realloc()");
}

E figurati, se non io ci sono altri pronti a risponderti. ;)

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

@Scanetatore ora è chiaro, risolvo con una variabile temporanea diciamo, che rialloco in base a vP e poi ne assegno l'indirizzo.

Got it! :^^:

 

Credo di non aver più domande (per ora.. quest'anno la vedo dura...) grazie ancora!

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti
Ospite
Questa discussione è chiusa.

×