2009-12-13 3 views
0

У меня проблема с двухмерными массивами :(Я чувствую себя очень глупо, и Visual C не помогает мне :(И я также считаю, что моя ошибка очень глупа, но все же я не могу ее найти :(у меня есть этот код:C++ двухмерные массивы с указателями

double matrix[100][100]; //which is full with a matrix 3x4 
double nVector[10000]; // for negative doubles 
//I wanted to see if there are negative doubles in each row and column 
//and I want this to happen with function 

И это моя функция:

double* negativeVector(double*nVector, double*fromVector, int m, int n){ 
    int position = 0; 

    double *myNegArray = nVector; 
    double *myMatrix = fromVector; 

    for(int i = 0; i < m*n; i++) 
     if(*(*(myMatrix+i)) < 0){ 
      *(myNegArray+position) = *(*(myMatrix+i)); 
      position++; 
     } 

    return myNegArray; 
} 

//for double*nVector I'm passing nVector 
//for double*fromVector I'm passing *matrix 

Visual C говорит мне, что у меня есть ошибка C2100: незаконное косвенность здесь: *(*(myMatrix+i)) Я надеюсь, что кто-то может мне помочь (happy)

Спасибо заранее!

+1

Почему бы не использовать std :: vector? Кроме того, компилятор Visual C++ говорит вам правильную вещь ... – Partial

+0

Вы можете написать на английском, что происходит, поэтому начните с myMatrix + i, напишите прозу о том, что происходит. Затем сделайте то же самое для первого «*», а затем второго. Где-то вы увидите, что то, что вы пытаетесь сделать, не имеет смысла, поэтому компилятор прав. –

+0

WOW люди СПАСИБО ВАМ ТАК ДЛЯ ВАШИХ ОТВЕТОВ !!!! (лук) – r1seUp

ответ

2

*(*(myMatrix+i)) неправ. Это распространенная ошибка.

2D-матрица не создает массив указателей, к которым вы можете получить доступ таким образом. Это другая структура. Несмотря на то, что массив является указателем, 2D-массив не является указателем на указатель, и он не может быть дважды заменен. У вас также нет другого доступа к элементу в координатах (x, y), не зная макета в памяти, потому что указатели на каждую строку нигде не найдены. Например, параметр char **argv параметра main() не является двумерным массивом. Это массив указателей на массивы, что является чем-то другим.

Есть два способа исправить это.

Один заменить

double *myMatrix = fromVector; 

по

double *myMatrix[100] = (appropriate cast)fromVector; 

и индексировать его как myMatrix[i/n][i%n]

Но помните, что 100 является константным выражением, и оно не может быть передан в качестве параметра. Кроме того, вы можете реализовать операцию Индексация себя:

  • Пасс дополнительный параметр: размер матрицы линии (100)
  • Вместо *(*(myMatrix+i)), написать:

    int row = i/n;
    int col = i%n;
    *(myMatrix+row*line_size+col) Ваш элемент ,

+0

«Даже если массив является указателем, 2D-массив не является указателем на указатель». Он должен: Если массив является указателем, массив 2d является указателем на указатель (поскольку массив 2d представляет собой массив массивов). Ошибка в том, что массив не является указателем: Затем массив 2d также не является указателем на указатель. Кроме того, двумерный массив * может * быть разыменован дважды - то есть '** matrix' вполне возможно. –

+0

Для второй «замещающей декларации» она должна выглядеть как «double (* myMatrix) [100] = (double (*) [100]) fromVector ;, но, как вы также заметили, 100 константа здесь. Таким образом, вы можете использовать предложенную арифметику, но это выглядит как более сложный способ сделать только «* (myMatrix + i)» (нет необходимости сначала получать строки и столбцы, просто чтобы добавить их позже), как это было предложено @partial и я. –

0

Я понятия не имею, почему вы копируете массивы дважды (один раз в параметрах функции и второй раз объявить некоторые новые массивы) ... Вы должны также думать о использовании STL ... станд :: вектор сделает вашу жизнь намного легче;)

double* negativeVector(double*nVector, double*fromVector, int m, int n){ 
    int position = 0; 

    double *myNegArray = nVector; 
    double *myMatrix = fromVector; 

    for(int i = 0; i < m*n; i++) 
     if(*((myMatrix+i)) < 0){ 
       *(myNegArray+position) = *((myMatrix+i)); 
       position++; 
     } 

    return myNegArray; 
} 
+0

Я считаю, что это не то, что они хотели. Они хотели индексировать квадрат размера m * n, а не первые m * n элементов верхней строки. –

+1

@Pavel, хорошо, если 'm' и' n' равны 100 соответственно (я подозреваю, что это размер строки и столбца?), То этот код будет правильно индексировать весь квадрат. –

1

Если вы передаете *matrix, вы фактически пропускание double[100] (массив из 100 дублей), что случается, передаются как указатель на его первый элемент. Если вы продвигаетесь дальше тех 100 удваиваний, используя i, добавленных к этому указателю, вы переходите к следующему массиву из 100 удвоений, так как 100 массивов из 100 двухместных номеров хранятся рядом друг с другом.

Background: Многомерный массив представляет собой массив, элемент которого сам по себе является массивом.Массив, подобный double a[100][100];, может быть объявлен эквивалентно typedef double aT[100]; aT a[100];. Если вы используете массив, похожий на указатель, временный указатель создается для первого элемента массива (который может быть массивом). Оператором * является такая операция, и в результате *a создает указатель типа double(*)[100] (который является указателем на массив из 100 удвоений) и разыгрывает его. Итак, что вы в итоге *matrix является double[100]. Передача его в функцию negativeVector создаст указатель на его первый элемент, который имеет тип double*.

Параметры указателя указывают на начало каждого из двух массивов по 100 удвоений каждый. Таким образом, вы должны переписать функцию

double* negativeVector(double*nVector, double*fromVector, int m, int n){ 
    int position = 0; 

    double *myNegArray = nVector; 
    double *myMatrix = fromVector; 

    for(int i = 0; i < m*n; i++) 
     if(*(myMatrix + i) < 0){ 
       *(myNegArray + position) = *(myMatrix + i); 
       position++; 
     } 

    return myNegArray; 
} 

Обратите внимание, что с вашей i итерации за пределами первого из 100 массивов, хранящихся в 2d массива, формально не быть правильным с этим. Но, как это бывает, эти массивы должны быть распределены рядом друг с другом, это будет работать на практике (и на самом деле рекомендуется как достаточно хорошая работа для передачи многомерных массивов вокруг, как указатели на их первый скалярный элемент).

1

сначала вы могли бы хотеть начать небольшой как-структуру

struct tmp { 
    bool negative; 
    double value; 
}; 

и сделать свой собственный путь до

tmp *myvars [100][100]; 

.
вместо этого попытаться использовать это структура и попробовать std::vectors вместо массивов, если это возможно, то попробуйте использовать указатели на decalring переменную «1 раз только» при объявлении переменной, как я сказал выше
затем передать аргументы

(tmp *mystructpointer) 
    mystructpointer->....... 

доступ к вашей матрице напрямую ... peice of take: D

+0

«Павел Радзивиловский» тоже прав. 2D-массивы отличаются от обычных аррис. на msdn (я думаю), но не могу найти правильную ссылку – VirusEcks

0

это домашнее задание? некоторые шаблоны - просто для удовольствия ;-)

double matrix[100][100]; 
double nVector[10000]; 

template< const int m, const int n > 
double* negativeVector(double* myNegArray, const double (&myMatrix)[m][n]) 
{ 
    int position = 0; 

    for(int i = 0; i < m; ++i) 
    { 
     for(int j = 0; j < n; ++j) 
     { 
      const double value = myMatrix[ i ][ j ]; 
      if (value < 0) 
      { 
       myNegArray[ position ] = value; 
       ++position; 
      } 
     } 
    } 

    return myNegArray; 
} 

int main() 
{ 
    //...initialize matrix here... 
    negativeVector(nVector, matrix); 
} 
0

Возможно, перепишите это с помощью std :: vector, чтобы увеличить читаемость? (#):

#include <vector> 
std::vector< std::vector<double> > matrix; //which is full with a matrix 3x4 
std::vector<double> row; 
row.resize(100,0); 
matrix.resize(100,row); 
std::vector<double> nVector; // for negative doubles, no size, we'll "push_back" 
//I wanted to see if there are negative doubles in each row and column 
//and I want this to happen with function 

Это СТЛ версия с поддержкой функции:

//I'm returning void because nvector contains the result, 
//so I don't feel the need to return anything. vectors contain their 
//own size so n and m are also not needed. Alsom pass in references 
void negativeVector(std::vector<double>& nVector, 
        std::vector< std::vector<double> >& fromVector){ 
    nVector.clear(); 
    int i,j; 
    for(i = 0; i < fromVector.size(); i++) { 
     for(j = 0; j < fromVector[i].size(); j++) { 
      if(fromVector[i][j] < 0){ 
       nVector.push_back(fromVector[i][j]); 
      } 
     } 
    } 
} 

вызов с:

negativeVector(nVector, matrix); 

После завершения функции, nVector содержит все отрицательные числа в матрице ,

Подробнее о std::vectorhere.

(#) для таких людей, как я, которые слишком ленивы/глупы, чтобы понять код, содержащий указатели.

0

Взгляните на сайт C++ Faq: Как назначить многомерные массивы с помощью новых?

link

И прочитал до точки [16,20] суммировать все ответы, которые вы получаете, и в конце концов вы получите очень полезный класс шаблона матрицы. Хорошо прочитайте.