2010-10-16 8 views

risposta

13

Il modo più semplice per inizializzare a 0 l'array è nella definizione:

char flags[26][80] = {}; 

Se si desidera utilizzare std::fill, o se si vuole ripristinare l'array, ho trovato questo un po 'meglio:

char flags[26][80]; 
std::fill(&flags[0][0], &flags[0][0] + sizeof(flags) /*/sizeof(flags[0][0]) */, 0); 

il fill espresso in termini di dimensioni dell'array ti permetterà di cambiare le dimensioni e mantenere intatto lo fill. Il sizeof(flags[0][0]) è 1 nel tuo caso (sizeof(char)==1), ma potresti voler lasciarlo nel caso in cui desideri cambiare il tipo in qualsiasi punto.

In questo caso particolare (array di bandiere tipo --integral) ho potuto anche considerare l'utilizzo memset anche se è il meno sicuro alternativa (questo si romperà se il tipo di matrice viene modificato in un non-pod type):

memset(&flags[0][0], 0, sizeof(flags)); 

Si noti che in tutti e tre i casi, le dimensioni dell'array vengono digitate solo una volta e il compilatore deduce il resto. Questo è un po 'più sicuro in quanto lascia meno spazio per errori del programmatore (cambiare le dimensioni in un unico posto, dimenticarlo negli altri).

MODIFICA: il codice è stato aggiornato e poiché non verrà compilato poiché l'array è privato e si sta tentando di inizializzarlo esternamente. A seconda che la tua classe sia effettivamente un aggregato (e vuoi mantenerlo tale) o se vuoi aggiungere un costruttore alla classe, puoi usare approcci diversi.

const std::size_t rows = 26; 
const std::size_t cols = 80; 
struct Aggregate { 
    char array[rows][cols]; 
}; 
class Constructor { 
public: 
    Constructor() { 
     std::fill(&array[0][0], &array[rows][0], 0); // [1] 
     // memset(array, 0, sizeof(array)); 
    } 
private: 
    char array[rows][cols]; 
}; 
int main() { 
    Aggregate a = {}; 
    Constructor b; 
} 

Anche se il array è destinata ad essere pubblica, utilizzando un costruttore potrebbe essere un approccio migliore in quanto garantirà che la array viene inizializzato correttamente in tutte le istanze della classe, mentre l'inizializzazione esterna dipende da codice utente non dimenticando di impostare i valori iniziali.

[1] Come @Oli Charlesworth menzionato in un commento, l'uso delle costanti è una soluzione diversa al problema di dover indicare (e mantenere sincronizzate) le dimensioni in più di un punto. Ho usato questo approccio qui con una combinazione ancora diversa: un puntatore al primo byte al di fuori dell'array bidimensionale può essere ottenuto richiedendo l'indirizzo della prima colonna di una riga oltre l'array bidimensionale. Ho usato questo approccio solo per dimostrare che può essere fatto, ma non è migliore di altri come &array[0][0]+(rows*cols)

+2

+1 per 'char flag [26] [80] = {}' :) –

+0

+1. Tuttavia, un'alternativa all'utilizzo di 'sizeof' è di' # define' (o 'const int') le dimensioni. Questo ha il vantaggio aggiunto che funzionerà se hai passato 'flags' come argomento di funzione, in modo che sia decaduto su un puntatore quindi' sizeof' non darà più il risultato corretto. –

+0

Non sono sicuro di poter utilizzare le parentesi di inizializzazione perché l'array 2d si trova all'interno di una classe. Ti darò la possibilità di aggiornare prima di accettare. – Truncheon

2

è sicuro, una matrice bidimensionale è una matrice di matrici. Dal momento che un array occupa memoria contigua, così sarà anche l'intera cosa multidimensionale. Quindi sì, è OK, sicuro e portatile. Supponendo che non sta chiedendo di stile, che è coperto da altre risposte (dal momento che si sta utilizzando bandiere, vi raccomando vivamente std::vector<std::bitset<80> > myFlags(26))

+0

Sei sicuro il bitset sarebbe adatto ? Sto solo memorizzando uno zero o uno all'interno di ogni spazio nell'array 2d. Questi flag vengono utilizzati per tenere traccia di quali posizioni sulla console sono state aggiornate con la mia routine di floodfill. – Truncheon

+0

@Truncheon: memorizzi 8 valori in un carattere, giusto? E per ottenere, diciamo, il settimo valore nel sesto carattere devi fare un po 'di shifting/anding ecc. Il bitset lo farà per te. Vale a dire, memorizzerà ogni flag in un bit, e puoi impostare/rimuovere un flag ogni flag dal suo indice senza preoccuparti dei pattern di bit. L'unico svantaggio è che la dimensione del bitset deve essere una costante in fase di compilazione. Se hai familiarità con boost, hanno dynamic_bitset che è praticamente il suo nome. –

+0

Credo che stia memorizzando un singolo bit in ogni byte. Ciò significa che usando un bitset di 26 * 80 posizioni e l'algebra '(row, col) -> index appropriata l'uso di un singolo' bitset' sarà più efficiente nel consumo di memoria. –

0

char[80] è supposto essere un sostituto per un tipo di stringa reale?In tal caso, vi consiglio il seguente:

std::vector<std::string> flags(26); 
flags[0] = "hello"; 
flags[1] = "beautiful"; 
flags[2] = "world"; 
// ... 

Oppure, se si dispone di un compilatore C++ che supporta gli elenchi di inizializzazione, ad esempio un recente compilatore g ++:

std::vector<std::string> flags { "hello", "beautiful", "world" /* ... */ }; 
Problemi correlati