Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ -
Forum - C/C++ - "Compattare" un array...

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
AldoBaldo (Member)
Expert


Messaggi: 347
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 8:39
Giovedì, 08/10/2015
Rieccomi con una delle mie domande banali.

Per aggiornare un programmino che sto scrivendo (un programma da usare a scuola con le lavagne LIM in dotazione) ho necessità di dotarmi di un vettore di immagini che rappresentino le pagine sulle quali scrivere/disegnare. Per gestire un sistema di pagine multiple, tipo fogli di un blocco note, ho bisogno di gestire un vettore non dinamico (il programma prevede che si possano aggiungere e togliere pagine a piacere, ma solo entro un numero massimo di pagine predefinito) di HBITMAP di Win32 da selezionare secondo necessità, per cui devo assicurarmi che in quel vettore non compaiano mai valori NULL entro la gamma delle pagine disponibili. Questo comporta che all'eliminazione delle pagine io debba "compattare" il vettore per eliminare i valori NULL che derivano dall'eliminazione (possono essere in qualsiasi posizione e in qualsiasi quantità entro il massimo previsto). Ho pensato a una funzione come quella che riporto qui sotto, che dai test sembra funzionare a dovere. La domanda è: mi sapete consigliare un metodo migliore per "compattare" l'array, nei limiti della difficoltà limitata che sono in grado di gestire?

Codice sorgente - presumibilmente C#

  1. // Nella funzione che segue, pp e' un puntatore ad un vettore di elementi di
  2. // tipo HBITMAP che contiene totEl HBITMAP (potrebbe comunque essere il
  3. // puntatore ad un vettore di elementi di qualsiasi altro tipo). L'intenzione
  4. // e' "compattare" quegli elementi in modo da eliminare ogni HBITMAP di valore
  5. // NULL compreso tra HBITMAP di valore non NULL. Per ottenere lo scopo ricorre
  6. // a due puntatori ausiliari a HBITMAP, p1 e p2.
  7.  
  8. void CompattaArrayHBITMAP( HBITMAP *pp, int totEl ) {
  9.     HBITMAP *p1, *p2;
  10.     p1 = p2 = pp;
  11.  
  12.     do {
  13.         while( *p2==NULL && p2<(pp+totEl) ) ++p2; // cerca il primo non NULL
  14.  
  15.         if( p2 == (pp+totEl) ) break; // siamo in fondo all'array
  16.  
  17.         if( p1 != p2 )
  18.             *p1++ = *p2++;    // sposta e incrementa
  19.         else { ++p1; ++p2; }  // incrementa senza spostare
  20.     } while( true ); // per sempre! esce col break
  21.  
  22.     while( p1<(pp+totEl) ) *p1++ = NULL; // "annulla" gli HBITMAP rimanenti
  23. }



Ma cosa vuoi che ne sappia? Io ci gioco, col codice, mica ci lavoro!
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 347
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 8:42
Giovedì, 08/10/2015
Dimenticavo... non me la sento di "infognarmi" con le STL, perché per ora mi confondono le idee ben più di quanto mi aiutino.


Ma cosa vuoi che ne sappia? Io ci gioco, col codice, mica ci lavoro!
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1459
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 18:43
Giovedì, 08/10/2015
Continui a portare gli elementi antecedenti al primo NULL indietro di una posizione finché l'ultimo elemento, prima in posizione k finisce in k - 1.....

PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 347
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 22:52
Giovedì, 08/10/2015
Sì. Va bene o è un procedimento stupido, secondo te? Puoi consigliarne dei migliori?


Ma cosa vuoi che ne sappia? Io ci gioco, col codice, mica ci lavoro!
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6116
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 0:34
Venerdì, 09/10/2015
Se non ci sono problemi di memoria, un modo più semplice (e veloce) è di allocare un nuovo array di HBITMAP e fare un singolo passo con un for loop. Qualcosa come:

Codice sorgente - presumibilmente C++

  1. HBITMAP *nuovo = new HBitmap[totEl];
  2.  
  3. for (int i = 0, int j = 0; i < totEl; i++){
  4.     if (*pp[i] != NULL) nuovo[j++] = pp[i];
  5. }
  6.  
  7. // j contiene la nuova dimensione dell'array
  8.  
  9. return nuovo;


Ultima modifica effettuata da pierotofy il 09/10/2015 alle 0:35


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
HeDo (Founder Member)
Guru^2


Messaggi: 2763
Iscritto: 21/09/2007

Segnala al moderatore
Postato alle 0:40
Venerdì, 09/10/2015


Ingegnere Informatico
https://ldlagency.it
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1459
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 8:28
Venerdì, 09/10/2015
No, riordinare l'array come ti ho consigliato va benissimo e non dovresti allocare e liberare memoria ogni volta che devi riordinare l'array. Se non puoi usare le liste è la cosa migliore

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6116
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 15:26
Venerdì, 09/10/2015
Testo quotato

Postato originariamente da TheDarkJuster:
riordinare l'array come ti ho consigliato va benissimo



A meno che il numero di elementi è particolarmente grande e la velocità d'esecuzione è importante. Fare uno shift senza un array secondario in questa maniera è O(n^2).


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
ZioCrocifisso (Member)
Pro


Messaggi: 135
Iscritto: 06/03/2013

Segnala al moderatore
Postato alle 19:11
Venerdì, 09/10/2015
Quell'operazione col for si può anche fare in-place, e poi eventualmente riallocare se è necessario. Se bisogna rimuovere un solo elemento, limitarsi a modificare l'array già esistente è più veloce che allocarne uno nuovo solo per risparmiare qualche byte.

Ultima modifica effettuata da ZioCrocifisso il 09/10/2015 alle 19:12


PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo