2

I was doing the assignment to use pointer to transpose matrices. My code can successfully transpose the first row of the matrix but fail to transpose other rows and columns. I suspect there's some problems with for loops but I cannot find where the problem is. The following attached is my code.

void transposeMatrix(int matrix[ROWS][COLS]){
    int**  transpose=(int **)malloc(ROWS*sizeof(int*));
    for(int  i=0; i< ROWS; i++)
        transpose[i]=(int*)malloc(COLS*sizeof(int));

    for(int  i=0; i<ROWS;i++){
        puts("");
        for(int  j=0; j<COLS;j++){
            *(transpose+i*ROWS+j)= *(matrix+j*COLS+i);
            printf("%d ",transpose[j][i]);
        }
        puts("");
    }
}

The matrix generates random numbers and the problems looks like this:

Original Matrix:
10 20 30
40 50 60
70 80 90

Transpose Matrix:
10 0 43009213
20 3401401 910429
30 0 134910124

I cannot attach the image so the above is just an elaboration of the problem I faced, the real situation is not exactly like that but very similar.

Thank you for your help!

Barmar
  • 741,623
  • 53
  • 500
  • 612
inVoKer
  • 49
  • 1
  • 7
  • Curious, why did code use a `(int **)` cast in `int** transpose=(int **)malloc(ROWS*sizeof(int*));` and `(int*)` in `(int*)malloc(COLS*sizeof(int))`? – chux - Reinstate Monica Feb 28 '19 at 03:00
  • `*(transpose+i*ROWS+j)= *(matrix+j*COLS+i)` is assigning a pointer. Sure you want that? – chux - Reinstate Monica Feb 28 '19 at 03:03
  • @chux Are you trying to say [don't cast malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)? – Barmar Feb 28 '19 at 03:03
  • You're assigning to `transpose[i][j]`, but then you're printing `transpose[j][i]`. – Barmar Feb 28 '19 at 03:06
  • @Barmar I try to flip them around but the problem still exists. I don't understand where does those strange numbers come from and how to fix them. I'm really new to C language and pointer so I am very confused now. – inVoKer Feb 28 '19 at 03:11
  • @Barmar No. I am asking OP why code was written using casts. I am especially interested in what encourages learners to cast. I suspect OP will not answer now. – chux - Reinstate Monica Feb 28 '19 at 03:38
  • @chux You know we see casts of malloc all the time. They're just copying what they've seen elsewhere. Many instructors also teach this, I'm sure. Why? Who knows, it's just an idiom that keeps getting passed on. The people who write it don't know why, they're just doing what they learned. – Barmar Feb 28 '19 at 03:45
  • @chux And it's not like it's technically wrong, it's just a bad idea, like not putting braces around `if` blocks. The reasons why these are poor coding are not obvious to inexperienced programmers (and most instructors are not experienced programmers). – Barmar Feb 28 '19 at 03:46
  • @Barmar No news there - still lacking what OP thinks - from OP. My mistake for not leading the [question](https://stackoverflow.com/questions/54917715/transpose-matrix-using-pointer-in-c?noredirect=1#comment96601271_54917715) with "nVoKer". – chux - Reinstate Monica Feb 28 '19 at 03:58
  • @chux The OP doesn't "think" anything about this, and you know it. And asking the question isn't going to get him to rethink it. It's really NOT obvious why it's wrong, and I think you're being passive-aggressive asking that question. Just point him to the question that explains why it's a bad idea, and let it go. – Barmar Feb 28 '19 at 04:01
  • @chux And in general, I've found it totally pointless to ask newbies why they do things, even though it seems totally obvious why they're wrong. Like when they reinitialize the array that's collecting results inside the loop instead of before it, or put `else print "not found"` in a loop that's searching for something. I've tried numerous times asking what they were thinking, they just get annoyed at me. – Barmar Feb 28 '19 at 04:04
  • @Barmar My goal was not to lead OP to not casting or casting as that is P/A as with this [comment](https://stackoverflow.com/questions/54917715/transpose-matrix-using-pointer-in-c?noredirect=1#comment96601311_54917715) began. If I wanted to post what you suggested, I would have done so with my first comment. My question was exactly what is was - a query why OP did what OP did - nothing more. As you [commented](https://stackoverflow.com/questions/54917715/transpose-matrix-using-pointer-in-c?noredirect=1#comment96601848_54917715), OP's code is not technically wrong. – chux - Reinstate Monica Feb 28 '19 at 04:11
  • @Barmar My experience differs from you. I have found insight from OP's responses. – chux - Reinstate Monica Feb 28 '19 at 04:12
  • @chux BTW, your comment couold be interpreted as asking why he cast to `int**` as opposed to some other type, not why he cast at all. – Barmar Feb 28 '19 at 04:16

3 Answers3

0

*(transpose+i*ROWS+j) is not the correct way to access elements of an array of pointers. That's the way to access a 2-dimensional array that's stored contiguously in row-major order in an int[] array or through an int* pointer.

The way to access an element of a 2-dimensional array that's implemented as an array of pointers is with *(*(transpose + i)+j). *(transpose + i) returns the pointer to row i, adding j to that returns the address of the j'th column in the row, and deferencing that gets or sets the value.

This will also work with an array declared as

int matrix[ROWS][COLS];

because of the way arrays decay to pointers.

So your assignment line should be:

        *(*(transpose + i)+j) = *(*(matrix + j)+i);

Then you need to change the printf() line, because it's not printing the same element you just assigned. It should be:

        printf("%d ", transpose[i][j]);

The full working function is:

void transposeMatrix(int matrix[ROWS][COLS]){
    int**  transpose=(int **)malloc(ROWS*sizeof(int*));
    for(int  i=0; i< ROWS; i++)
        transpose[i]=(int*)malloc(COLS*sizeof(int));

    for(int  i=0; i<ROWS;i++){
        puts("");
        for(int  j=0; j<COLS;j++){
            *(*(transpose + i)+j) = *(*(matrix + j)+i);
            printf("%d ",transpose[i][j]);
        }
        puts("");
    }
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

You have problem with identifying memory location for row and col of each cells Here is the way using them:

i-th rows of transpose = *(transpose + i)
j-th col in i-th row of transpose  = *(*(transpose+i) + j)

Similar to matrix:

i-th rows of matrix= *(matrix + i)
j-th col in i-th row of matrix  = *(*(matrix+i) + j)

So here is my solution:

void transposeMatrix(int matrix[ROWS][COLS]) {
    int**  transpose = (int **)malloc(ROWS * sizeof(int*));
    for (int i = 0; i < ROWS; i++)
        transpose[i] = (int*)malloc(COLS * sizeof(int));

    for (int i = 0; i < ROWS; i++) {
        puts("");
        for (int j = 0; j < COLS; j++) {
            *(*(transpose + i) + j) = *(*(matrix + j) + i);
            printf("%d ", transpose[i][j]);
        }
        puts("");
    }
}
Loc Tran
  • 1,170
  • 7
  • 15
0

It's not necessary for you to allocate a new matrix row by row. Also, the functions that do the transpose and printing can be passed straight int * rather than preshaped arrays like int [3][2] etc.

It's even possible to reshape the matrix in place (i.e. without allocating new space). If you like I can post example code for that later.

For instance:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int M[2][3] = { {1, 2, 3}, {7, 8, 9} };
int N[3][3] = { {1, 2, 3}, { 4, 5, 6 }, {7, 8, 9} };


int *alloc_transpose(const int *matrix, size_t rows, size_t cols);
void print_matrix(const int *matrix, size_t rows, size_t cols);

int main()
{
    int *t_matrix;
    print_matrix(&M[0][0], 2, 3);
fprintf(stderr, "----\n");
    t_matrix = alloc_transpose(&M[0][0], 2, 3);
    if (t_matrix) {
        print_matrix(t_matrix, 3, 2);
    }
    free(t_matrix);
    t_matrix = alloc_transpose(&N[0][0], 3, 3);
    if (t_matrix) {
    fprintf(stderr, "----\n");
        print_matrix(t_matrix, 3, 3);
    }
    free(t_matrix);
    return 0;
}

void print_matrix(const int *matrix, size_t rows, size_t cols)
{
    size_t r, c;
    for (r = 0; r < rows; r++) {
        for (c = 0; c < cols; c++) {
            printf("%d ", *((matrix + r * cols) + c));
        }
        putchar('\n');
    }
}

int *alloc_transpose(const int *matrix, size_t rows, size_t cols)
{
    int *tm;
    int r, c;       /* relative to transposed matrix */

    tm = malloc(sizeof(int) * cols * rows); /* contiguous is okay */

    if (!tm)
        return NULL;

    for (r = 0; r < rows; r++) {
        for (c = 0; c < cols; c++) {
            *((tm + c * rows) + r) =
                          *((matrix + r * cols) + c);
        }
    }

    return tm;
}
Ahmed Masud
  • 21,655
  • 3
  • 33
  • 58