在C ++中初始化大型二维数组

时间:2010-08-11 15:32:45

标签: c++ arrays

我希望在类中包含 static 常量二维数组。该数组相对较大,但我只想初始化一些元素,而其他元素可能是编译器初始化它们。

例如,如果类被定义为:

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}
};

我只对初始化标有'7'的元素感兴趣,我如何对相同的元素执行此操作,但是使用较大的数组,如array [1024] [1024]?

8 个答案:

答案 0 :(得分:31)

初始化的数组中任何超出初始化的部分都被初始化为0.因此:

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

这意味着您必须初始化的所有内容都是最后一个非零:

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}
};

这不是最佳解决方案,但可以节省一些工作。

答案 1 :(得分:7)

初始化后,无法将const数组赋给const数组。所以你必须编写脚本:

以这种方式包含您的文件:

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.
};

答案 2 :(得分:3)

巧合的是,在阅读了你的问题几个小时之后,我在书中寻找其他内容时遇到了一个可能的解决方案"C - A Reference Manual" 5th ed., Harbison/Steele(顺便说一句,这是一个很棒的C引用)。

根据这本书,

  

C99允许您命名要在初始化列表中初始化的聚合(结构,联合或数组)的组件。

......它举了一个例子:

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

因此,根据编译器的合规性和数组中非零元素的大小,您可以使用此语法有效地初始化矩阵。也就是说,本书没有给出二维数组的例子。不幸的是,我无法测试这个想法,因为MSVC ++ 2005似乎不支持C99。

答案 3 :(得分:1)

当我这样做时,我使用一种方法来读取数据。通常,它看起来像:

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;
}

答案 4 :(得分:0)

您只能通过访问者函数/宏访问数组并安排内部存储,以便初始化部分先行。

答案 5 :(得分:0)

解决方案是在某处隐藏非const数组,从文件或资源加载它,然后使用const引用来访问它。即

#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;
}

它(IMO)比脚本生成的巨大阵列更具可读性。

你可以用类似2D数组的类做同样的事情(很容易写)。再次 - 在某处使用非const对象,并使用const引用来访问数据。应该很容易使非const数组完全不可见,只有一个cpp。

另一种方法是使用脚本生成数组。如果您认为大数组是丑陋的,请将整个内容放入* .h文件中(确保它只包含在一个* .cpp文件中),这样就不会吓跑人们了。只要语法正确,编译器就不关心你在代码中写的是什么。

我认为没有其他选择。

答案 6 :(得分:0)

使用std::fill_n

只需要四行
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);

答案 7 :(得分:-5)

安装R软件,它是免费的! 然后使用

调用下面定义的函数
  

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

如果数据是你的矩阵那么你就完成了


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)
}