Передача переменной типа int [5] [5] в функцию, которая требует int ** - PullRequest
1 голос
/ 11 февраля 2009

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

Функция имеет подпись void generate_all_paths(int** maze, int size), а массив определен как int arr[5][5] = {REMOVED}.

Я не совсем уверен, как правильно привести массив для функции (или, если это невозможно).

Ответы [ 7 ]

6 голосов
/ 11 февраля 2009

Эта тема многомерного массива, к сожалению, сбивает с толку многих программистов на C ++. Ну, вот решение:

void generate_all_paths(int (*maze)[5], int size);

Вот так должно выглядеть объявление функции. Альтернатива, но полностью эквивалентная -

void generate_all_paths(int maze[][5], int size);

Оба создают параметр, который является указателем на массив из 5 целых чисел. Затем вы можете передать массив из 5 целых чисел в эту функцию:

generate_all_paths(arr, 5);

Поскольку первый элемент вашего массива представляет собой массив из 5 целых чисел, он будет автоматически (неявно) преобразован в указатель на этот первый элемент при передаче этой функции.

В комментариях вы показали, что привязаны к int**, потому что и ваше внутреннее, и внешнее измерение должны иметь значения времени выполнения. Многомерный массив больше не может использоваться. Что вы можете сделать для целей тестирования, так это создать массив указателей, таких как:

int store[5 * 5] = { ..... };
int *arr[5] = { store, store + 5, store + 10, store + 15, store + 20 };

Тогда, на самом деле, вы можете сделать так, чтобы ваша функция принимала int**. Поскольку первый элемент вашего массива - это int*, он будет автоматически преобразован в int**. Еще один способ сделать это - сохранить данные в двумерном массиве, а просто создать «представление», структурированное из указателей на этот массив:

int *arr[5] = { store[0], store[1], store[2], store[3], store[4] };

Где хранится ваш массив int[5][5]. Так как store[n] обращается к n-му подмассиву этого двумерного массива и его тип элемента равен int, его преобразованный указателем тип равен int*, который снова будет совместим.

3 голосов
/ 24 мая 2009

Вы можете написать:

void display(char **a)

А затем используйте a[i][j] для ссылки на элементы в нем.

Объявление char ** означает «указатель на указатель на целое число». Чтобы разбить его на шаги:

char *b = a[i];

Получает указатель на первый элемент i -ого массива в массиве массивов.

char c = b[j];

Это дает вам j '-ый элемент в массиве b.

Следующая проблема, с которой вы столкнетесь, - это размещение такого массива массивов.

char **arrayOfArrays = new char *[10];

for (int n = 0; n < 10; n++)
    arrayOfArrays[n] = new char[20];

Это выделяет массив из 10 массивов, каждый «дочерний» массив имеет 20 символов.

В C / C ++ синтаксис доступа к массиву - это просто способ получения значения на некотором расстоянии от указателя.

char *p = "Hello";

char *pl = p + 2;   // get pointer to middle 'l'
char l = *pl;       // fetch

char o = p[4];      // use array syntax instead
1 голос
/ 24 мая 2009

void display(char ** array) должно сработать. Также я не думаю, что это зарезервированное слово в стандарте C / C ++.

1 голос
/ 24 мая 2009

А также, почему массив является зарезервированным словом?

Это не так. Вы, вероятно, используете Visual Studio, где он отображается как ключевое слово из-за его использования в C ++ / CLI в качестве собственного управляемого типа. Однако это не имеет значения для C ++, и Visual Studio вводит в заблуждение в этом отношении.

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

void display(char** array) …

Тем не менее, ваша функция принимает фиксированную, известную длину массива и некоторые другие детали. Лучше было бы использовать вложенные std::vector или std::string (например). Использование таких существующих типов данных делает вашу жизнь намного проще.

void display(std::vector<std::string> const& array) {
    for (size_t i = 0; i < array.length(); ++i)
        cout << array[i] << endl;
}

Чтобы воспользоваться этим, необходимо изменить и ваш вызывающий код, чтобы использовать эти структуры данных вместо простых массивов C в char s.

0 голосов
/ 24 мая 2009

В ответе Уотикера отсутствует важный факт. Он предлагает массив массивов. Во-первых, это тратит память на массив указателей («char ** arrayOfArrays = new char * [10]» является точкой создания этого). Во-вторых, массив символов может не быть непрерывным блоком памяти, что часто является проблемой. Единственный обходной путь в C ++ - это создание одномерного массива и вычисление индексов, когда они вам нужны.

char *b = new char[width*height];

тогда вы можете обратиться к элементу x, y (x по ширине, y по высоте), как это

char c=b[width*y+x];

Это может быть, однако, немного медленнее, чем решение выше (измерено в GCC 3.4.5), поэтому, если вы не заинтересованы в непрерывной памяти (например, вы всегда получаете доступ к элементам с помощью [] [], никогда не добавляя целое на указатель и разыменование его), то вам следует использовать массив af массивов. Однако, если вы заинтересованы иметь непрерывную память, например, чтобы передать его в качестве инициализатора объекту std :: string или отправить целиком через сеть, вам следует использовать второй.

0 голосов
/ 24 мая 2009

Лучше всего использовать указатели, но Borland C ++ допускает передачу массивов в качестве параметров для функций. Посмотрите на этот код (включает в себя: iostream и conio):

////////////////////////////////////////////

void ReceivedArray(char x[5]){

for (int i=0; i<5; i++ )
cout << x[i];

}

void main(){

char *x = new char[5];

for (int i=0; i<5; i++ )
x[i]='o';

ReceivedArray(x);
getchar();
}


///////////////////////////////////////////////////////////////


For passing 2D arrays (oops! some lines in spanish, sorry!):

(includes: iostream, stdlb, stdio and math)


/////////////////////////////////////////////////

using namespace std;

void ver(int x[][20]){
for(int i=0; i<15; i++)  {
  for(int j=0; j<20; j++) {
   cout<< x[i][j] <<" ";       }
   cout << "\n";        }

}

void cambiar0(int x[][20]){ int n[255];
   for (int i=255; i>=0; i--)
    n[255-i]=i;


for(int i=0; i<15; i++)
  for(int j=0; j<20; j++)
      for(int k=0; k<255; k++)
       if(x[i][j]==n[k])  {
          x[i][j]=k; break;  }  
}

int main(int argc, char* argv[]){
int x[15][20]; char a; 

for(int i=0; i<15; i++)
  for(int j=0; j<20; j++)
   x[i][j]=rand()%255;

  cout << "¿desea ver la matriz? s/n ";
 cin >> a;
 if(a=='s') ver(x);

 cambiar0(x);

 cout << "\n\n";
 cout << "¿desea ver la matriz? s/n ";
 cin >> a;
 if(a=='s') ver(x);

system("PAUSE"); return 0;
}

///////////////////////////////////

Надеюсь, это то, что вы имели в виду.

0 голосов
/ 11 февраля 2009

arr - указатель на имеющийся у вас многомерный массив и фактически указатель на int. Теперь, поскольку ваша функция принимает указатель на указатель int, вам нужно получить адрес arr, используя: &arr и передать его функции, чтобы у вас был следующий код:

Для приведения массива: Передайте &arr в функцию. Для ссылки на массив внутри функции: *maze[x][y]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...