How to transpose a matrix in C? - error
Asked Answered
G

2

7

I am trying to write a function to transpose matrices.

paramters of that function:

  • the matrix to transpose

  • the output matrix which is empty.

The problem is I am able to transpose some matrices but some other fail like the one i am giving in my example. WHy? how could I solve it?

code:

int main (void)
{

//this works well
/*  double array[3][2] = {{1,2},{3,4},{5,6}};
    height = 3;
    width = 2;
*/
//this input doesn't work

    double array[2][3] = {{1,2,3},{4,5,6}};
    height = 2;
    width = 3;


int heightOutput =  width; //2
int widthOutput = height; //3

    double **output;

    output = malloc(widthOutput * sizeof(double *)); //rows from 1
    for (i = 0; i < widthOutput; i++)
    {
        output[i] = malloc(heightOutput * sizeof(double)); //columns
    }

    transposeMatrix(&array[0][0], height,width, &output[0][0], heightOutput, widthOutput);

            printf("\n");
            printf("\noutput matrix\n");
    for(i=0;i<heightOutput;i++)
    {
        for(j=0;j<widthOutput;j++)
        {
            printf("%f\t",output[i][j]);
        }
        printf("\n");
    }
}



void transposeMatrix(double* array2, int height, int width, double * output, int height2, int width2)
{


    double workaround[3][3] ={0};
    double result;
    int i,j;

printf("input matrix:\n");


for(i=0;i<height;i++)
    {
        for(j=0;j<width;j++)
        {
                printf("%f\t",(*((array2+i*width)+j)));

        }
        printf("\n");
    }


        printf("\n");
    for(i=0;i<width2;i++)
    {
        for(j=0;j<height2;j++)
        {
            result = (*((array2+i*width)+j));
            workaround[i][j] = result;
        }
    }


    for(i=0;i<width2;i++)
    {
        for(j=0;j<height2;j++)
        {
            *((output+j*3)+i) = workaround[i][j];
            printf("%f\t",(*((output+j*3)+i)));
        }
        printf("\n");
    }


}
Grate answered 24/4, 2015 at 1:35 Comment(1)
When asking others to read your code, please use spaces. Like this: result = (*((array2 + i * width) + j)); Makes it easier for us.Fluctuate
D
3

The main problem is that you confused with sizes of matrices.

  1. When you fill workaround matrix your loop should be like this, since size of original matrix is (height x width).

    for(i=0;i<width;i++)
    {
        for(j=0;j<height;j++)
        {
            result = (*((array2+i*width)+j));
            workaround[i][j] = result;
        }
    }
    
  2. When transposing matrix

    for(i=0;i<height2;i++)
    {
        for(j=0;j<width2;j++)
        {
           *((output+i*width2)+j) = workaround[j][i];
           printf("%f\t",(*((output+i*width2)+j)));
        }
    }
    
  3. In memory allocation you also got wrong sizes, it should be

    output = malloc(heightOutput * sizeof(double *)); //rows from 1
    for (i = 0; i < heightOutput; i++)
    {
        output[i] = malloc(widthOutput * sizeof(double)); //columns
    }
    

    With this changes your program will run without errors, but output is still wil be wrong

    input matrix:                                                                                                                                                                    
    1.000000        2.000000        3.000000                                                                                                                                         
    4.000000        5.000000        6.000000                                                                                                                                         
    
    1.000000        2.000000        3.000000                                                                                                                                         
    4.000000        5.000000        6.000000                                                                                                                                         
    
    
    output matrix                                                                                                                                                                    
    1.000000        4.000000                                                                                                                                                         
    5.000000        0.000000                                                                                                                                                         
    0.000000        0.000000  
    
  4. The last problem is with argument passing. You dynamically allocate memory, pointers to rows first

    output = malloc(heightOutput * sizeof(double *)); //rows from 1
    

    With this you got array of pointers

    * -> NULL
    * -> NULL
    * -> NULL
    

    and with loop you assign values to them

    for (i = 0; i < heightOutput; i++)
    {
        output[i] = malloc(widthOutput * sizeof(double)); //columns
    }
    
    * -> [e00, e01]
    * -> [e10, e11]
    * -> [e20, e21]
    

    But there is no guarantee that they will be allocated one after another, still you operate with output like with linear allocated data. To correctly work with this you need to pass double pointer.

    void transposeMatrix(double* array2, int height, int width, double ** output, int height2, int width2)
    {
        ...
        for(i=0;i<width2;i++)
        {
            for(j=0;j<height2;j++)
            {
                output[j][i] = workaround[i][j];
                printf("%f\t",output[j][i]);
            }
            printf("\n");
        }
    }
    

    If you want to allocate memory linear do it like follows

    output = malloc(heightOutput * widthOutput * sizeof(double));
    

