2010-08-11 33 views
16

Ich möchte statische und Konstante zweidimensionale Array innerhalb einer Klasse haben. Das Array ist relativ groß, aber ich möchte nur ein paar Elemente initialisieren, und andere sind möglicherweise, was auch immer der Compiler initialisiert.Initialisieren großen zweidimensionalen Array in C++

Zum Beispiel, wenn eine Klasse definiert wie:

class A { 
public: 
    static int const test[10][10]; 
}; 

int const A::test[10][10] = { 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 
}; 

und ich bin nur daran interessiert, die Elemente mit ‚7‘ markiert zu initialisieren, wie mache ich das auf die gleichen Elemente, aber mit Array von größere Größe, wie Array [1024] [1024]?

+1

Err ... Sie scheinen bereits die richtige Lösung zu haben. –

+0

Wie wichtig ist es, dass Ihre Daten konstant sind? –

+1

@Billy: Aber er wird 789 Jahre brauchen, um ein 1024 x 1024 Array zu kodieren. –

Antwort

26

Jeder Teil eines Arrays, das initialisiert wird, dass über die Initialisierung ist, wird auf 0 gesetzt Daher initialisiert:

int const A::test[10][10];   // uninitialized 

int const A::test[10][10] = { {0} }; // all elements initialized to 0. 

int const A::test[10][10] = {1,2}; // test[0][0] ==1, test[0][1]==2, rest==0 

Das bedeutet, alles, was Sie initialisieren müssen die letzten Nicht-Null liegt:

int const A::test[10][10] = { 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0}, 
    {0, 0, 0, 7, 7, 7, 7, 0, 0, 0} 
}; 

Es ist nicht die beste Lösung, aber spart etwas Arbeit.

+3

Auch, weil wir nicht Elemente schreiben müssen, die uns nicht interessieren, wie: int const A :: test [10] [10] = {{}, {}, {}, {0, 0 , 0, 7, 7, 7, 7}, {0, 0, 0, 7, 7, 7, 7}, {0, 0, 0, 7, 7, 7, 7}, {0, 0, 0 , 7, 7, 7, 7}} –

+0

@Matthew leere Initialisierungslisten sind eine GNU-Erweiterung. – a3f

0

Sie können auf das Array nur über Accessor-Funktionen/Makros zugreifen und den internen Speicher so anordnen, dass der initialisierte Teil zuerst geht.

0

Eine Lösung wäre, nicht-const-array irgendwo auszublenden, es aus Datei oder Ressource zu laden und dann const-Referenz zu verwenden, um darauf zuzugreifen. I.e.

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 

typedef int Array[1024][1024]; 

namespace DontTouch{ 
    Array arr; 
    void initArray(){ 
     for (int i = 0; i < 1024; i++) 
      for (int j = 0; j < 1024; j++) 
       arr[i][j] = rand() & 0xff; 
    } 
} 

const Array &arr = DontTouch::arr; 

int main(int argc, char** argv){ 
    DontTouch::initArray(); 

    //arr[4][4] = 0;//compiler error    
    for (int i = 0; i < 1024; i++){ 
     for (int j = 0; j < 1024; j++) 
      printf(" 0x%02x", arr[i][j]); 
     printf("\n"); 
    } 

    return 0; 
} 

Es wird (IMO) lesbarer sein als Skript-generierte riesige Array.

Sie können dasselbe mit Klasse tun, die wie 2D-Array funktioniert (einfach genug zu schreiben). Erneut - habe irgendwo ein nicht-konstantes Objekt und verwende const-Referenz, um auf die Daten zuzugreifen. Es sollte einfach sein, ein nicht-konstantes Array außerhalb von nur einem cpp vollständig unsichtbar zu machen.

Ein anderer Weg, um dies zu tun, ist Array mit Skript zu generieren. Wenn du denkst, dass große Arrays hässlich sind, lege das ganze Ding in die * .h-Datei (stelle sicher, dass es nur in einer * .cpp-Datei enthalten ist), damit es die Leute nicht verscheucht. Dem Compiler ist es egal, was Sie in Ihrem Code schreiben, solange er syntaktisch korrekt ist.

Ich glaube nicht, dass es andere Optionen gibt.

+0

Danke, aber hier Benutzer muss DontTouch :: initArray() aufrufen, und ich möchte, dass dieses Array automatisch initialisiert wird. Außerdem möchte ich Array statisch sein, const Klassenmitglied ... scheint, dass nur die Lösung das große generierte Array ist ... –

+0

