2016-06-07 2 views
-2

Я пытаюсь сохранить 2-мерный массив в указателе на указатель итеративно. Я заполняю его случайными значениями Гаусса, но это не важная часть. Я пытаюсь заполнить массив, на который указывает A, но получить ошибку «плохой код доступа». Как правильно заполнить массив/указатель? Благодарю.Назначить указатель на указатель в цикле C++

INT основной() {

int N = 100; 
double **A[N][N]; 
for(int i = 0; i< N; i++){ 
    for(int j =0; j < N; j++){ 
     random_device rd; 
     default_random_engine generator; 
     generator.seed(rd()); 
     normal_distribution<double> distribution(0.0,1.0); 
     **A[i][j] = distribution(generator); // error here, bad access code 1 
    } 
} 
+2

Обратите внимание, что ваша вторая строка объявляет двумерный массив указателей ** ** ** на двойные указатели **. вы можете изменять значения только на 'A [i] [j]'. Если вы хотите присвоить значение '** A [i] [j]', вы должны сначала выделить для него память, используя 'new'. – Xiobiq

+0

Предупреждение: вы не хотите, чтобы каждый раз, когда вы его используете, каждый раз переставляете генератор случайных чисел. Очень дорого и может привести к тому, что всегда будет получать одинаковое число, в зависимости от реализации 'std :: random_device'. Устанавливайте генератор только один раз в начале программы. – user4581301

ответ

2

Во-первых, изменить double **A[N][N]; к double **A;. Вам нужен двойной указатель, а не матрица двойных указателей. Затем вы должны выделить память следующим образом: A=new double*[N];, а затем for(i=0;i<N;i++) A[i]=new double[n]; Тогда все будет работать нормально. Вы получите доступ к элементу матрицы обычным способом, A[i][j], а не **A[i][j]! Этот пример кода познакомит вас с концепцией:

#include <iostream> 

int main() { 

    int n=100; 

    double **a; 
    a=new double*[n]; 
    for(int i=0;i<n;i++) a[i]=new double[n]; 

    a[1][2]=3; 

    std::cout<<a[1][2]; 

    for(int i=0;i<n;i++) delete a[i]; 
    delete[] a; 

    return 0; 
} 
+1

Ваш код не «удаляет» выделенную память – Xiobiq

+0

Спасибо, это работает. Теперь проблема в том, что я пытаюсь использовать программу svdcomp.C, которой вы должны передать двойной указатель. Когда я пропускаю ** A, он дает мне ошибку «никакой подходящей функции для вызова». Любые мысли или предложения здесь? – PatEugene

+1

@PatEugene Возможно, вы захотите спросить, что в отдельном вопросе – Xiobiq

1

Ошибка здесь:

**A[i][j] = distribution(generator); 

A[i][j] хранит значение типа double**. Поэтому вам нужно сначала сохранить ваше случайное значение в действительном адресе, а затем сохранить его в A.

/*Assign a new double* pointer to A[i][j]*/ 
A[i][j] = new double*; 

/*Assign a new double pointer which is addressed by A[i][j]*/ 
*A[i][j] = new double; 

/*Assign value to **A[i][j] */ 
**A[i][j] = distribution(generator); 
+0

'A [i] [j] = distribution (generator)' будет присваивать указатель на двойной указатель ('double **') значение 'double' – Xiobiq

+0

@Polikdir Я не знаю, какое значение имеет функция' distribution () 'возвращает, и думал, что это будет тип' double ** '. Было бы здорово, если бы вы могли сказать. –

+0

Прежде чем принимать такие вещи, вы должны были проверить [документацию] (http://en.cppreference.com/w/cpp/numeric/random/normal_distribution/operator()). Это также довольно интуитивно понятно. – Xiobiq

2

Вы не можете объявить статический массив, используя не-const integer для своих измерений.

Вы объявляете массив указателей, но указатели не указывают на какую-либо действительную память, поэтому вы получаете ошибки памяти.

Попробуйте вместо этого:

const int N = 100; 

double A[N][N]; 

random_device rd; 
default_random_engine generator; 
generator.seed(rd()); 
normal_distribution<double> distribution(0.0,1.0); 

for(int i = 0; i < N; ++i) { 
    for(int j = 0; j < N; ++j) { 
     A[i][j] = distribution(generator); 
    } 
} 

С другой стороны, выделить массив в куче, вместо стека (то вы можете использовать неконстантную Int для измерений):

int N = 100; 

double **A = new double*[N]; 
for(int i = 0; i < N; ++i) { 
    A[i] = new double[N]; 
} 

random_device rd; 
default_random_engine generator; 
generator.seed(rd()); 
normal_distribution<double> distribution(0.0,1.0); 

for(int i = 0; i < N; ++i) { 
    for(int j = 0; j < N; ++j) { 
     A[i][j] = distribution(generator); 
    } 
} 

... 

for(int i = 0; i < N; ++i) { 
    delete[] A[i]; 
} 
delete[] A; 

Или это :

int N = 100; 

double *A = new double[N*N]; 

random_device rd; 
default_random_engine generator; 
generator.seed(rd()); 
normal_distribution<double> distribution(0.0,1.0); 

for(int i = 0; i < N; ++i) { 
    for(int j = 0; j < N; ++j) { 
     A[(i*N)+j] = distribution(generator); 
    } 
} 

... 

delete[] A; 

с учетом сказанного, то лучше использовать std::vector вместо new[] вручную:

int N = 100; 

std::vector<std::vector<double> > A(N); 
for(int i = 0; i< N; i++) { 
    A[i].resize(N); 
} 

random_device rd; 
default_random_engine generator; 
generator.seed(rd()); 
normal_distribution<double> distribution(0.0,1.0); 

for(int i = 0; i < N; ++i) { 
    for(int j = 0; j < N; ++j) { 
     A[i][j] = distribution(generator); 
    } 
} 

Или:

int N = 100; 

std::vector<double> A(N*N); 

random_device rd; 
default_random_engine generator; 
generator.seed(rd()); 
normal_distribution<double> distribution(0.0,1.0); 

for(int i = 0; i < N; ++i) { 
    for(int j = 0; j < N; ++j) { 
     A[(i*N)+j] = distribution(generator); 
    } 
} 
+0

@ M.M: Я изменил свой ответ. –

Смежные вопросы