But to me all of it looks kind of complicated, simply it would looks like

void transposeMatrix(double* src, double* dst, int n, int m)
{
    int i, j;
    for(i = 0; i < n; ++i)
        for(j = 0; j < m; ++j)
            dst[j * n + i] = src[i * m + j];
}

int main(void)
{
    double array[2][3] = {{1,2,3},{4,5,6}};
    int height = 2;
    int width = 3;
    int i, j;

    double *output = malloc(height * width * sizeof(double));

    printf("input matrix\n");
    for(i=0;i<height;i++)
    {
        for(j=0;j<width;j++)
        {
            printf("%f\t",array[i][j]);
        }
        printf("\n");
    }

    transposeMatrix(&array[0][0], output, height,width);

    printf("output matrix\n");
    for(i=0;i<width;i++)
    {
        for(j=0;j<height;j++)
        {
            printf("%f\t",output[i*height + j]);
        }
        printf("\n");
    }
}

Edit: To answer to your comment: Let' say we have matrix 4 * 5

| a00 a01 a02 a03 a04 |
| a10 a11 a12 a13 a14 |
| a20 a21 a22 a23 a24 |
| a30 a31 a32 a33 a34 |

In memory allocated with

// n = 4, m = 5
double* A = malloc(n * m * sizeof(double));

it will look like

| a00 a01 a02 a03 a04 a10 a11 a12 a13 a14 a20 a21 a22 a23 a24 a30 a31 a32 a33 a34 |

So to get element let's say (2, 3) we need to skip 2 * 5 elements (it's two rows each of 5 elements) and 3 elements from the beginning of the third row, so - 13 elements to skip in array. And to generalize for matrix m * n to get (i, j) element we need to skip (i * m) + j elements in array.

Dimidiate answered 24/4, 2015 at 2:21 Comment(3)
Hello, thank you very much, this worked. Would it be possible to get some information about what this notation means/does output[i*height + j]Grate
@trilolil It's the same as *((output+i*height)+j)). When you allocate memory for matrix lineary as double* A = malloc(n*m*sizeof(double)) you can access (i, j) element with A[i*m+j].Dimidiate
But what I don't understand is why you need this multiplication?Grate
S
0
include stdio.h  
include conio.h 
include string.h
include stdlib.h

int main(){

    int i,j,n,t=0,a[100][100],k,l,b=0;

    printf(" n="); // you write the number or rows and columns or the matrix
    scanf("%d",&n);

    for(i=1;i<=n;i++){ //you write the elements of the matrix
        for(j=1;j<=n;j++){
            printf("a[%d][%d]=",i,j);
            scanf("%d",&a[i][j]);
        }
    }
    printf("\n");

    for(i=1;i<=n;i++){ //you can see you original matrix
        for(j=1;j<=n;j++){
            printf("%d ",a[i][j]);
        } 
        printf("\n");
    }
    printf("\n -\n");

    for (i=2; i<=n; i++) { //now we transpose the original matrix
        for (j=1; j < i; j++) {
            t = a[i][j];
            a[i][j] = a[j][i];
            a[j][i] = t;
            printf("\n da \n");
         }
   }

// now we can see the transpose of the matrix

// and compare it to the first one

printf("\n  \n ");

for(i=1;i<=n;i++){ 
    for(j=1;j<=n;j++){
        printf("%d ",a[i][j]);
    }
    printf("\n");
}
printf("\n  \n");

system("PAUSE");

return 0;
Sandbag answered 18/5, 2016 at 19:11 Comment(3)
Welcome to Stack Overflow. It's helpful to explain your solution in English as well as providing a code sample.Afterdamp
Welcome to SO and to expand upon @MattRaines's comment, please double check your code's formatting.Stationary
Thank you for your warm welcoming :)Sandbag

© 2022 - 2024 — McMap. All rights reserved.