Инициализировать большой двумерный массив в С++
Я хочу иметь статический и постоянный двухмерный массив внутри класса. Массив относительно велик, но я хочу только инициализировать несколько элементов, а другие могут быть независимо от того, компилятор их инициализирует.
Например, если класс определен как:
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", как это сделать на тех же элементах, но с массивом большего размера, например массивом [1024] [1024]?
Ответы
Ответ 1
Любая часть инициализированного массива, которая находится за пределами инициализации, инициализируется равным 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}
};
Это не лучшее решение, но сохранит некоторую работу.
Ответ 2
Невозможно назначить массив int для const после его инициализации. Итак, вам придется script его:
И включите файл следующим образом:
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.
};
Ответ 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} */
Таким образом, в зависимости от соответствия вашего компилятора и размера ненулевых элементов в вашем массиве вы можете использовать этот синтаксис для эффективного создания вашей матрицы. Тем не менее, книга не дает примера для 2D-массивов. К сожалению, я не смог проверить эту идею, поскольку MSVС++ 2005, похоже, не поддерживает C99.
Ответ 4
Когда я это делаю, я использую метод для чтения данных. Как правило, это выглядит так:
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;
}
Ответ 5
Вы можете получить доступ к массиву только через функции доступа/макросы и упорядочить внутреннее хранилище, чтобы сначала была инициализированная часть.
Ответ 6
Решение заключалось бы в том, чтобы спрятать не-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) более читабельным, чем script -генерированный огромный массив.
Вы можете сделать то же самое с классом, который действует как 2D-массив (достаточно простой для записи). Опять же - где-то есть неконстантный объект и используйте ссылку const для доступа к данным. Было бы легко сделать non-const массив полностью невидимым за пределами только одного cpp.
Другой способ сделать это - создать массив, используя script. Если вы считаете, что большие массивы уродливы, поместите всю вещь в *.h файл (убедитесь, что он включен только в один файл *.cpp), поэтому он не пугает людей. Компилятору все равно, что вы пишете в коде, если он синтаксически корректен.
Я не думаю, что есть другие варианты.
Ответ 7
Это занимает всего четыре строки, используя 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);
Ответ 8
Могу ли я задать вопрос, связанный с этой темой? На самом деле мне нужно кодировать 2-мерный массив, где число строк равно 339. Я пытался это кодировать, но я думаю, что количество строк ограничено 59. Как я могу определить свой массив?
Ответ 9
установить программное обеспечение 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)
}