Matthew Murdock: "und ich möchte, dass dieses Array automatisch initialisiert wird" eine Klasse erstellen, die das Array initialisiert innerhalb der Konstruktion und lege eine statische Instanz dieser Klasse irgendwo hin. Sie erhalten eine automatische Initialisierung. – SigTerm

7

Es gibt keine Möglichkeit, nach der Initialisierung ein int-Array zu const zuzuweisen. So werden Sie zum Skript zusammen:

und geben Sie Ihre Datei auf diese Weise:

class A { 
public: 
    static const int test[10][10]; 
}; 

const int A::test[10][10] = { 
#include "data.inc" // points to the file generated by script. 
}; 
+0

Dies ist eine gültige und ziemlich unkomplizierte Lösung (insb. Wenn Sie Offline-Scripting in Betracht ziehen, um die Header-Datei zu erzeugen). Es kann sich jedoch als problematisch erweisen, wenn Sie mit einem eingebetteten System mit einem engen Speicher umgehen. Aus irgendeinem Grund, der für mich unklar ist, wird die Initialisierung von Variablen in allen von mir untersuchten Compiler-Instanzen in der Laufzeit und nicht in der Ladezeit durchgeführt, was bedeutet, dass das Array von Initialisierungswerten zusätzlichen Speicherplatz belegt -top des Speicherplatzes, der von der eigentlichen Array-Variablen selbst zugewiesen wurde. – ysap

1

Wenn ich das tue, verwende ich eine Methode in Daten zu lesen. Generisch, es sieht aus wie:

extern void ReadElements(string sFile, Matrix a) 
{ 
    int x; 
    int y; 
    double value; 

    ifstream myInFile; 

    myInFile.open(sFile, ifstream::in); 
    while(!myInFile.eof()) 
    { 
     myInFile >> x >> y >> value; 
     a[x][y] = value; 
    } 

    myInFile.close(); 
    return; 
} 
+0

Aber wird es für 'const' Array funktionieren? – ysap

3

Zufälligerweise ein paar Stunden nach der Frage lesen, ich in eine mögliche Lösung gestoßen, während "C - A Reference Manual" 5th ed., Harbison/Steele etwas anderes im Buch suchen (dies ist eine fantastische C Referenz, durch die Art und Weise).

Nach dem Buch,

C99 können Sie die Komponenten eines Aggregats (structs, Vereinigung oder Array) benennen innerhalb einer Initialisiererliste initialisiert werden.

... und es gibt ein Beispiel:

int a1[5] = { [2]=100, [1]=3 }; /* eqv. to {0, 3, 100, 0, 0} */ 

So, abhängig von der Einhaltung des Compilers und auf der Größe der Nicht-Null-Elemente im Array, können Sie in der Lage zu Verwenden Sie diese Syntax, um Ihre Matrix effizient zu initialisieren. Das heißt, das Buch gibt kein Beispiel für 2D-Arrays. Leider konnte ich diese Idee nicht testen, da MSVC++ 2005 C99 nicht zu unterstützen scheint.

+0

GCC unterstützt dies nur in C, nicht in C++. – slacker

+0

ysap, danke, aber ich habe es nur mit C und gcc als Compiler arbeiten lassen. In Visual Studio funktioniert es nicht ... –

-5

R-Software installieren, es ist kostenlos! dann die Funktion unten definiert rufen mit

writetable(data,"test","myfile.h")

wenn Daten Ihre Matrix ist dann sind Sie fertig


writetable<-function(data,varname="test",file="myFile.hpp"){ 
    cat('const static double CONST_array_',varname," [][] = { \n \t\t\t\t {",file=file,append=TRUE,sep='') 
    for (j in 1:(dim(data)[2]-1)){ 
    for (i in 1:(dim(data)[1]-1)){ 
     cat(data[i,j],',',file=file,append=TRUE) 
    } 
    cat(data[dim(data)[1],j],'},\n \t\t\t\t\t{',file=file,append=TRUE) 
    } 
    for (i in 1:(dim(data)[1]-1)){ 
    cat(data[i,dim(data)[2]],',',file=file,append=TRUE) 
    } 
    cat(data[dim(data)[1],dim(data)[2]],'}\n }; \n',file=file,append=TRUE) 
} 
0

Es dauert nur vier Zeilen von std::fill_n

mit
using std::fill_n; 
using std::begin; 

fill_n(begin(test[3])+3, 4, 7); 
fill_n(begin(test[4])+3, 4, 7); 
fill_n(begin(test[5])+3, 4, 7); 
fill_n(begin(test[6])+3, 4, 7); 
+0

funktioniert nicht auf 'const'. – syockit

Verwandte Themen