Проблема с возвратом двумерного массива

Меня попросили написать программу, которая получает двумерный массив (матрицу), количество столбцов и количество строк, и программа будет возвращать транспонированную матрицу (без использования [][], то есть только с использованием арифметики указателя)

Программа, которую я написал, действительно транспонирует матрицу, это не проблема. Моя проблема заключается в том, чтобы понять, как вернуться. вот мой код:

int** transpose_matrix(matrix mat1,int number_of_rows,int number_of_columns)
{
    matrix mat2;
    int row_index,column_index;
    for(row_index=0;row_index<number_of_rows;row_index++)
    {
        for(column_index=0;column_index<number_of_columns;column_index++)
            **(mat2+(column_index*number_of_rows)+row_index)=**(mat1+(row_index*number_of_columns)+column_index);
    }
    // at this point, mat2 is exactly the transpose of mat1
    return mat2;
}

теперь вот моя проблема: я не могу вернуть матрицу, самое близкое, что я могу сделать, это вернуть адрес первого значения матрицы, но даже если я это сделаю, вся остальная матрица будет непригодна для использования, как только я выйти из функции transpose_matrix обратно в void main... Как я могу вернуть mat2?


person Oria Gruber    schedule 19.03.2013    source источник
comment
@nhahtdh malloc не выделяет место в стеке.   -  person Carey Gregory    schedule 20.03.2013
comment
@nhahtdh Это динамическая куча.   -  person squiguy    schedule 20.03.2013
comment
Подумайте о куче, но написанном стеке. #_#   -  person nhahtdh    schedule 20.03.2013


Ответы (2)


Во-первых, двумерный массив не является двойным указателем.

Во-вторых, динамическое размещение. Если matrix — тип двумерного массива, то напишите что-то вроде этого:

typedef int matrix[ROWS][COLUMNS];
typedef int (*matrix_ptr)[COLUMNS];

matrix_ptr transpose_matrix(matrix m, int rows, int cols)
{
    matrix_ptr transposed = malloc(sizeof(*transposed) * rows);
    // transpose, then
    return transposed;
}
person Community    schedule 19.03.2013
comment
@qPCR4vir Почему ты кричишь? - person ; 20.03.2013
comment
В любом случае, я хочу сделать вам +1, но я хочу увидеть // транспонирование, а затем сначала часть. - person qPCR4vir; 20.03.2013
comment
@ qPCR4vir Извините, но это не имеет значения. ОП уже написал код для транспонирования, он просто спрашивал способ вернуть всю матрицу. - person ; 20.03.2013
comment
@ qPCR4vir Почему бы и нет? - person ; 20.03.2013
comment
Может быть, я ошибаюсь, но '(transposed+i)' равно '((int)transposed+iCOLUMNS)' ?? - person qPCR4vir; 20.03.2013
comment
@ qPCR4vir То, что вы написали, является синтаксической ошибкой. transposed — это указатель на массив. - person ; 20.03.2013
comment
Да именно в этом проблема. Код OP предназначен для указателя на int, а не для указателя на массив COLUMNS int (для массива ROWS int может быть лучше?? он транспонирован). - person qPCR4vir; 20.03.2013
comment
Ребята, я действительно новичок во всем этом, вы можете объяснить мне, о чем спор? может быть, я смогу чему-то научиться. А также объясните код, который вы написали. Предположим, я тупой. (и код для моего транспонирования работает, проблема с возвратом) - person Oria Gruber; 20.03.2013
comment
Код @ qPCR4vir OP предполагает, что матрица представлена ​​​​в виде двумерного массива. Если вы не хотите вручную указывать уродливую индексацию, например ptr[rows * column + row], вы можете использовать указатель на массив и позволить компилятору безопасно выполнить индексацию за вас. Является ли указатель на int[ROWS] или на int[COLUMNS], полностью зависит от кода, который OP имеет до сих пор. - person ; 20.03.2013

ОК: Здесь у вас есть 3 вещи:

  1. Вы не можете вернуть указатель на локальную переменную (это будет мусор после возврата, а стек (память), где он был, используется повторно).
  2. Массив распадается на указатель на первый элемент при передаче.
  3. Арифметика указателя: p+1 увеличивает адрес в p на sizeof(*p), поэтому p указывает на следующий элемент, а не на следующий байт.

Простое исправление для вашего кода (это работает для любого размера матрицы):

    int* transpose_matrix(int *mat1,int number_of_rows,int number_of_columns)
    {
        int *mat2=malloc(number_of_rows*number_of_columns*sizeof(int));
        int row_index,column_index;
        for(row_index=0;row_index<number_of_rows;row_index++)
        {
            for(column_index=0;column_index<number_of_columns;column_index++)
                mat2[column_index*number_of_rows+row_index]=mat1[row_index*number_of_columns+column_index];
        }
        // at this point, mat2 is exactly the transpose of mat1
        return mat2;
    }

...
    print(m,r,c); // I hope you have a print()
    int *t=transpose_matrix(m,r,c);
    print (t,c,r);
...
    // use t[max: c-1][max: r-1]
    free(t);

Если у нас есть только матрица фиксированного размера (ну, с C99 мы также можем использовать массив переменной длины!).

typedef int  Matrix[ROWS][COLUMNS];
typedef int TMatrix[COLUMNS][ROWS];
typedef int (*pMatrix)[COLUMNS]; 
typedef int (*pTMatrix)[ROWS];  

pTMatrix transpose_matrix(Matrix m , int rows, int cols)
{
    pTMatrix t = malloc(sizeof(*t)*cols);
    for (int r=0; r<rows ; ++r)
    for (int c=0; r<cols ; ++r)
      t[c][r]=m[r][c];
    return t;
}

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

person qPCR4vir    schedule 19.03.2013
comment
Хорошо, кажется, это работает, но теперь у меня есть другая проблема, мне нужно напечатать транспонированную матрицу, но вы объявили m указателем на целое число, поэтому вы превратили массив 2d в массив 1d, как это сделать? Я печатаю транспонированную матрицу? - person Oria Gruber; 20.03.2013
comment
Используя уродливое индексирование, такое как ptr[rows * column + row], :-( - person qPCR4vir; 20.03.2013